Skip to content

Commit 166330c

Browse files
authored
Merge branch 'dev' into feat/stop-macro-evaluation
2 parents 397a7df + e53c837 commit 166330c

File tree

605 files changed

+6053
-1351
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

605 files changed

+6053
-1351
lines changed

.github/generate_cppcheck_report.py

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import sys
2+
3+
UPDATED_FILES = sys.argv[1:]
4+
TABLE_HEADER = """| Filename | Line | Type | Description |
5+
| -------- | ---- | ---- | ----------- |"""
6+
7+
with open("cppcheck.txt") as f:
8+
content = f.readlines()
9+
10+
updated = []
11+
anything_else = []
12+
13+
for line in content:
14+
filename, row, kind, desc = line.split(":", 3)
15+
formatted = f"| {filename} | {row} | {kind.strip()} | {desc.strip()} |"
16+
17+
if filename == "nofile":
18+
continue
19+
20+
if filename in UPDATED_FILES:
21+
updated.append(formatted)
22+
else:
23+
anything_else.append(formatted)
24+
25+
26+
def make_output(data):
27+
if data:
28+
output = TABLE_HEADER + "\n"
29+
output += "\n".join(data)
30+
return output
31+
return ""
32+
33+
34+
print(f"""### CppCheck report
35+
36+
{make_output(updated)}
37+
38+
<details>
39+
<summary>Report files about files you didn't modify in this PR</summary>
40+
41+
{make_output(anything_else)}
42+
</details>
43+
""")

.github/launch-lizard.py

+6-6
Original file line numberDiff line numberDiff line change
@@ -32,22 +32,22 @@
3232

3333

3434
def make_sorted_table_lines(lines_with_ccn):
35-
output = ""
36-
for line in sorted(lines_with_ccn, key=lambda e: e[1], reverse=True):
37-
output += f"| {line[0]} | {line[1]} |\n"
38-
return output
35+
if lines_with_ccn:
36+
output = TABLE_HEADERS + "\n"
37+
for line in sorted(lines_with_ccn, key=lambda e: e[1], reverse=True):
38+
output += f"| {line[0]} | {line[1]} |\n"
39+
return output
40+
return ""
3941

4042

4143
print(f"""### Lizard report
4244
4345
Listing only functions with cyclomatic complexity >= {MAX_CCN} or NLOC >= {MAX_NLOC} or parameters >= {MAX_PARAM}.
44-
{TABLE_HEADERS}
4546
{make_sorted_table_lines(updated)}
4647
4748
<details>
4849
<summary>Report about files you didn't modify in this PR</summary>
4950
50-
{TABLE_HEADERS}
5151
{make_sorted_table_lines(anything_else)}
5252
</details>
5353
""")

.github/workflows/ci.yml

