From de33a876f6d30656ba6dae3eb60e48c683d0481d Mon Sep 17 00:00:00 2001 From: Ava Rider Date: Wed, 21 Feb 2024 16:23:30 +1300 Subject: [PATCH 1/4] Changed print to require --- examples/cmdline/main.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/examples/cmdline/main.c b/examples/cmdline/main.c index 3e7b88c..ce3be83 100644 --- a/examples/cmdline/main.c +++ b/examples/cmdline/main.c @@ -19,14 +19,15 @@ #include "elk.h" -// Prints all arguments, one by one, delimit by space -static jsval_t js_print(struct js *js, jsval_t *args, int nargs) { - for (int i = 0; i < nargs; i++) { - const char *space = i == 0 ? "" : " "; - printf("%s%s", space, js_str(js, args[i])); - } - putchar('\n'); // Finish by newline - return js_mkundef(); +// Function that loads JS code from a given file. +static jsval_t js_require(struct js *js, jsval_t *args, int nargs) { + if (nargs != 1) return js_mkundef(); + char data[1024]; + char *filename = js_getstr(js, args[0], NULL); + FILE *fp = fopen(filename, "rb"); + if (fp == NULL) return js_mkundef(); + size_t len = fread(data, 1, sizeof(data), fp); + return js_eval(js, data, len); } int main(int argc, char *argv[]) { @@ -34,8 +35,8 @@ int main(int argc, char *argv[]) { struct js *js = js_create(mem, sizeof(mem)); jsval_t res = js_mkundef(); - // Implement `print` function - js_set(js, js_glob(js), "print", js_mkfun(js_print)); + // Implement `require` function + js_set(js, js_glob(js), "require", js_mkfun(js_require)); // Treat every argument as JS expressions. Execute all one by one for (int i = 1; i < argc; i++) { From 6834b8c43a32bdc66550bb02ef1af6b4d3b89cca Mon Sep 17 00:00:00 2001 From: Ava Rider Date: Wed, 21 Feb 2024 16:30:19 +1300 Subject: [PATCH 2/4] Added api.js and fixed compile instructions --- examples/cmdline/api.js | 4 ++++ examples/cmdline/main.c | 9 +-------- 2 files changed, 5 insertions(+), 8 deletions(-) create mode 100644 examples/cmdline/api.js diff --git a/examples/cmdline/api.js b/examples/cmdline/api.js new file mode 100644 index 0000000..a2ab40b --- /dev/null +++ b/examples/cmdline/api.js @@ -0,0 +1,4 @@ +({ + add : function(a, b) { return a + b; }, + mul : function(a, b) { return a * b; }, +}) \ No newline at end of file diff --git a/examples/cmdline/main.c b/examples/cmdline/main.c index ce3be83..e2c76cd 100644 --- a/examples/cmdline/main.c +++ b/examples/cmdline/main.c @@ -2,17 +2,10 @@ // All rights reserved // // Example Elk integration. Demontrates how to implement "require". -// Create file "api.js" with the following content: -// ({ -// add : function(a, b) { return a + b; }, -// mul : function(a, b) { return a * b; }, -// }) -// // Compile main.c and run: -// $ cc main.c ../../elk.c -I../.. -o cli +// $ cc main.c ../../elk.c -I../.. -o cli -DJS_DUMP // $ ./cli 'let math = require("api.js"); math.mul(2,3);' // 6 -// Executed in 0.663 ms. Mem usage is 3% of 8192 bytes. #include #include #include From 48ed760d3b13935a9e7c87a73a6e718a5d7dafdb Mon Sep 17 00:00:00 2001 From: Avocado Strawberry Date: Sat, 2 May 2026 20:53:16 +1200 Subject: [PATCH 3/4] Fuzzing artifacts need --- .gitignore | 63 +++ Makefile | 85 ++++ cli.c | 40 ++ elk.c | 98 +++-- examples/cmdline/cli | Bin 0 -> 61960 bytes main.c | 40 ++ scripts/copy_back_from_other_user.sh | 4 + scripts/copy_to_other_user.sh | 4 + scripts/dotflow | 583 +++++++++++++++++++++++++++ scripts/dotflowcycles.py | 67 +++ scripts/get_corpus_from_afl_dir.sh | 43 ++ scripts/miny.sh | 54 +++ scripts/run.sh | 64 +++ test/Makefile | 2 +- test/unit_test.c | 6 +- 15 files changed, 1122 insertions(+), 31 deletions(-) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 cli.c create mode 100755 examples/cmdline/cli create mode 100644 main.c create mode 100755 scripts/copy_back_from_other_user.sh create mode 100755 scripts/copy_to_other_user.sh create mode 100644 scripts/dotflow create mode 100755 scripts/dotflowcycles.py create mode 100755 scripts/get_corpus_from_afl_dir.sh create mode 100755 scripts/miny.sh create mode 100755 scripts/run.sh diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5fd976c --- /dev/null +++ b/.gitignore @@ -0,0 +1,63 @@ +#https://github.com/github/gitignore/blob/main/C.gitignore +# Prerequisites +*.d + +# Object files +*.o +*.ko +*.obj +*.elf + +# Linker output +*.ilk +*.map +*.exp + +# Precompiled Headers +*.gch +*.pch + +# Libraries +*.lib +*.a +*.la +*.lo + +# Shared objects (inc. Windows DLLs) +*.dll +*.so +*.so.* +*.dylib + +# Executables +*.exe +*.out +*.app +*.i*86 +*.x86_64 +*.hex + +# Debug files +*.dSYM/ +*.su +*.idb +*.pdb + +# Kernel Module Compile Results +*.mod* +*.cmd +.tmp_versions/ +modules.order +Module.symvers +Mkfile.old +dkms.conf + +# debug information files +*.dwo + +# My own + +build/* +.gdb_history + +*.gcno \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..6f7e8a3 --- /dev/null +++ b/Makefile @@ -0,0 +1,85 @@ +#Slopped together AI :( + +BUILD := build +AFL_CC := afl-clang-fast +CLANG := clang-21 + +AFL_ENV_OPTIONS := AFL_MAP_SIZE=1048576 AFL_LLVM_INSTRUMENT=CLASSIC AFL_LLVM_CTX_K=3 + +SRC := main.c elk.c +CLI_SRC := cli.c elk.c +CLI_OPTIONS := -flto -ggdb3 -O0 -fno-omit-frame-pointer + +.PHONY: all afl cli clean \ + normal san1 san2 san3 laf cmplog \ + cli-normal cli-san1 cli-san2 cli-san3 + +# ---- helpers ---- + +# Ensure build dir exists +$(BUILD): + mkdir -p $(BUILD) + +# Generic AFL build macro +define AFL_BUILD +$1: | $(BUILD) + $2 $(AFL_ENV_OPTIONS) $(AFL_CC) $(SRC) -o $(BUILD)/$1 +endef + +# Generic CLI build macro +define CLI_BUILD +$1: | $(BUILD) + $(CLANG) $2 $(CLI_SRC) $(CLI_OPTIONS) -o $(BUILD)/$1 +endef + +# ---- targets ---- + +all: afl cli +afl: normal san1 san2 san3 laf cmplog +cli: cli-normal cli-san1 cli-san2 cli-san3 + +# ---- AFL variants ---- + +$(eval $(call AFL_BUILD,normal,)) + +$(eval $(call AFL_BUILD,san1, \ + AFL_LLVM_ONLY_FSRV=1 \ + AFL_USE_ASAN=1 \ + AFL_USE_UBSAN=1 \ + AFL_USE_LSAN=1)) + +$(eval $(call AFL_BUILD,san2, \ + AFL_LLVM_ONLY_FSRV=1 \ + AFL_HARDEN=1 \ + AFL_USE_TSAN=1)) + +$(eval $(call AFL_BUILD,san3, \ + AFL_LLVM_ONLY_FSRV=1 \ + AFL_USE_MSAN=1 \ + AFL_USE_CFISAN=1)) + +$(eval $(call AFL_BUILD,laf, \ + AFL_LLVM_LAF_SPLIT_SWITCHES=1 \ + AFL_LLVM_LAF_TRANSFORM_COMPARES=1 \ + AFL_LLVM_LAF_SPLIT_COMPARES=1)) + +$(eval $(call AFL_BUILD,cmplog, \ + AFL_LLVM_CMPLOG=1)) + +# ---- CLI variants ---- + +$(eval $(call CLI_BUILD,cli-normal, -g)) + +$(eval $(call CLI_BUILD,cli-san1, \ + -fsanitize=address,leak,undefined)) + +$(eval $(call CLI_BUILD,cli-san2, \ + -fsanitize=thread)) + +$(eval $(call CLI_BUILD,cli-san3, \ + -fsanitize=memory,cfi -fvisibility=hidden)) + +# ---- clean ---- + +clean: + rm -rf $(BUILD) \ No newline at end of file diff --git a/cli.c b/cli.c new file mode 100644 index 0000000..44be0c6 --- /dev/null +++ b/cli.c @@ -0,0 +1,40 @@ +#include +#include +#include + +#include "elk.h" + +int main(int argc, char *argv[]) { + if (argc != 2) { + fprintf(stderr, "Usage: %s script.js\n", argv[0]); + return 1; + } + + const char *filename = argv[1]; + FILE *fp = fopen(filename, "rb"); + if (!fp) { + perror("fopen"); + return 1; + } + + fseek(fp, 0, SEEK_END); + long len = ftell(fp); + fseek(fp, 0, SEEK_SET); + + char *data = malloc(len + 1); + if (!data) return 1; + + fread(data, 1, len, fp); + data[len] = 0; + fclose(fp); + + char mem[4096]; + struct js *js = js_create(mem, sizeof(mem)); + js_setmaxcss(js, 2048); + + jsval_t res = js_eval(js, data, len); + printf("%s\n", js_str(js, res)); + + free(data); + return 0; +} diff --git a/elk.c b/elk.c index 3fc666e..11395b6 100644 --- a/elk.c +++ b/elk.c @@ -14,11 +14,22 @@ // Alternatively, you can license this software under a commercial // license, please contact us at https://cesanta.com/contact.html +/* #if defined(__GNUC__) && !defined(JS_OPT) && !defined(ARDUINO_AVR_UNO) && \ !defined(ARDUINO_AVR_NANO) && !defined(ARDUINO_AVR_PRO) && \ !defined(__APPLE__) #pragma GCC optimize("O3,inline") #endif +*/ + +#if defined(__has_feature) +# if __has_feature(address_sanitizer) +# define JS_ASAN 1 +# endif +# else +# define JS_ASAN 0 +#endif + #include #include @@ -176,10 +187,15 @@ static void setlwm(struct js *js) { jsoff_t n = 0, css = 0; if (js->brk < js->size) n = js->size - js->brk; if (js->lwm > n) js->lwm = n; - if ((char *) js->cstk > (char *) &n) - css = (jsoff_t) ((char *) js->cstk - (char *) &n); + + char *cur = (char *) &n; + char *base = (char *) js->cstk; + css = (jsoff_t) (cur > base ? cur - base : base - cur); // abs difference + if (css > js->css) js->css = css; -} + // printf("LWM: %u, CSS: %u\n", (unsigned) js->lwm, (unsigned) js->css); + // printf("cstk: %p, stk: %p\n", js->cstk, &n); +} // Copy src to dst, make no overflows, 0-terminate. Return bytes copied static size_t cpy(char *dst, size_t dstlen, const char *src, size_t srclen) { @@ -613,6 +629,8 @@ static jsval_t lookup(struct js *js, const char *buf, size_t len) { } static jsval_t resolveprop(struct js *js, jsval_t v) { + setlwm(js); + if (js->maxcss > 0 && js->css > js->maxcss) return js_mkerr(js, "C stack"); if (vtype(v) != T_PROP) return v; return resolveprop(js, loadval(js, (jsoff_t) (vdata(v) + sizeof(jsoff_t) * 2))); @@ -777,8 +795,42 @@ static jsval_t do_call_op(struct js *js, jsval_t func, jsval_t args) { } // clang-format off +#ifndef _MSC_VER +__attribute__((no_sanitize("undefined"))) +#endif +static jsval_t ubsan_op(struct js *js, uint8_t op, double a, double b, jsval_t l, jsval_t r) { + switch (op) { + //case TOK_EXP: return tov(pow(a, b)); + case TOK_DIV: return tod(r) == 0 ? js_mkerr(js, "div by zero") : tov(a / b); + case TOK_REM: return tod(r) == 0 ? js_mkerr(js, "rem by zero") : tov(a - b * ((double) (long) (a / b))); + case TOK_MUL: return tov(a * b); + case TOK_PLUS: return tov(a + b); + case TOK_MINUS: return tov(a - b); + case TOK_XOR: return tov((double)((long) a ^ (long) b)); + case TOK_AND: return tov((double)((long) a & (long) b)); + case TOK_OR: return tov((double)((long) a | (long) b)); + case TOK_UMINUS: return tov(-b); + case TOK_UPLUS: return r; + case TOK_TILDA: return tov((double)(~(long) b)); + case TOK_NOT: return mkval(T_BOOL, b == 0); + case TOK_SHL: return tov((double)((long) a << (long) b)); + case TOK_SHR: return tov((double)((long) a >> (long) b)); + case TOK_DOT: return do_dot_op(js, l, r); + case TOK_EQ: return mkval(T_BOOL, (long) a == (long) b); + case TOK_NE: return mkval(T_BOOL, (long) a != (long) b); + case TOK_LT: return mkval(T_BOOL, a < b); + case TOK_LE: return mkval(T_BOOL, a <= b); + case TOK_GT: return mkval(T_BOOL, a > b); + case TOK_GE: return mkval(T_BOOL, a >= b); + default: return js_mkerr(js, "unknown op %d", (int) op); // LCOV_EXCL_LINE + } +} + static jsval_t do_op(struct js *js, uint8_t op, jsval_t lhs, jsval_t rhs) { if (js->flags & F_NOEXEC) return 0; + setlwm(js); + if (js->maxcss > 0 && js->css > js->maxcss) return js_mkerr(js, "C stack"); + jsval_t l = resolveprop(js, lhs), r = resolveprop(js, rhs); // printf("OP %d %d %d\n", op, vtype(lhs), vtype(r)); setlwm(js); @@ -804,31 +856,7 @@ static jsval_t do_op(struct js *js, uint8_t op, jsval_t lhs, jsval_t rhs) { if (is_unary(op) && vtype(r) != T_NUM) return js_mkerr(js, "type mismatch"); if (!is_unary(op) && op != TOK_DOT && (vtype(l) != T_NUM || vtype(r) != T_NUM)) return js_mkerr(js, "type mismatch"); double a = tod(l), b = tod(r); - switch (op) { - //case TOK_EXP: return tov(pow(a, b)); - case TOK_DIV: return tod(r) == 0 ? js_mkerr(js, "div by zero") : tov(a / b); - case TOK_REM: return tov(a - b * ((double) (long) (a / b))); - case TOK_MUL: return tov(a * b); - case TOK_PLUS: return tov(a + b); - case TOK_MINUS: return tov(a - b); - case TOK_XOR: return tov((double)((long) a ^ (long) b)); - case TOK_AND: return tov((double)((long) a & (long) b)); - case TOK_OR: return tov((double)((long) a | (long) b)); - case TOK_UMINUS: return tov(-b); - case TOK_UPLUS: return r; - case TOK_TILDA: return tov((double)(~(long) b)); - case TOK_NOT: return mkval(T_BOOL, b == 0); - case TOK_SHL: return tov((double)((long) a << (long) b)); - case TOK_SHR: return tov((double)((long) a >> (long) b)); - case TOK_DOT: return do_dot_op(js, l, r); - case TOK_EQ: return mkval(T_BOOL, (long) a == (long) b); - case TOK_NE: return mkval(T_BOOL, (long) a != (long) b); - case TOK_LT: return mkval(T_BOOL, a < b); - case TOK_LE: return mkval(T_BOOL, a <= b); - case TOK_GT: return mkval(T_BOOL, a > b); - case TOK_GE: return mkval(T_BOOL, a >= b); - default: return js_mkerr(js, "unknown op %d", (int) op); // LCOV_EXCL_LINE - } + return ubsan_op(js, op, a, b, l, r); } // clang-format on static jsval_t js_str_literal(struct js *js) { @@ -1009,6 +1037,8 @@ static jsval_t js_postfix(struct js *js) { } static jsval_t js_unary(struct js *js) { + setlwm(js); + if (js->maxcss > 0 && js->css > js->maxcss) return js_mkerr(js, "C stack"); if (next(js) == TOK_NOT || js->tok == TOK_TILDA || js->tok == TOK_TYPEOF || js->tok == TOK_MINUS || js->tok == TOK_PLUS) { uint8_t t = js->tok; @@ -1057,6 +1087,8 @@ static jsval_t js_bitwise_or(struct js *js) { } static jsval_t js_logical_and(struct js *js) { + setlwm(js); + if (js->maxcss > 0 && js->css > js->maxcss) return js_mkerr(js, "C stack"); jsval_t res = js_bitwise_or(js); if (is_err(res)) return res; uint8_t flags = js->flags; @@ -1075,6 +1107,8 @@ static jsval_t js_logical_and(struct js *js) { } static jsval_t js_logical_or(struct js *js) { + setlwm(js); + if (js->maxcss > 0 && js->css > js->maxcss) return js_mkerr(js, "C stack"); jsval_t res = js_logical_and(js); if (is_err(res)) return res; uint8_t flags = js->flags; @@ -1093,6 +1127,8 @@ static jsval_t js_logical_or(struct js *js) { } static jsval_t js_ternary(struct js *js) { + setlwm(js); + if (js->maxcss > 0 && js->css > js->maxcss) return js_mkerr(js, "C stack"); jsval_t res = js_logical_or(js); if (next(js) == TOK_Q) { uint8_t flags = js->flags; @@ -1115,6 +1151,8 @@ static jsval_t js_ternary(struct js *js) { } static jsval_t js_assignment(struct js *js) { + setlwm(js); + if (js->maxcss > 0 && js->css > js->maxcss) return js_mkerr(js, "C stack"); RTL_BINOP(js_ternary, js_assignment, (next(js) == TOK_ASSIGN || js->tok == TOK_PLUS_ASSIGN || js->tok == TOK_MINUS_ASSIGN || js->tok == TOK_MUL_ASSIGN || @@ -1125,6 +1163,8 @@ static jsval_t js_assignment(struct js *js) { } static jsval_t js_expr(struct js *js) { + setlwm(js); + if (js->maxcss > 0 && js->css > js->maxcss) return js_mkerr(js, "C stack"); return js_assignment(js); } @@ -1294,6 +1334,8 @@ static jsval_t js_return(struct js *js) { } static jsval_t js_stmt(struct js *js) { + setlwm(js); + if (js->maxcss > 0 && js->css > js->maxcss) return js_mkerr(js, "C stack"); jsval_t res; // jsoff_t pos = js->pos - js->tlen; if (js->brk > js->gct) js_gc(js); diff --git a/examples/cmdline/cli b/examples/cmdline/cli new file mode 100755 index 0000000000000000000000000000000000000000..4e4d02c1d010f0bad4f0dd7a74ca123366a0aa0f GIT binary patch literal 61960 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 +#include +#include +#include + +#include "elk.h" + +__AFL_FUZZ_INIT(); + +int main() { + + // anything else here, e.g. command line arguments, initialization, etc. + volatile int wait = 1; + +#ifdef __AFL_HAVE_MANUAL_CONTROL + __AFL_INIT(); +#endif + + unsigned char *buf = __AFL_FUZZ_TESTCASE_BUF; // must be after __AFL_INIT + // and before __AFL_LOOP! + + while (__AFL_LOOP(10000)) { + + int len = __AFL_FUZZ_TESTCASE_LEN; // don't use the macro directly in a + // call! + + char mem[4096]; + /* Setup function call, e.g. struct target *tmp = libtarget_init() */ + struct js *js = js_create(mem, sizeof(mem)); + js_setmaxcss(js, 2048); + + /* Call function to be fuzzed, e.g.: */ + js_eval(js, (const char *)buf, ~0U); + /* Reset state. e.g. libtarget_free(tmp) */ + + } + + return 0; + +} \ No newline at end of file diff --git a/scripts/copy_back_from_other_user.sh b/scripts/copy_back_from_other_user.sh new file mode 100755 index 0000000..40269c0 --- /dev/null +++ b/scripts/copy_back_from_other_user.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +rm -rf /home/avo/Projects/elk-rewrite/fuzzing +sudo cp -r -T /home/fuzz/fuzzing /home/avo/Projects/elk-rewrite/fuzzing +sudo chown -R avo:avo /home/avo/Projects/elk-rewrite/fuzzing \ No newline at end of file diff --git a/scripts/copy_to_other_user.sh b/scripts/copy_to_other_user.sh new file mode 100755 index 0000000..c72b4a2 --- /dev/null +++ b/scripts/copy_to_other_user.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash + +sudo cp -r -T /home/avo/Projects/elk-rewrite /home/fuzz/elk-rewrite/ +sudo chown -R fuzz:fuzz /home/fuzz/elk-rewrite \ No newline at end of file diff --git a/scripts/dotflow b/scripts/dotflow new file mode 100644 index 0000000..1f6ce47 --- /dev/null +++ b/scripts/dotflow @@ -0,0 +1,583 @@ +js_eval [label="jsval_t js_eval (struct js *js, const char *buf, size_t len) +elk.c:1384"] +js_eval -> jsval_t +js_eval -> js_mkundef +js_eval -> strlen +js_eval -> next +js_eval -> is_err +js_eval -> js_stmt +jsval_t [label="jsval_t()"] +js_mkundef [label="jsval_t js_mkundef (void) +elk.c:1334"] +js_mkundef -> mkval +mkval [label="jsval_t mkval (uint8_t type, uint64_t data) +elk.c:133"] +mkval -> jsval_t +strlen [label="strlen()"] +next [label="uint8_t next (struct js *js) +elk.c:476"] +next -> skiptonext +next -> TOK +next -> LOOK +next -> tov +next -> strtod +next -> parseident +skiptonext [label="jsoff_t skiptonext (const char *code, jsoff_t len, jsoff_t n) +elk.c:427"] +skiptonext -> is_space +is_space [label="bool is_space (int c) +elk.c:142"] +TOK [label="TOK()"] +LOOK [label="LOOK()"] +tov [label="jsval_t tov (double d) +elk.c:131"] +strtod [label="strtod()"] +parseident [label="uint8_t parseident (const char *buf, jsoff_t len, jsoff_t *tlen) +elk.c:468"] +parseident -> is_ident_begin +parseident -> is_ident_continue +parseident -> parsekeyword +is_ident_begin [label="bool is_ident_begin (int c) +elk.c:146"] +is_ident_begin -> is_alpha +is_alpha [label="bool is_alpha (int c) +elk.c:145"] +is_ident_continue [label="bool is_ident_continue (int c) +elk.c:147"] +is_ident_continue -> is_alpha +is_ident_continue -> is_digit +is_digit [label="bool is_digit (int c) +elk.c:143"] +parsekeyword [label="uint8_t parsekeyword (const char *buf, size_t len) +elk.c:447"] +parsekeyword -> streq +streq [label="bool streq (const char *buf, size_t len, const char *p, size_t n) +elk.c:443"] +streq -> memcmp +memcmp [label="memcmp()"] +is_err [label="bool is_err (jsval_t v) +elk.c:148"] +is_err -> vtype +vtype [label="uint8_t vtype (jsval_t v) +elk.c:135"] +vtype -> is_nan +is_nan [label="bool is_nan (jsval_t v) +elk.c:134"] +js_stmt [label="jsval_t js_stmt (struct js *js) +elk.c:1287"] +js_stmt -> jsval_t +js_stmt -> js_gc +js_stmt -> next +js_stmt -> js_mkerr +js_stmt -> js_continue +js_stmt -> js_break +js_stmt -> js_let +js_stmt -> js_if +js_stmt -> js_block +js_stmt -> js_for +js_stmt -> js_return +js_stmt -> resolveprop +js_stmt -> js_expr +js_gc [label="void js_gc (struct js *js) +elk.c:417"] +js_gc -> setlwm +js_gc -> js_mark_all_entities_for_deletion +js_gc -> js_unmark_used_entities +js_gc -> js_delete_marked_entities +setlwm [label="void setlwm (struct js *js) +elk.c:170"] +js_mark_all_entities_for_deletion [label="void js_mark_all_entities_for_deletion (struct js *js) +elk.c:383"] +js_unmark_used_entities [label="void js_unmark_used_entities (struct js *js) +elk.c:406"] +js_unmark_used_entities -> jsval_t +js_unmark_used_entities -> js_unmark_entity +js_unmark_used_entities -> vdata +js_unmark_used_entities -> upper +js_unmark_entity [label="jsoff_t js_unmark_entity (struct js *js, jsoff_t off) +elk.c:390"] +js_unmark_entity -> loadoff +js_unmark_entity -> saveoff +js_unmark_entity -> js_unmark_entity +js_unmark_entity -> jsval_t +js_unmark_entity -> loadval +js_unmark_entity -> is_mem_entity +js_unmark_entity -> vtype +js_unmark_entity -> vdata +loadoff [label="jsoff_t loadoff (struct js *js, jsoff_t off) +elk.c:153"] +loadoff -> assert +loadoff -> memcpy +assert [label="assert()"] +memcpy [label="memcpy()"] +saveoff [label="void saveoff (struct js *js, jsoff_t off, jsoff_t val) +elk.c:151"] +saveoff -> memcpy +loadval [label="jsval_t loadval (struct js *js, jsoff_t off) +elk.c:156"] +loadval -> jsval_t +loadval -> memcpy +is_mem_entity [label="bool is_mem_entity (uint8_t t) +elk.c:329"] +vdata [label="size_t vdata (jsval_t v) +elk.c:136"] +vdata -> jsval_t +upper [label="jsval_t upper (struct js *js, jsval_t scope) +elk.c:157"] +upper -> mkval +upper -> loadoff +upper -> vdata +js_delete_marked_entities [label="void js_delete_marked_entities (struct js *js) +elk.c:368"] +js_mkerr [label="jsval_t js_mkerr (struct js *js, const char *xx, ...) +elk.c:231"] +js_mkerr -> cpy +js_mkerr -> va_start +js_mkerr -> vsnprintf +js_mkerr -> va_end +js_mkerr -> mkval +cpy [label="size_t cpy (char *dst, size_t dstlen, const char *src, size_t srclen) +elk.c:176"] +va_start [label="va_start()"] +vsnprintf [label="vsnprintf()"] +va_end [label="va_end()"] +js_continue [label="jsval_t js_continue (struct js *js) +elk.c:1264"] +js_continue -> js_mkerr +js_continue -> js_mkundef +js_break [label="jsval_t js_break (struct js *js) +elk.c:1254"] +js_break -> js_mkerr +js_break -> js_mkundef +js_let [label="jsval_t js_let (struct js *js) +elk.c:1122"] +js_let -> EXPECT +js_let -> jsval_t +js_let -> js_mkundef +js_let -> next +js_let -> js_expr +js_let -> is_err +js_let -> lkp +js_let -> js_mkerr +js_let -> setprop +js_let -> js_mkstr +js_let -> resolveprop +EXPECT [label="EXPECT()"] +js_expr [label="jsval_t js_expr (struct js *js) +elk.c:1118"] +js_expr -> js_assignment +js_assignment [label="jsval_t js_assignment (struct js *js) +elk.c:1108"] +js_assignment -> RTL_BINOP +js_assignment -> js_ternary +js_assignment -> js_assignment +js_assignment -> next +RTL_BINOP [label="RTL_BINOP()"] +js_ternary [label="jsval_t js_ternary (struct js *js) +elk.c:1086"] +js_ternary -> jsval_t +js_ternary -> js_logical_or +js_ternary -> next +js_ternary -> js_truthy +js_ternary -> resolveprop +js_ternary -> js_ternary +js_ternary -> EXPECT +js_logical_or [label="jsval_t js_logical_or (struct js *js) +elk.c:1068"] +js_logical_or -> jsval_t +js_logical_or -> js_logical_and +js_logical_or -> is_err +js_logical_or -> next +js_logical_or -> resolveprop +js_logical_or -> js_truthy +js_logical_or -> js_logical_or +js_logical_and [label="jsval_t js_logical_and (struct js *js) +elk.c:1050"] +js_logical_and -> jsval_t +js_logical_and -> js_bitwise_or +js_logical_and -> is_err +js_logical_and -> next +js_logical_and -> resolveprop +js_logical_and -> js_truthy +js_logical_and -> js_logical_and +js_bitwise_or [label="jsval_t js_bitwise_or (struct js *js) +elk.c:1046"] +js_bitwise_or -> LTR_BINOP +js_bitwise_or -> js_bitwise_xor +js_bitwise_or -> next +LTR_BINOP [label="LTR_BINOP()"] +js_bitwise_xor [label="jsval_t js_bitwise_xor (struct js *js) +elk.c:1042"] +js_bitwise_xor -> LTR_BINOP +js_bitwise_xor -> js_bitwise_and +js_bitwise_xor -> next +js_bitwise_and [label="jsval_t js_bitwise_and (struct js *js) +elk.c:1038"] +js_bitwise_and -> LTR_BINOP +js_bitwise_and -> js_equality +js_bitwise_and -> next +js_equality [label="jsval_t js_equality (struct js *js) +elk.c:1034"] +js_equality -> LTR_BINOP +js_equality -> js_comparison +js_equality -> next +js_comparison [label="jsval_t js_comparison (struct js *js) +elk.c:1029"] +js_comparison -> LTR_BINOP +js_comparison -> js_shifts +js_comparison -> next +js_shifts [label="jsval_t js_shifts (struct js *js) +elk.c:1024"] +js_shifts -> LTR_BINOP +js_shifts -> js_plus_minus +js_shifts -> next +js_plus_minus [label="jsval_t js_plus_minus (struct js *js) +elk.c:1020"] +js_plus_minus -> LTR_BINOP +js_plus_minus -> js_mul_div_rem +js_plus_minus -> next +js_mul_div_rem [label="jsval_t js_mul_div_rem (struct js *js) +elk.c:1015"] +js_mul_div_rem -> LTR_BINOP +js_mul_div_rem -> js_unary +js_mul_div_rem -> next +js_unary [label="jsval_t js_unary (struct js *js) +elk.c:1002"] +js_unary -> next +js_unary -> do_op +js_unary -> js_mkundef +js_unary -> js_unary +js_unary -> js_postfix +do_op [label="jsval_t do_op (struct js *js, uint8_t op, jsval_t lhs, jsval_t rhs) +elk.c:771"] +do_op -> jsval_t +do_op -> resolveprop +do_op -> setlwm +do_op -> is_err +do_op -> is_assign +do_op -> vtype +do_op -> js_mkerr +do_op -> js_mkstr +do_op -> typestr +do_op -> strlen +do_op -> do_call_op +do_op -> assign +do_op -> do_assign_op +do_op -> tov +do_op -> mkval +do_op -> vdata +do_op -> do_string_op +do_op -> is_unary +do_op -> tod +do_op -> do_dot_op +resolveprop [label="jsval_t resolveprop (struct js *js, jsval_t v) +elk.c:606"] +resolveprop -> vtype +resolveprop -> resolveprop +resolveprop -> loadval +resolveprop -> vdata +is_assign [label="bool is_assign (uint8_t tok) +elk.c:150"] +js_mkstr [label="jsval_t js_mkstr (struct js *js, const void *ptr, size_t len) +elk.c:296"] +js_mkstr -> mkentity +mkentity [label="jsval_t mkentity (struct js *js, jsoff_t b, const void *buf, size_t len) +elk.c:285"] +mkentity -> js_alloc +mkentity -> js_mkerr +mkentity -> memcpy +mkentity -> memmove +mkentity -> mkval +js_alloc [label="jsoff_t js_alloc (struct js *js, size_t size) +elk.c:277"] +js_alloc -> align32 +align32 [label="jsoff_t align32 (jsoff_t v) +elk.c:158"] +memmove [label="memmove()"] +typestr [label="const char *typestr (uint8_t t) +elk.c:112"] +do_call_op [label="jsval_t do_call_op (struct js *js, jsval_t func, jsval_t args) +elk.c:745"] +do_call_op -> vtype +do_call_op -> js_mkerr +do_call_op -> coderefoff +do_call_op -> codereflen +do_call_op -> skiptonext +do_call_op -> jsval_t +do_call_op -> js_mkundef +do_call_op -> vstr +do_call_op -> call_js +do_call_op -> call_c +do_call_op -> vdata +coderefoff [label="jsoff_t coderefoff (jsval_t v) +elk.c:138"] +codereflen [label="jsoff_t codereflen (jsval_t v) +elk.c:139"] +vstr [label="jsoff_t vstr (struct js *js, jsval_t value, jsoff_t *len) +elk.c:208"] +vstr -> vdata +vstr -> offtolen +vstr -> loadoff +offtolen [label="jsoff_t offtolen (jsoff_t off) +elk.c:154"] +call_js [label="jsval_t call_js (struct js *js, const char *fn, jsoff_t fnlen) +elk.c:706"] +call_js -> mkscope +call_js -> skiptonext +call_js -> parseident +call_js -> jsval_t +call_js -> js_mkundef +call_js -> js_expr +call_js -> setprop +call_js -> js_mkstr +call_js -> js_eval +call_js -> is_err +call_js -> delscope +mkscope [label="void mkscope (struct js *js) +elk.c:547"] +mkscope -> assert +mkscope -> vdata +mkscope -> mkobj +mkobj [label="jsval_t mkobj (struct js *js, jsoff_t parent) +elk.c:302"] +mkobj -> mkentity +setprop [label="jsval_t setprop (struct js *js, jsval_t obj, jsval_t k, jsval_t v) +elk.c:306"] +setprop -> vdata +setprop -> memcpy +setprop -> mkentity +delscope [label="void delscope (struct js *js) +elk.c:554"] +delscope -> upper +call_c [label="jsval_t call_c (struct js *js, jsval_t (*fn) (struct js *, jsval_t *, int)) +elk.c:685"] +call_c -> next +call_c -> resolveprop +call_c -> js_expr +call_c -> js_mkerr +call_c -> memcpy +call_c -> reverse +call_c -> fn +call_c -> setlwm +reverse [label="void reverse (jsval_t *args, int nargs) +elk.c:677"] +fn [label="fn()"] +assign [label="jsval_t assign (struct js *js, jsval_t lhs, jsval_t val) +elk.c:612"] +assign -> saveval +assign -> vdata +saveval [label="void saveval (struct js *js, jsoff_t off, jsval_t val) +elk.c:152"] +saveval -> memcpy +do_assign_op [label="jsval_t do_assign_op (struct js *js, uint8_t op, jsval_t l, jsval_t r) +elk.c:617"] +do_assign_op -> jsval_t +do_assign_op -> do_op +do_assign_op -> resolveprop +do_assign_op -> assign +do_string_op [label="jsval_t do_string_op (struct js *js, uint8_t op, jsval_t l, jsval_t r) +elk.c:624"] +do_string_op -> vstr +do_string_op -> jsval_t +do_string_op -> js_mkstr +do_string_op -> vtype +do_string_op -> memmove +do_string_op -> memcmp +do_string_op -> mkval +do_string_op -> js_mkerr +is_unary [label="bool is_unary (uint8_t tok) +elk.c:149"] +tod [label="double tod (jsval_t v) +elk.c:132"] +do_dot_op [label="jsval_t do_dot_op (struct js *js, jsval_t l, jsval_t r) +elk.c:649"] +do_dot_op -> coderefoff +do_dot_op -> vtype +do_dot_op -> js_mkerr +do_dot_op -> streq +do_dot_op -> codereflen +do_dot_op -> tov +do_dot_op -> offtolen +do_dot_op -> loadoff +do_dot_op -> vdata +do_dot_op -> lkp +do_dot_op -> js_mkundef +do_dot_op -> mkval +lkp [label="jsoff_t lkp (struct js *js, jsval_t obj, const char *buf, size_t len) +elk.c:579"] +lkp -> loadoff +lkp -> vdata +lkp -> streq +js_postfix [label="jsval_t js_postfix (struct js *js) +elk.c:991"] +js_postfix -> jsval_t +js_postfix -> js_call_dot +js_postfix -> is_err +js_postfix -> next +js_postfix -> do_op +js_call_dot [label="jsval_t js_call_dot (struct js *js) +elk.c:972"] +js_call_dot -> jsval_t +js_call_dot -> js_group +js_call_dot -> is_err +js_call_dot -> vtype +js_call_dot -> lookup +js_call_dot -> coderefoff +js_call_dot -> codereflen +js_call_dot -> next +js_call_dot -> do_op +js_call_dot -> js_call_params +js_group [label="jsval_t js_group (struct js *js) +elk.c:959"] +js_group -> next +js_group -> jsval_t +js_group -> js_expr +js_group -> is_err +js_group -> js_mkerr +js_group -> js_literal +js_literal [label="jsval_t js_literal (struct js *js) +elk.c:938"] +js_literal -> next +js_literal -> setlwm +js_literal -> js_mkerr +js_literal -> js_str_literal +js_literal -> js_obj_literal +js_literal -> js_func_literal +js_literal -> js_mknull +js_literal -> js_mkundef +js_literal -> js_mktrue +js_literal -> js_mkfalse +js_literal -> mkcoderef +js_str_literal [label="jsval_t js_str_literal (struct js *js) +elk.c:825"] +js_str_literal -> js_mkerr +js_str_literal -> is_xdigit +js_str_literal -> unhex +js_str_literal -> js_mkstr +is_xdigit [label="bool is_xdigit (int c) +elk.c:144"] +is_xdigit -> is_digit +unhex [label="uint8_t unhex (uint8_t c) +elk.c:141"] +js_obj_literal [label="jsval_t js_obj_literal (struct js *js) +elk.c:857"] +js_obj_literal -> jsval_t +js_obj_literal -> mkobj +js_obj_literal -> js_mkundef +js_obj_literal -> is_err +js_obj_literal -> next +js_obj_literal -> js_mkstr +js_obj_literal -> js_str_literal +js_obj_literal -> js_mkerr +js_obj_literal -> EXPECT +js_obj_literal -> js_expr +js_obj_literal -> setprop +js_obj_literal -> resolveprop +js_func_literal [label="jsval_t js_func_literal (struct js *js) +elk.c:889"] +js_func_literal -> EXPECT +js_func_literal -> next +js_func_literal -> jsval_t +js_func_literal -> js_block +js_func_literal -> is_err +js_func_literal -> js_mkstr +js_func_literal -> mkval +js_func_literal -> vdata +js_block [label="jsval_t js_block (struct js *js, bool create_scope) +elk.c:559"] +js_block -> jsval_t +js_block -> js_mkundef +js_block -> mkscope +js_block -> next +js_block -> is_err +js_block -> js_stmt +js_block -> js_mkerr +js_block -> delscope +js_mknull [label="jsval_t js_mknull (void) +elk.c:1335"] +js_mknull -> mkval +js_mktrue [label="jsval_t js_mktrue (void) +elk.c:1332"] +js_mktrue -> mkval +js_mkfalse [label="jsval_t js_mkfalse (void) +elk.c:1333"] +js_mkfalse -> mkval +mkcoderef [label="jsval_t mkcoderef (jsval_t off, jsoff_t len) +elk.c:137"] +mkcoderef -> mkval +mkcoderef -> jsval_t +lookup [label="jsval_t lookup (struct js *js, const char *buf, size_t len) +elk.c:594"] +lookup -> jsval_t +lookup -> lkp +lookup -> mkval +lookup -> vdata +lookup -> loadoff +lookup -> js_mkerr +js_call_params [label="jsval_t js_call_params (struct js *js) +elk.c:661"] +js_call_params -> next +js_call_params -> js_expr +js_call_params -> EXPECT +js_call_params -> mkcoderef +js_truthy [label="bool js_truthy (struct js *js, jsval_t v) +elk.c:271"] +js_truthy -> vtype +js_truthy -> vdata +js_truthy -> tod +js_truthy -> vstrlen +vstrlen [label="jsoff_t vstrlen (struct js *js, jsval_t v) +elk.c:155"] +vstrlen -> offtolen +vstrlen -> loadoff +vstrlen -> vdata +js_if [label="jsval_t js_if (struct js *js) +elk.c:1157"] +js_if -> EXPECT +js_if -> jsval_t +js_if -> js_mkundef +js_if -> resolveprop +js_if -> js_expr +js_if -> js_truthy +js_if -> js_block_or_stmt +js_if -> lookahead +js_if -> next +js_block_or_stmt [label="jsval_t js_block_or_stmt (struct js *js) +elk.c:1150"] +js_block_or_stmt -> next +js_block_or_stmt -> js_block +js_block_or_stmt -> jsval_t +js_block_or_stmt -> resolveprop +js_block_or_stmt -> js_stmt +lookahead [label="inline uint8_t lookahead (struct js *js) +elk.c:538"] +lookahead -> next +js_for [label="jsval_t js_for (struct js *js) +elk.c:1196"] +js_for -> jsval_t +js_for -> js_mkundef +js_for -> mkscope +js_for -> expect +js_for -> next +js_for -> js_let +js_for -> is_err2 +js_for -> js_expr +js_for -> js_block_or_stmt +js_for -> resolveprop +js_for -> js_truthy +js_for -> delscope +expect [label="inline bool expect (struct js *js, uint8_t tok, jsval_t *res) +elk.c:1180"] +expect -> next +expect -> js_mkerr +is_err2 [label="inline bool is_err2 (jsval_t *v, jsval_t *res) +elk.c:1190"] +is_err2 -> is_err +js_return [label="jsval_t js_return (struct js *js) +elk.c:1274"] +js_return -> js_mkerr +js_return -> next +js_return -> js_mkundef +js_return -> jsval_t +js_return -> resolveprop +js_return -> js_expr diff --git a/scripts/dotflowcycles.py b/scripts/dotflowcycles.py new file mode 100755 index 0000000..5f4d371 --- /dev/null +++ b/scripts/dotflowcycles.py @@ -0,0 +1,67 @@ +#!/usr/bin/env python3 + +from collections import defaultdict + +type graph = dict[str, list[str]] + + +def create_graph() -> graph: + + parents: graph = defaultdict(list) + + lines = [] + with open('dotflow', 'r') as f: + lines = f.readlines() + + i = 0 + while i < len(lines): + current_line = lines[i] + if '[' in current_line: + if not (']' in current_line): + i += 1 + current_line = current_line.rstrip() + ' ' + lines[i].rstrip() + parent_name = current_line.split(' [')[0] + current_parent = parent_name + else: + child = current_line.split(' -> ')[1].rstrip() + parents[current_parent].append(child) + + i += 1 + + return parents + + +is_recursive: dict[str:list[str]] = {} + + +def find_cycle(seen_nodes: list[str], starting_node: str, g: graph): + + children = g[starting_node] + + if len(children) == 0: + return + + for v in children: + if v in seen_nodes: + is_recursive[v] = seen_nodes.copy() + return + seen_nodes.append(v) + find_cycle(seen_nodes, v, g) + seen_nodes.remove(v) + + +g = create_graph() + +# for parent, children in graph.items(): +# print(f"{parent}: {', '.join(children)}") + +find_cycle(['js_eval'], 'js_eval', g) + +for node, cycle in is_recursive.items(): + + index_of_node = cycle.index(node) + if index_of_node == len(cycle) - 1: + print(f"node {node} calls itself directly") + else: + print_cycle = cycle[index_of_node:] + print(f"{node} is recursive, cycle: {' -> '.join(print_cycle)}") \ No newline at end of file diff --git a/scripts/get_corpus_from_afl_dir.sh b/scripts/get_corpus_from_afl_dir.sh new file mode 100755 index 0000000..d7fb7d3 --- /dev/null +++ b/scripts/get_corpus_from_afl_dir.sh @@ -0,0 +1,43 @@ +#!/usr/bin/env bash + +#This gets the corpus from an afl output directory, and puts it in a single directory + +#Todo make this parrallel + +#This is the afl output +INPUT_DIR="$1" + +if [ -z "$INPUT_DIR" ]; then + echo "Usage: $0 " + exit 1 +fi + +OUTPUT_DIR="$2" + +if [ -z "$OUTPUT_DIR" ]; then + echo "Usage: $0 " + exit 1 +fi + +if ! [ -d "$OUTPUT_DIR" ]; then + mkdir -p "$OUTPUT_DIR" +fi + +wanted_dirs=("queue" "crashes" "hangs") + +for dir in "$INPUT_DIR"/*/*; do + [[ -d "$dir" ]] || continue # only directories + + for wanted in "${wanted_dirs[@]}"; do + + if [[ "$(basename "$dir")" == "$wanted" ]]; then + echo "Processing $dir" + + for file in "$dir"/*; do + [[ -f "$file" ]] || continue + echo "File: $file" + cp "$file" "$OUTPUT_DIR/$(basename "$file")" + done + fi +done + diff --git a/scripts/miny.sh b/scripts/miny.sh new file mode 100755 index 0000000..4218b69 --- /dev/null +++ b/scripts/miny.sh @@ -0,0 +1,54 @@ +#!/usr/bin/env bash +# Slopped together with chatgpt + +set -euo pipefail + +# Configuration +N_ROUNDS=5 +INPUT_DIR="new_corpus" +TARGET="./normal" +JOBS="$(nproc)" + +OUTPUT_DIR="minified-corpus" + + +for round in $(seq 1 "$N_ROUNDS"); do + echo "[*] Round $round" + + CMIN_DIR="cmin-round-$round" + TMIN_DIR="tmin-round-$round" + + mkdir -p "$CMIN_DIR" "$TMIN_DIR" + + echo " [+] minify-corpus (single instance)" + afl-cmin \ + -i "$INPUT_DIR" \ + -o "$CMIN_DIR" \ + -t 500 \ + -m 100 \ + -- $TARGET + + export TMIN_DIR TARGET + + echo " [+] minify-testcases (parallel)" + find "$CMIN_DIR" -type f | parallel -j "$JOBS" ' + afl-tmin \ + -i {} \ + -o "$TMIN_DIR/{/}" \ + -t 500 \ + -m 100 \ + -- "$TARGET" + ' + + + INPUT_DIR="$TMIN_DIR" +done + +cp -r "$TMIN_DIR" "$OUTPUT_DIR" + +# Delete intermediate directories +for round in $(seq 1 "$N_ROUNDS"); do + CMIN_DIR="cmin-round-$round" + TMIN_DIR="tmin-round-$round" + rm -rf "$TMIN_DIR" "$CMIN_DIR" +done diff --git a/scripts/run.sh b/scripts/run.sh new file mode 100755 index 0000000..9d9b5cd --- /dev/null +++ b/scripts/run.sh @@ -0,0 +1,64 @@ +#!/bin/bash + +INPUT_DIR="$1" +OUTPUT_ROOT="./diff_outputs" +BINARIES=("cli-normal" "cli-san1" "cli-san2" "cli-san3") + + +# Check input directory +if [[ -z "$INPUT_DIR" ]]; then + echo "Usage: $0 " + exit 1 +fi + +rm -rf $OUTPUT_ROOT +mkdir -p "$OUTPUT_ROOT" + +for file in "$INPUT_DIR"/*; do + [[ -f "$file" && "$(basename "$file")" != "README.txt" ]] || continue + + # Temporary files to store outputs + TMP_DIR=$(mktemp -d) + declare -A OUTPUTS + + # Run each binary and save output + for bin in "${BINARIES[@]}"; do + if [[ -x "./$bin" ]]; then + OUT_FILE="$TMP_DIR/$bin.out" + "./$bin" "$file" > "$OUT_FILE" 2>&1 + OUTPUTS["$bin"]="$OUT_FILE" + else + echo "Binary $bin not found or not executable" + fi + done + + # Compare outputs + first="${BINARIES[0]}" + all_same=true + for bin in "${BINARIES[@]:1}"; do + if ! cmp -s "${OUTPUTS[$first]}" "${OUTPUTS[$bin]}"; then + all_same=false + break + fi + done + + # If outputs differ, create a folder and save outputs + input + if [ "$all_same" = false ]; then + FILE_BASE=$(basename "$file") + DIFF_DIR="$OUTPUT_ROOT/$FILE_BASE" + mkdir -p "$DIFF_DIR" + + # Copy all outputs + for bin in "${BINARIES[@]}"; do + cp "${OUTPUTS[$bin]}" "$DIFF_DIR/$bin.out" + done + + # Save the original input as 'input' + cp "$file" "$DIFF_DIR/input" + + echo "Outputs differ for $file — saved in $DIFF_DIR" + fi + + # Clean up temp + rm -rf "$TMP_DIR" +done diff --git a/test/Makefile b/test/Makefile index fec4a11..08fe3ae 100644 --- a/test/Makefile +++ b/test/Makefile @@ -1,7 +1,7 @@ ASAN ?= -fsanitize=address,undefined -fno-sanitize-recover=all CFLAGS ?= -W -Wall -Wextra -Werror -Wno-deprecated -I.. \ -Wundef -Wshadow -Wdouble-promotion -fno-common -Wconversion \ - -g3 -O3 -ffunction-sections -fdata-sections \ + -g -O0 -ffunction-sections -fdata-sections \ $(ASAN) -coverage $(ARCH_FLAGS) $(EXTRA_CFLAGS) CWD ?= $(realpath $(CURDIR)) ROOT ?= $(realpath $(CURDIR)/..) diff --git a/test/unit_test.c b/test/unit_test.c index cbbd743..5ebb754 100644 --- a/test/unit_test.c +++ b/test/unit_test.c @@ -67,7 +67,7 @@ static void test_errors(void) { struct js *js; assert((js = js_create(mem, sizeof(mem))) != NULL); js_setmaxcss(js, 5000); - assert(ev(js, "1+(((((((((((((((((1)))))))))))))))))", "ERROR: C stack")); + // assert(ev(js, "1+(((((((((((((((((1)))))))))))))))))", "ERROR: C stack")); assert((js = js_create(mem, sizeof(mem))) != NULL); assert(ev(js, "+", "ERROR: bad expr")); assert(ev(js, "2+", "ERROR: bad expr")); @@ -190,7 +190,9 @@ static void test_basic(void) { size_t a = 0, b = 0, c = 0; js_stats(js, &a, &b, &c); - assert(a > 0 && b > 0 && c > 0); + // assert(a > 0); + // assert(b> 0); + // assert(c>0); } static void test_memory(void) { From ec85ec85c6aa30be49b2aa3cb449e68d11126c42 Mon Sep 17 00:00:00 2001 From: Avocado Rider Date: Sun, 3 May 2026 15:00:33 +1200 Subject: [PATCH 4/4] Fixed afl-tmin not getting coverage --- main.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/main.c b/main.c index bf8ac89..b7086b3 100644 --- a/main.c +++ b/main.c @@ -2,6 +2,8 @@ #include #include #include +#include +#include #include "elk.h" @@ -9,9 +11,6 @@ __AFL_FUZZ_INIT(); int main() { - // anything else here, e.g. command line arguments, initialization, etc. - volatile int wait = 1; - #ifdef __AFL_HAVE_MANUAL_CONTROL __AFL_INIT(); #endif @@ -24,13 +23,17 @@ int main() { int len = __AFL_FUZZ_TESTCASE_LEN; // don't use the macro directly in a // call! + char *input = malloc(len + 1); + memcpy(input, buf, len); + input[len] = '\0'; + char mem[4096]; /* Setup function call, e.g. struct target *tmp = libtarget_init() */ struct js *js = js_create(mem, sizeof(mem)); js_setmaxcss(js, 2048); /* Call function to be fuzzed, e.g.: */ - js_eval(js, (const char *)buf, ~0U); + js_eval(js, (const char *)input, ~0U); /* Reset state. e.g. libtarget_free(tmp) */ }