Skip to content
This repository was archived by the owner on Oct 10, 2025. It is now read-only.

Commit 117d8f9

Browse files
Setup Fuzzing With A Basic Harness (#34)
Still incomplete, not all components are fuzzed, but still this PR contains some important fixes, so it's better to merge it soon. * Setup Fuzzing With A Basic Harness * Fix Script Path * Fix Include For Windows * Update Dockerfile.fuzz * Update Dockerfile.fuzz * Update fuzz.yml * Update Dockerfile.fuzz * Fuzz Dont Care About CoreDumps * Fuzz Only With ASAN * Docker Dont Ignore Tests Directory * Fix Perms * Try Again * Try Again * Try A Fix Again * Cleanups
1 parent d12169d commit 117d8f9

Some content is hidden

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

74 files changed

+4602
-552
lines changed

.dockerignore

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# Exclude build artifacts and outputs from Docker build context
2+
Build/
3+
fuzz-outputs/
4+
*.o
5+
*.a
6+
*.so
7+
*.dylib
8+
*.exe
9+
*.dll
10+
11+
# Exclude test outputs and logs
12+
meson-logs/
13+
meson-info/
14+
meson-private/
15+
meson-uninstalled/
16+
17+
# Exclude documentation build artifacts
18+
Docs/
19+
*.md
20+
LICENSE*
21+
22+
# Exclude CI/CD files
23+
.github/
24+
.git/
25+
.gitignore
26+
27+
# Exclude editor and IDE files
28+
.vscode/
29+
.idea/
30+
*.swp
31+
*.swo
32+
*~
33+
34+
# Exclude temporary files
35+
*.tmp
36+
*.temp
37+
*.log

.github/workflows/fuzz.yml

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
name: AFL++ Fuzzing
2+
3+
on:
4+
push:
5+
branches: [ master, develop ]
6+
pull_request:
7+
branches: [ master ]
8+
schedule:
9+
# Run fuzzing daily at 2 AM UTC
10+
- cron: '0 2 * * *'
11+
workflow_dispatch:
12+
13+
jobs:
14+
fuzz:
15+
runs-on: ubuntu-latest
16+
timeout-minutes: 60
17+
18+
steps:
19+
- name: Checkout code
20+
uses: actions/checkout@v4
21+
22+
- name: Set up Docker Buildx
23+
uses: docker/setup-buildx-action@v3
24+
25+
- name: Make fuzz-docker.sh executable
26+
run: chmod +x Scripts/fuzz-docker.sh
27+
28+
- name: Clean up previous fuzzing outputs
29+
run: |
30+
# Clean up any previous fuzzing outputs to avoid conflicts
31+
rm -rf fuzz-outputs/*
32+
echo "Cleaned up previous fuzzing outputs"
33+
34+
- name: Run AFL++ fuzzing (with ASAN)
35+
run: |
36+
timeout 30m ./Scripts/fuzz-docker.sh || true
37+
38+
- name: Fix permissions for artifact upload
39+
run: |
40+
# Fix ownership and permissions for fuzz outputs
41+
if [ -d "fuzz-outputs" ]; then
42+
# Change ownership to runner user
43+
sudo chown -R runner:runner fuzz-outputs/
44+
# Ensure proper permissions
45+
chmod -R 755 fuzz-outputs/
46+
# List contents to verify
47+
echo "Fixed permissions for fuzz-outputs directory:"
48+
ls -la fuzz-outputs/
49+
# Check for new fuzzer directory structure
50+
if [ -d "fuzz-outputs/fuzzer-asan" ]; then
51+
echo "Contents of fuzz-outputs/fuzzer-asan:"
52+
ls -la fuzz-outputs/fuzzer-asan/
53+
fi
54+
# Check for legacy directory structure
55+
if [ -d "fuzz-outputs/default" ]; then
56+
echo "Contents of fuzz-outputs/default:"
57+
ls -la fuzz-outputs/default/
58+
fi
59+
else
60+
echo "No fuzz-outputs directory found"
61+
fi
62+
63+
- name: Rename files with invalid characters for artifact upload
64+
run: |
65+
# Function to rename files with invalid characters
66+
rename_files() {
67+
local dir="$1"
68+
if [ -d "$dir" ]; then
69+
echo "Renaming files in $dir to remove invalid characters..."
70+
find "$dir" -type f -name "*:*" -o -name "*\"*" -o -name "*<*" -o -name "*>*" -o -name "*|*" -o -name "*\**" -o -name "*\?*" | while read -r file; do
71+
# Get directory and filename
72+
dirname=$(dirname "$file")
73+
filename=$(basename "$file")
74+
# Replace invalid characters with underscores
75+
new_filename=$(echo "$filename" | sed 's/[:<>|*"?]/_/g')
76+
# Only rename if the filename actually changed
77+
if [ "$filename" != "$new_filename" ]; then
78+
new_path="$dirname/$new_filename"
79+
echo "Renaming: $file -> $new_path"
80+
mv "$file" "$new_path"
81+
fi
82+
done
83+
fi
84+
}
85+
86+
# Rename files in fuzzing output directories
87+
if [ -d "fuzz-outputs" ]; then
88+
rename_files "fuzz-outputs/fuzzer-asan"
89+
rename_files "fuzz-outputs/default"
90+
echo "File renaming completed"
91+
else
92+
echo "No fuzz-outputs directory found for renaming"
93+
fi
94+
95+
- name: Check for crashes
96+
run: |
97+
echo "Checking for crashes in fuzzing results..."
98+
99+
# Check AFL++ with ASAN results (using new fuzzer directory name)
100+
if [ -d "fuzz-outputs/fuzzer-asan/crashes" ] && [ "$(ls -A fuzz-outputs/fuzzer-asan/crashes)" ]; then
101+
echo "❌ Crashes found in AFL++ with ASAN:"
102+
ls -la fuzz-outputs/fuzzer-asan/crashes/
103+
exit 1
104+
elif [ -d "fuzz-outputs/default/crashes" ] && [ "$(ls -A fuzz-outputs/default/crashes)" ]; then
105+
echo "❌ Crashes found in AFL++ with ASAN (legacy directory):"
106+
ls -la fuzz-outputs/default/crashes/
107+
exit 1
108+
else
109+
echo "✅ No crashes found in AFL++ with ASAN"
110+
fi
111+
112+
- name: Upload fuzzing results
113+
uses: actions/upload-artifact@v4
114+
if: always()
115+
with:
116+
name: fuzzing-results
117+
path: fuzz-outputs/
118+
retention-days: 7

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,5 @@ Docs/
1010
Docs/public
1111
.DS_Store
1212
.venv
13+
fuzz-outputs
14+
Fuzz/outputs/

Bin/ElfInfo.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -331,12 +331,12 @@ typedef struct {
331331
"{>2r}" /* shnum */ \
332332
"{>2r}" /* shstrndx */
333333

334-
int main(int argc, char** argv) {
334+
int main(int argc, char **argv) {
335335
if (argc < 2) {
336336
LOG_FATAL("USAGE: {} {}", argv[0], argv[1]);
337337
}
338338

339-
FILE* elf = fopen(argv[1], "rb");
339+
FILE *elf = fopen(argv[1], "rb");
340340
if (!elf) {
341341
LOG_ERROR("Failed to open file for reading.");
342342
return 1;

Bin/MisraDoc.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ typedef struct Project {
2424
Strs test_directories;
2525
} Project;
2626

27-
void ProjectDeinit(Project* p) {
27+
void ProjectDeinit(Project *p) {
2828
if (!p) {
2929
LOG_ERROR("Invalid project object. Invalid arguments");
3030
abort();
@@ -94,15 +94,15 @@ void ProjectDeinit(Project* p) {
9494
obj_deinit(__o_b_j); \
9595
} while (0)
9696

97-
int main(int argc, char** argv) {
97+
int main(int argc, char **argv) {
9898
if (argc != 2) {
9999
FWriteFmtLn(stderr, "USAGE : {} config.json", argc == 0 ? "MisraDoc" : argv[0]);
100100
return 1;
101101
}
102102

103103
LogInit(false);
104104

105-
const char* config_path = argv[1];
105+
const char *config_path = argv[1];
106106

107107
Project project = {0};
108108
Scope(&project, ProjectDeinit, {
@@ -180,7 +180,7 @@ VecForeach(&file_paths, file_path) {
180180
Str md_code = StrInit();
181181
Scope(&md_code, StrDeinit, {
182182
// Create template strings for StrWriteFmt with escaped braces
183-
const char* mdHeader =
183+
const char *mdHeader =
184184
"---\n"
185185
"title: \"{}\"\n"
186186
"meta_title: \"{}\"\n"
@@ -209,7 +209,7 @@ VecForeach(&file_paths, file_path) {
209209

210210

211211
// dump code to output path
212-
FILE* f = fopen(output_path.data, "w");
212+
FILE *f = fopen(output_path.data, "w");
213213
Scope(f, fclose, { fwrite(md_code.data, 1, md_code.length, f); });
214214
});
215215
});

Bin/MisraEnum.c

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -32,16 +32,16 @@ typedef struct EnumEntry {
3232

3333
typedef Vec(EnumEntry) EnumEntries;
3434

35-
int main(int argc, char** argv) {
35+
int main(int argc, char **argv) {
3636
LogInit(false);
3737

3838
if (argc < 2 || argc > 3) {
3939
FWriteFmtLn(stderr, "USAGE : {} <enum-json-spec> [output-file-name]", argc == 0 ? "MisraEnum" : argv[0]);
4040
return 1;
4141
}
4242

43-
const char* input_filename = argv[1];
44-
const char* output_filename = NULL;
43+
const char *input_filename = argv[1];
44+
const char *output_filename = NULL;
4545
if (argc == 3) {
4646
output_filename = argv[3];
4747
}
@@ -126,7 +126,7 @@ int main(int argc, char** argv) {
126126

127127
if (to_from_str) {
128128
// Store string literals in temporary variables
129-
const char* funcHeader =
129+
const char *funcHeader =
130130
"///\n"
131131
"/// Converts given zero-terminated string to {} enum value.\n"
132132
"///\n"
@@ -142,7 +142,7 @@ int main(int argc, char** argv) {
142142
" }}\n";
143143

144144
// Prepare the return value for invalid enum
145-
const char* invalidEnumName = "0";
145+
const char *invalidEnumName = "0";
146146
if (invalid_enum.name.length) {
147147
invalidEnumName = invalid_enum.name.data;
148148
}
@@ -151,16 +151,16 @@ int main(int argc, char** argv) {
151151

152152
// Use VecForeach for iterating over entries
153153
VecForeach(&entries, e) {
154-
const char* compareTemplate = " if(ZstrCompareN(\"{}\", zstr, {}) == 0) {{return {};}}\n";
154+
const char *compareTemplate = " if(ZstrCompareN(\"{}\", zstr, {}) == 0) {{return {};}}\n";
155155
// Store the length in a variable to avoid taking address of rvalue
156156
unsigned long long strLength = (unsigned long long)e.str.length;
157157
StrWriteFmt(&code, compareTemplate, e.str.data, strLength, e.name.data);
158158
};
159159

160-
const char* returnTemplate = " return {};\n}}\n";
160+
const char *returnTemplate = " return {};\n}}\n";
161161
StrWriteFmt(&code, returnTemplate, invalidEnumName);
162162

163-
const char* toZstrHeader =
163+
const char *toZstrHeader =
164164
"///\n"
165165
"/// Converts given enum to {} zero-terminated string.\n"
166166
"///\n"
@@ -176,19 +176,19 @@ int main(int argc, char** argv) {
176176

177177
// Use VecForeach for iterating over entries
178178
VecForeach(&entries, e) {
179-
const char* caseTemplate = " case {} : {{return \"{}\";}}\n";
179+
const char *caseTemplate = " case {} : {{return \"{}\";}}\n";
180180
StrWriteFmt(&code, caseTemplate, e.name.data, e.str.data);
181181
};
182182

183-
const char* defaultTemplate =
183+
const char *defaultTemplate =
184184
" default: break;\n"
185185
" }}\n"
186186
" return \"{}\";\n"
187187
"}}\n";
188188

189189
// Use a static string for NULL to avoid taking address of string literal
190-
const char* nullStrValue = "NULL";
191-
const char* nullStr = nullStrValue;
190+
const char *nullStrValue = "NULL";
191+
const char *nullStr = nullStrValue;
192192
if (invalid_enum.str.data) {
193193
nullStr = invalid_enum.str.data;
194194
}
@@ -197,7 +197,7 @@ int main(int argc, char** argv) {
197197
}
198198

199199
if (output_filename) {
200-
FILE* f = fopen(output_filename, "w");
200+
FILE *f = fopen(output_filename, "w");
201201
fwrite(code.data, 1, code.length, f);
202202
fclose(f);
203203
} else {

Bin/SubProcComm.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@
44
// the prgram writes something to child process and expect's the same thing echoed back
55
// so it can be verified that we got the same content
66
// executed like : Build/SubProcComm /bin/head -n 1
7-
int main(int argc, char** argv, char** envp) {
7+
int main(int argc, char **argv, char **envp) {
88
// create a new child process
9-
SysProc* proc = SysProcCreate(argv[1], argv + 1, envp);
9+
SysProc *proc = SysProcCreate(argv[1], argv + 1, envp);
1010

1111
// write something to it's stdout
1212
SysProcWriteToStdinFmtLn(proc, "value = {}", 42);

0 commit comments

Comments
 (0)