+27-4
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ jobs:
7070
config:
7171
- {
7272
os: ubuntu-24.04, name: "Ubuntu Clang 16",
73-
compiler: clang, compiler_version: 16, sanitizers: "Off",
73+
compiler: clang, compiler_version: 16, sanitizers: "On",
7474
artifact: "ubuntu-clang-16"
7575
}
7676
- {
@@ -80,7 +80,7 @@ jobs:
8080
}
8181
- {
8282
os: ubuntu-24.04, name: "Ubuntu GCC 14",
83-
compiler: gcc, compiler_version: 14, sanitizers: "Off",
83+
compiler: gcc, compiler_version: 14, sanitizers: "On",
8484
artifact: "ubuntu-gcc-14"
8585
}
8686
- {
@@ -201,6 +201,7 @@ jobs:
201201
fuzzing:
202202
runs-on: ubuntu-24.04
203203
name: Fuzz testing
204+
continue-on-error: true
204205

205206
container:
206207
image: aflplusplus/aflplusplus:v4.20c
@@ -242,9 +243,31 @@ jobs:
242243
-- ${BUILD_FOLDER}/arkscript @@ -L ./lib
243244
244245
- name: Summarize
246+
id: summary
247+
shell: bash
245248
run: |
246-
afl-whatsup -s -d output
247-
afl-showmap -C -i output -o /dev/null -- ./${BUILD_FOLDER}/arkscript @@ -L ./lib
249+
echo "FUZZ_SUMMARY<<EOF" >> $GITHUB_ENV
250+
afl-whatsup -s -d output >> $GITHUB_ENV
251+
afl-showmap -C -i output -o /dev/null -- ./${BUILD_FOLDER}/arkscript @@ -L ./lib | sed -r "s/\x1B\[([0-9]{1,3}(;[0-9]{1,2};?)?)?[mGK]//g" | grep -v Reading | grep -v Scanning >> $GITHUB_ENV
252+
echo "EOF" >> $GITHUB_ENV
253+
254+
- name: Find Comment
255+
uses: peter-evans/find-comment@v3
256+
id: fc
257+
with:
258+
issue-number: ${{ github.event.pull_request.number }}
259+
comment-author: 'github-actions[bot]'
260+
body-includes: Fuzzing report
261+
262+
- name: Create or update comment
263+
uses: peter-evans/create-or-update-comment@v4
264+
with:
265+
comment-id: ${{ steps.fc.outputs.comment-id }}
266+
issue-number: ${{ github.event.pull_request.number }}
267+
body: |
268+
## Fuzzing report
269+
${{ env.FUZZ_SUMMARY }}
270+
edit-mode: replace
248271

249272
- name: Sort files for upload
250273
continue-on-error: true

.github/workflows/release.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ jobs:
2626
- {
2727
os: ubuntu-24.04, name: "Ubuntu GCC 14",
2828
compiler: gcc, compiler_version: 14,
29-
artifact: "ubuntu-gcc-13"
29+
artifact: "ubuntu-gcc-14"
3030
}
3131
- {
3232
os: windows-latest, name: "Windows VS 2022",

.github/workflows/static_analysis.yml

+2-5
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,9 @@ jobs:
3737
-I include src \
3838
--enable=all --inline-suppr \
3939
--suppressions-list=cppcheck-suppressions.txt
40-
cat cppcheck.txt | sort > cppcheck_sorted.txt
40+
content=$(python .github/generate_cppcheck_report.py $(echo $(git diff --name-only -r HEAD^1 HEAD)))
4141
echo "CPPCHECK_REPORT<<EOF" >> $GITHUB_ENV
42-
echo "| Filename | Line | Type | Description |" >> $GITHUB_ENV
43-
echo "| -------- | ---- | ---- | ----------- |" >> $GITHUB_ENV
44-
cat cppcheck_sorted.txt | awk -F ":" '{type=$3;out=""; for (i = 4; i <= NF; i++) {out = out " " $i}; print $1 " | " $2 " |" type " |" out}' >> $GITHUB_ENV
42+
echo "$content" >> $GITHUB_ENV
4543
echo "EOF" >> $GITHUB_ENV
4644
4745
- name: Find Comment
@@ -63,6 +61,5 @@ jobs:
6361
6462
---
6563
66-
### CppCheck report
6764
${{ env.CPPCHECK_REPORT }}
6865
edit-mode: replace

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
# Personal utilities
66
warnings.log
7+
cppcheck.txt
78

89
# ArkScript
910
__arkscript__/

CHANGELOG.md

+10
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,16 @@
5353
- fixed a bug when passing the wrong number of arguments to a function inside an async call was crashing the VM because the function couldn't be named
5454
- fixed a bug in the compiler generating invalid `fun` nodes
5555
- fixed a bug when generating `let`, `mut` or `set` nodes inside macros with an invalid node type
56+
- fixed a bug when reading invalid UTF8 codepoints in the parser caused out of bounds reads
57+
- fixed a bug with recursive macro, exhausting the stack space due to recursive evaluation
58+
- futures can be awaited again, they will return nil on all the tries
59+
- checking for reused argument name in macros during parsing
60+
- enhanced comment after node handling in macros
61+
- adding a hard limit on package names length (255 characters, to comply with posix limits)
62+
- disallow passing invalid nodes as arguments to functions and operators
63+
- checking for unevaluated spread inside macros
64+
- checking for invalid symbols when defining a function through a macro
65+
- added a max macro unification depth
5666

5767
### Removed
5868
- removed unused `NodeType::Closure`

CMakeLists.txt

+14-19
Original file line numberDiff line numberDiff line change
@@ -48,18 +48,18 @@ if (CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_CLANG OR APPLE)
4848
target_compile_options(ArkReactor
4949
PUBLIC
5050
-Wall -Wextra -pedantic -Wstrict-aliasing
51-
-Wno-unknown-pragmas # We use pragmas to disable warnings we understand.
51+
-Wshadow
52+
-Wconversion
53+
-Werror
54+
# Allow deprecation warnings to not be treated as errors
55+
-Wno-error=deprecated-declarations
56+
# We use pragmas to disable warnings we understand.
5257
# So we need to disable the warning about pragmas.
53-
-Wno-unknown-warning-option # Disable warnings about disabling warnings we have
54-
# disabled.
58+
-Wno-unknown-pragmas
59+
# Disable warnings about disabling warnings we have disabled.
60+
-Wno-unknown-warning-option
5561
)
5662

57-
if (CMAKE_COMPILER_IS_GNUCXX)
58-
# The package utf8 has an issue with constant overflow.
59-
# Once this is fixed remove this flag:
60-
target_compile_options(ArkReactor PUBLIC -Wno-overflow)
61-
endif ()
62-
6363
if (APPLE)
6464
# The standard SSH libraries are depreciate on APPLE.
6565
# Thus they currently generate a warning that we have to ignore for now.
@@ -105,7 +105,7 @@ add_subdirectory("${ark_SOURCE_DIR}/lib/termcolor" EXCLUDE_FROM_ALL)
105105
target_link_libraries(ArkReactor PUBLIC termcolor)
106106

107107
target_include_directories(ArkReactor
108-
PUBLIC
108+
SYSTEM PUBLIC
109109
"${ark_SOURCE_DIR}/lib/picosha2/"
110110
"${ark_SOURCE_DIR}/lib/fmt/include")
111111

@@ -161,7 +161,10 @@ if (ARK_PROFILER_MIPS)
161161
endif ()
162162

163163
if (ARK_BUILD_MODULES)
164+
get_directory_property(old_dir_compile_options COMPILE_OPTIONS)
165+
add_compile_options(-w)
164166
add_subdirectory(${ark_SOURCE_DIR}/lib/modules)
167+
set_directory_properties(PROPERTIES COMPILE_OPTIONS "${old_dir_compile_options}")
165168
endif ()
166169

167170
# TODO: consider using ctest
@@ -201,18 +204,10 @@ if (ARK_BUILD_EXE)
201204
${ark_SOURCE_DIR}/lib/fmt/src/format.cc)
202205
add_executable(arkscript ${EXE_SOURCES})
203206

204-
if (MSVC)
205-
# Disable warnings for lib/replxx
206-
# This is a separate module we don't control so can't fix the code without help.
207-
# Disable warnings when compiling this package remove when resolved.
208-
# /wd4267: conversion from 'size_t' to 'type', possible loss of data
209-
# /wd4244: conversion from 'type1' to 'type2', possible loss of data
210-
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4267 /wd4244")
211-
endif ()
212-
213207
add_subdirectory("${ark_SOURCE_DIR}/lib/replxx" EXCLUDE_FROM_ALL)
214208
add_subdirectory("${ark_SOURCE_DIR}/lib/clipp" EXCLUDE_FROM_ALL)
215209

210+
target_include_directories(arkscript SYSTEM PUBLIC "${ark_SOURCE_DIR}/lib/clipp/include")
216211
target_link_libraries(arkscript PUBLIC ArkReactor replxx clipp termcolor)
217212
target_compile_features(arkscript PRIVATE cxx_std_20)
218213

examples/quicksort.ark

+2-1
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,12 @@
3131
# an unsorted list to sort
3232
(let a [3 6 1 5 1 65 324 765 1 6 3 0 6 9 6 5 3 2 5 6 7 64 645 7 345 432 432 4 324 23])
3333

34+
(let rep (if (>= (len sys:args) 1) (toNumber (@ sys:args 0)) 1))
35+
3436
# a benchmarking function, to see the difference between C++ sort and ArkScript quicksort
3537
# obviously ArkScript will be a bit slower
3638
(let bench (fun (name code) {
3739
(mut start (time))
38-
(let rep 1000)
3940

4041
(mut i 0)
4142
(while (< i rep) {

include/Ark/Compiler/AST/Optimizer.hpp

+7-6
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22
* @file Optimizer.hpp
33
* @author Alexandre Plateau ([email protected])
44
* @brief Optimizes a given ArkScript AST
5-
* @version 0.4
6-
* @date 2020-10-27
5+
* @version 1.0
6+
* @date 2024-07-09
77
*
8-
* @copyright Copyright (c) 2020-2021
8+
* @copyright Copyright (c) 2020-2024
99
*
1010
*/
1111

@@ -32,8 +32,9 @@ namespace Ark::internal
3232
/**
3333
* @brief Construct a new Optimizer
3434
*
35+
* @param debug level of debug
3536
*/
36-
explicit Optimizer(uint16_t options) noexcept;
37+
explicit Optimizer(unsigned debug) noexcept;
3738

3839
/**
3940
* @brief Send the AST to the optimizer, then run the different optimization strategies on it
@@ -51,7 +52,7 @@ namespace Ark::internal
5152

5253
private:
5354
Node m_ast;
54-
uint16_t m_options;
55+
unsigned m_debug;
5556
std::unordered_map<std::string, unsigned> m_sym_appearances;
5657

5758
/**
@@ -74,7 +75,7 @@ namespace Ark::internal
7475
* @param node
7576
* @param func
7677
*/
77-
void runOnGlobalScopeVars(Node& node, const std::function<void(Node&, Node&, int)>& func);
78+
void runOnGlobalScopeVars(Node& node, const std::function<void(Node&, Node&, std::size_t)>& func);
7879

7980
/**
8081
* @brief Count the occurrences of each symbol in the AST, recursively

include/Ark/Compiler/AST/Parser.hpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -174,13 +174,13 @@ namespace Ark::internal
174174

175175
std::optional<Node> field()
176176
{
177-
std::string symbol;
178-
if (!name(&symbol))
177+
std::string sym;
178+
if (!name(&sym))
179179
return std::nullopt;
180180

181181
std::optional<Node> leaf { Node(NodeType::Field) };
182182
setNodePosAndFilename(leaf.value());
183-
leaf->push_back(Node(NodeType::Symbol, symbol));
183+
leaf->push_back(Node(NodeType::Symbol, sym));
184184

185185
while (true)
186186
{

include/Ark/Compiler/AST/Predicates.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ namespace Ark::internal
114114
explicit IsChar(const char c) :
115115
CharPred("'" + std::string(1, c) + "'"), m_k(c)
116116
{}
117-
explicit IsChar(const utf8_char_t c) :
117+
explicit IsChar(const utf8_char_t& c) :
118118
CharPred(std::string(c.c_str())), m_k(c.codepoint())
119119
{}
120120
bool operator()(const utf8_char_t::codepoint_t c) const override

include/Ark/Compiler/AST/utf8_char.hpp

+16-7
Original file line numberDiff line numberDiff line change
@@ -23,44 +23,53 @@ namespace Ark::internal
2323
m_codepoint(cp), m_length(len), m_repr(repr) {}
2424

2525
// https://github.com/sheredom/utf8.h/blob/4e4d828174c35e4564c31a9e35580c299c69a063/utf8.h#L1178
26-
static std::pair<std::string::iterator, utf8_char_t> at(std::string::iterator it)
26+
static std::pair<std::string::iterator, utf8_char_t> at(std::string::iterator it, const std::string::iterator end)
2727
{
28-
codepoint_t codepoint;
28+
codepoint_t cp;
2929
length_t length;
3030
repr_t repr = {};
3131

3232
if (0xf0 == (0xf8 & *it)) // 4 byte utf8 codepoint
3333
{
34-
codepoint = (static_cast<codepoint_t>(0x07 & *it) << 18) |
34+
if (it + 3 == end || it + 2 == end || it + 1 == end)
35+
return std::make_pair(end, utf8_char_t {});
36+
37+
cp = (static_cast<codepoint_t>(0x07 & *it) << 18) |
3538
(static_cast<codepoint_t>(0x3f & *(it + 1)) << 12) |
3639
(static_cast<codepoint_t>(0x3f & *(it + 2)) << 6) |
3740
static_cast<codepoint_t>(0x3f & *(it + 3));
3841
length = 4;
3942
}
4043
else if (0xe0 == (0xf0 & *it)) // 3 byte utf8 codepoint
4144
{
42-
codepoint = (static_cast<codepoint_t>(0x0f & *it) << 12) |
45+
if (it + 2 == end || it + 1 == end)
46+
return std::make_pair(end, utf8_char_t {});
47+
48+
cp = (static_cast<codepoint_t>(0x0f & *it) << 12) |
4349
(static_cast<codepoint_t>(0x3f & *(it + 1)) << 6) |
4450
static_cast<codepoint_t>(0x3f & *(it + 2));
4551
length = 3;
4652
}
4753
else if (0xc0 == (0xe0 & *it)) // 2 byte utf8 codepoint
4854
{
49-
codepoint = (static_cast<codepoint_t>(0x1f & *it) << 6) |
55+
if (it + 1 == end)
56+
return std::make_pair(end, utf8_char_t {});
57+
58+
cp = (static_cast<codepoint_t>(0x1f & *it) << 6) |
5059
static_cast<codepoint_t>(0x3f & *(it + 1));
5160
length = 2;
5261
}
5362
else // 1 byte utf8 codepoint otherwise
5463
{
55-
codepoint = static_cast<unsigned char>(*it);
64+
cp = static_cast<unsigned char>(*it);
5665
length = 1;
5766
}
5867

5968
for (length_t i = 0; i < length; ++i)
6069
repr[i] = static_cast<unsigned char>(*(it + static_cast<int>(i)));
6170

6271
return std::make_pair(it + static_cast<long>(length),
63-
utf8_char_t(codepoint, length, repr));
72+
utf8_char_t(cp, length, repr));
6473
}
6574

6675
[[nodiscard]] bool isPrintable() const

0 commit comments

Comments
 (0)