From c2e0cdc6d67891e6e228e78ffbc8cbc8e3c05621 Mon Sep 17 00:00:00 2001 From: William Bell <62452284+Ugric@users.noreply.github.com> Date: Tue, 2 Sep 2025 18:35:43 +0100 Subject: [PATCH] fix buffer overflow seg fault when using cache --- anonymous-function-test.ar | 6 +-- src/arobject.h | 2 +- src/main.c | 3 ++ src/runtime/call/call.c | 9 +++-- src/runtime/objects/number/number.c | 59 ++++++++++++++++++----------- src/runtime/objects/number/number.h | 2 + src/runtime/objects/string/string.c | 2 +- src/runtime/runtime.c | 41 +++++++++++--------- 8 files changed, 75 insertions(+), 49 deletions(-) diff --git a/anonymous-function-test.ar b/anonymous-function-test.ar index 5fea105..3fcc5cf 100644 --- a/anonymous-function-test.ar +++ b/anonymous-function-test.ar @@ -1,3 +1,3 @@ -let i = 10000 -while (i) do - i=i-1 \ No newline at end of file +let f(i) = do + while (i) i=i-1 +f(1e6) \ No newline at end of file diff --git a/src/arobject.h b/src/arobject.h index d889538..6914ed9 100644 --- a/src/arobject.h +++ b/src/arobject.h @@ -48,10 +48,10 @@ typedef struct { } Translated; struct string_struct { - char *data; uint64_t prehash; uint64_t hash; bool hash_computed; + char *data; size_t length; }; diff --git a/src/main.c b/src/main.c index 3d0e23a..f4811a0 100644 --- a/src/main.c +++ b/src/main.c @@ -258,6 +258,9 @@ int load_cache(Translated *translated_dest, char *joined_paths, uint64_t hash, *translated_dest = init_translator(source_path); + + translated_dest->registerCount = register_count; + arena_resize(&translated_dest->constants, constantsSize); if (fread(translated_dest->constants.data, 1, constantsSize, bytecode_file) != diff --git a/src/runtime/call/call.c b/src/runtime/call/call.c index 2855aea..bdb9b5a 100644 --- a/src/runtime/call/call.c +++ b/src/runtime/call/call.c @@ -143,7 +143,7 @@ void run_call(ArgonObject *original_object, size_t argc, ArgonObject **argv, object->value.argon_fn.bytecode_length, false}, object->value.argon_fn.translated.constants, object->value.argon_fn.translated.path}, - {state->registers, + {ar_alloc(object->value.argon_fn.translated.registerCount * sizeof(ArgonObject *)), 0, object->value.argon_fn.translated.path, NULL, @@ -156,10 +156,11 @@ void run_call(ArgonObject *original_object, size_t argc, ArgonObject **argv, if (CStackFrame) { runtime(new_stackFrame.translated, new_stackFrame.state, new_stackFrame.stack, err); + state->registers[0] = new_stackFrame.state.registers[0]; } else { - *state->currentStackFramePointer = - ar_alloc(sizeof(StackFrame)); - **state->currentStackFramePointer = new_stackFrame; + StackFrame *currentStackFrame = ar_alloc(sizeof(StackFrame)); + *currentStackFrame = new_stackFrame; + *state->currentStackFramePointer = currentStackFrame; if ((*state->currentStackFramePointer)->depth >= 10000) { double logval = log10((double)(*state->currentStackFramePointer)->depth); diff --git a/src/runtime/objects/number/number.c b/src/runtime/objects/number/number.c index 14ebbcd..906fc3c 100644 --- a/src/runtime/objects/number/number.c +++ b/src/runtime/objects/number/number.c @@ -99,7 +99,7 @@ ArgonObject *ARGON_NUMBER_TYPE___add__(size_t argc, ArgonObject **argv, bool gonna_overflow = (a > 0 && b > 0 && a > INT64_MAX - b) || (a < 0 && b < 0 && a < INT64_MIN - b); if (!gonna_overflow) { - return new_number_object_from_num_and_den(a + b, 1); + return new_number_object_from_int64(a + b); } mpq_t a_GMP, b_GMP; mpq_init(a_GMP); @@ -165,7 +165,7 @@ ArgonObject *ARGON_NUMBER_TYPE___subtract__(size_t argc, ArgonObject **argv, bool gonna_overflow = (neg_a > 0 && b > 0 && b > INT64_MAX - neg_a) || (neg_a < 0 && b < 0 && b < INT64_MIN - neg_a); if (!gonna_overflow) { - return new_number_object_from_num_and_den(a - b, 1); + return new_number_object_from_int64(a - b); } mpq_t a_GMP, b_GMP; mpq_init(a_GMP); @@ -414,11 +414,11 @@ ArgonObject *ARGON_NUMBER_TYPE___string__(size_t argc, ArgonObject **argv, #define small_ints_min -256 #define small_ints_max 256 -ArgonObject small_ints[small_ints_max-small_ints_min+1]; +ArgonObject small_ints[small_ints_max - small_ints_min + 1]; void init_small_ints() { - for (int64_t i = 0; i <= small_ints_max-small_ints_min; i++) { - int64_t n = i+small_ints_min; + for (int64_t i = 0; i <= small_ints_max - small_ints_min; i++) { + int64_t n = i + small_ints_min; small_ints[i].type = TYPE_NUMBER; small_ints[i].dict = createHashmap_GC(); add_builtin_field(&small_ints[i], __class__, ARGON_NUMBER_TYPE); @@ -432,29 +432,31 @@ void init_small_ints() { void create_ARGON_NUMBER_TYPE() { ARGON_NUMBER_TYPE = new_object(); add_builtin_field(ARGON_NUMBER_TYPE, __name__, - new_string_object_null_terminated("number")); + new_string_object_null_terminated("number")); add_builtin_field( ARGON_NUMBER_TYPE, __string__, create_argon_native_function("__string__", ARGON_NUMBER_TYPE___string__)); - add_builtin_field(ARGON_NUMBER_TYPE, __new__, - create_argon_native_function("__new__", ARGON_NUMBER_TYPE___new__)); + add_builtin_field( + ARGON_NUMBER_TYPE, __new__, + create_argon_native_function("__new__", ARGON_NUMBER_TYPE___new__)); add_builtin_field( ARGON_NUMBER_TYPE, __number__, create_argon_native_function("__number__", ARGON_NUMBER_TYPE___number__)); add_builtin_field(ARGON_NUMBER_TYPE, __boolean__, - create_argon_native_function("__boolean__", - ARGON_NUMBER_TYPE___boolean__)); - add_builtin_field(ARGON_NUMBER_TYPE, __add__, - create_argon_native_function("__add__", ARGON_NUMBER_TYPE___add__)); + create_argon_native_function( + "__boolean__", ARGON_NUMBER_TYPE___boolean__)); + add_builtin_field( + ARGON_NUMBER_TYPE, __add__, + create_argon_native_function("__add__", ARGON_NUMBER_TYPE___add__)); add_builtin_field(ARGON_NUMBER_TYPE, __subtract__, - create_argon_native_function("__subtract__", - ARGON_NUMBER_TYPE___subtract__)); + create_argon_native_function( + "__subtract__", ARGON_NUMBER_TYPE___subtract__)); add_builtin_field(ARGON_NUMBER_TYPE, __multiply__, - create_argon_native_function("__multiply__", - ARGON_NUMBER_TYPE___multiply__)); + create_argon_native_function( + "__multiply__", ARGON_NUMBER_TYPE___multiply__)); add_builtin_field(ARGON_NUMBER_TYPE, __division__, - create_argon_native_function("__division__", - ARGON_NUMBER_TYPE___division__)); + create_argon_native_function( + "__division__", ARGON_NUMBER_TYPE___division__)); init_small_ints(); } @@ -534,7 +536,7 @@ ArgonObject *new_number_object(mpq_t number) { int64_t i64 = 0; bool is_int64 = mpq_to_int64(number, &i64); if (is_int64 && i64 >= small_ints_min && i64 <= small_ints_max) { - return &small_ints[i64-small_ints_min]; + return &small_ints[i64 - small_ints_min]; } ArgonObject *object = new_object(); add_builtin_field(object, __class__, ARGON_NUMBER_TYPE); @@ -552,7 +554,7 @@ ArgonObject *new_number_object(mpq_t number) { ArgonObject *new_number_object_from_num_and_den(int64_t n, uint64_t d) { if (d == 1 && n >= small_ints_min && n <= small_ints_max) { - return &small_ints[n-small_ints_min]; + return &small_ints[n - small_ints_min]; } ArgonObject *object = new_object(); add_builtin_field(object, __class__, ARGON_NUMBER_TYPE); @@ -573,11 +575,24 @@ ArgonObject *new_number_object_from_num_and_den(int64_t n, uint64_t d) { return object; } +ArgonObject *new_number_object_from_int64(int64_t i64) { + if (i64 >= small_ints_min && i64 <= small_ints_max) { + return &small_ints[i64 - small_ints_min]; + } + ArgonObject *object = new_object(); + add_builtin_field(object, __class__, ARGON_NUMBER_TYPE); + object->type = TYPE_NUMBER; + object->value.as_number.is_int64 = true; + object->value.as_number.n.i64 = i64; + object->as_bool = i64; + return object; +} + ArgonObject *new_number_object_from_double(double d) { int64_t i64 = 0; bool is_int64 = double_to_int64(d, &i64); if (is_int64 && i64 >= small_ints_min && i64 <= small_ints_max) { - return &small_ints[i64-small_ints_min]; + return &small_ints[i64 - small_ints_min]; } ArgonObject *object = new_object(); add_builtin_field(object, __class__, ARGON_NUMBER_TYPE); @@ -602,7 +617,7 @@ void load_number(Translated *translated, RuntimeState *state) { uint8_t is_int64 = pop_byte(translated, state); if (is_int64) { state->registers[to_register] = - new_number_object_from_num_and_den(pop_bytecode(translated, state), 1); + new_number_object_from_int64(pop_bytecode(translated, state)); return; } size_t num_size = pop_bytecode(translated, state); diff --git a/src/runtime/objects/number/number.h b/src/runtime/objects/number/number.h index 9b933a0..148b35d 100644 --- a/src/runtime/objects/number/number.h +++ b/src/runtime/objects/number/number.h @@ -22,4 +22,6 @@ ArgonObject *new_number_object_from_double(double d); ArgonObject *new_number_object_from_num_and_den(int64_t n, uint64_t d); +ArgonObject *new_number_object_from_int64(int64_t i64); + #endif // RUNTIME_NUMBER_H \ No newline at end of file diff --git a/src/runtime/objects/string/string.c b/src/runtime/objects/string/string.c index cf0980f..02704bc 100644 --- a/src/runtime/objects/string/string.c +++ b/src/runtime/objects/string/string.c @@ -18,7 +18,7 @@ ArgonObject *new_string_object(char *data, size_t length, uint64_t prehash, ArgonObject *object = new_object(); add_builtin_field(object, __class__, ARGON_STRING_TYPE); add_builtin_field(object, field_length, - new_number_object_from_num_and_den(length, 1)); + new_number_object_from_int64(length)); object->type = TYPE_STRING; object->value.as_str.data = ar_alloc_atomic(length); memcpy(object->value.as_str.data, data, length); diff --git a/src/runtime/runtime.c b/src/runtime/runtime.c index 55a6139..fc73f2a 100644 --- a/src/runtime/runtime.c +++ b/src/runtime/runtime.c @@ -388,7 +388,7 @@ ArgonObject *ARGON_BOOL_TYPE___number__(size_t argc, ArgonObject **argv, "__number__ expects 1 arguments, got %" PRIu64, argc); return ARGON_NULL; } - return new_number_object_from_num_and_den(argv[0] == ARGON_TRUE, 1); + return new_number_object_from_int64(argv[0] == ARGON_TRUE); } ArgonObject *ARGON_STRING_TYPE___string__(size_t argc, ArgonObject **argv, @@ -463,7 +463,7 @@ ArgonObject *ARGON_NULL_TYPE___number__(size_t argc, ArgonObject **argv, *err = create_err(0, 0, 0, "", "Runtime Error", "__boolean__ expects 1 arguments, got %" PRIu64, argc); } - return new_number_object_from_num_and_den(0, 1); + return new_number_object_from_int64(0); } ArgonObject *ARGON_NULL_TYPE___string__(size_t argc, ArgonObject **argv, ArErr *err, RuntimeState *state) { @@ -494,8 +494,10 @@ void bootstrap_types() { ARGON_BOOL_TYPE = new_object(); add_builtin_field(ARGON_BOOL_TYPE, __base__, BASE_CLASS); ARGON_TRUE = new_object(); + ARGON_TRUE->type = TYPE_BOOL; add_builtin_field(ARGON_TRUE, __class__, ARGON_BOOL_TYPE); ARGON_FALSE = new_object(); + ARGON_FALSE->type = TYPE_BOOL; add_builtin_field(ARGON_FALSE, __class__, ARGON_BOOL_TYPE); ARGON_NULL->as_bool = false; @@ -626,7 +628,8 @@ static inline void load_const(Translated *translated, RuntimeState *state) { uint64_t to_register = pop_byte(translated, state); size_t length = pop_bytecode(translated, state); uint64_t offset = pop_bytecode(translated, state); - ArgonObject *object = new_string_object(arena_get(&translated->constants, offset), length, 0, 0); + ArgonObject *object = new_string_object( + arena_get(&translated->constants, offset), length, 0, 0); state->registers[to_register] = object; } @@ -715,8 +718,7 @@ void runtime(Translated _translated, RuntimeState _state, Stack *stack, [OP_LOAD_ACCESS_FUNCTION] = &&DO_LOAD_ACCESS_FUNCTION}; _state.head = 0; - StackFrame *currentStackFrame = - ar_alloc(sizeof(StackFrame)); + StackFrame *currentStackFrame = ar_alloc(sizeof(StackFrame)); *currentStackFrame = (StackFrame){_translated, _state, stack, NULL, 0}; currentStackFrame->state.currentStackFramePointer = ¤tStackFrame; while (currentStackFrame) { @@ -819,8 +821,8 @@ void runtime(Translated _translated, RuntimeState _state, Stack *stack, } DO_ADDITION: { uint8_t registerA = pop_byte(translated, state); - uint64_t registerB = pop_byte(translated, state); - uint64_t registerC = pop_byte(translated, state); + uint8_t registerB = pop_byte(translated, state); + uint8_t registerC = pop_byte(translated, state); ArgonObject *valueA = state->registers[registerA]; ArgonObject *valueB = state->registers[registerB]; @@ -833,8 +835,7 @@ void runtime(Translated _translated, RuntimeState _state, Stack *stack, bool gonna_overflow = (a > 0 && b > 0 && a > INT64_MAX - b) || (a < 0 && b < 0 && a < INT64_MIN - b); if (!gonna_overflow) { - state->registers[registerC] = - new_number_object_from_num_and_den(a + b, 1); + state->registers[registerC] = new_number_object_from_int64(a + b); continue; } mpq_t a_GMP, b_GMP; @@ -873,13 +874,15 @@ void runtime(Translated _translated, RuntimeState _state, Stack *stack, continue; } - ArgonObject *args[] = {valueA, valueB}; - state->registers[registerC] = ARGON_ADDITION_FUNCTION(2, args, err, state); - goto START; - DO_SUBTRACTION:; - registerA = pop_byte(translated, state); - registerB = pop_byte(translated, state); - registerC = pop_byte(translated, state); + ArgonObject *args[] = {valueA, valueB}; + state->registers[registerC] = + ARGON_ADDITION_FUNCTION(2, args, err, state); + continue; + } + DO_SUBTRACTION: { + uint8_t registerA = pop_byte(translated, state); + uint8_t registerB = pop_byte(translated, state); + uint8_t registerC = pop_byte(translated, state); ArgonObject *valueA = state->registers[registerA]; ArgonObject *valueB = state->registers[registerB]; @@ -893,8 +896,7 @@ void runtime(Translated _translated, RuntimeState _state, Stack *stack, bool gonna_overflow = (neg_a > 0 && b > 0 && b > INT64_MAX - neg_a) || (neg_a < 0 && b < 0 && b < INT64_MIN - neg_a); if (!gonna_overflow) { - state->registers[registerC] = - new_number_object_from_num_and_den(a - b, 1); + state->registers[registerC] = new_number_object_from_int64(a - b); continue; } mpq_t a_GMP, b_GMP; @@ -939,6 +941,9 @@ void runtime(Translated _translated, RuntimeState _state, Stack *stack, continue; } } + + ArgonObject *result = currentStackFrame->state.registers[0]; currentStackFrame = currentStackFrame->previousStackFrame; + if(currentStackFrame) currentStackFrame->state.registers[0] = result; } }