fix buffer overflow seg fault when using cache

This commit is contained in:
William Bell
2025-09-02 18:35:43 +01:00
parent 571efe46b7
commit c2e0cdc6d6
8 changed files with 75 additions and 49 deletions

View File

@@ -1,3 +1,3 @@
let i = 10000 let f(i) = do
while (i) do while (i) i=i-1
i=i-1 f(1e6)

View File

@@ -48,10 +48,10 @@ typedef struct {
} Translated; } Translated;
struct string_struct { struct string_struct {
char *data;
uint64_t prehash; uint64_t prehash;
uint64_t hash; uint64_t hash;
bool hash_computed; bool hash_computed;
char *data;
size_t length; size_t length;
}; };

View File

@@ -258,6 +258,9 @@ int load_cache(Translated *translated_dest, char *joined_paths, uint64_t hash,
*translated_dest = init_translator(source_path); *translated_dest = init_translator(source_path);
translated_dest->registerCount = register_count;
arena_resize(&translated_dest->constants, constantsSize); arena_resize(&translated_dest->constants, constantsSize);
if (fread(translated_dest->constants.data, 1, constantsSize, bytecode_file) != if (fread(translated_dest->constants.data, 1, constantsSize, bytecode_file) !=

View File

@@ -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.bytecode_length, false},
object->value.argon_fn.translated.constants, object->value.argon_fn.translated.constants,
object->value.argon_fn.translated.path}, object->value.argon_fn.translated.path},
{state->registers, {ar_alloc(object->value.argon_fn.translated.registerCount * sizeof(ArgonObject *)),
0, 0,
object->value.argon_fn.translated.path, object->value.argon_fn.translated.path,
NULL, NULL,
@@ -156,10 +156,11 @@ void run_call(ArgonObject *original_object, size_t argc, ArgonObject **argv,
if (CStackFrame) { if (CStackFrame) {
runtime(new_stackFrame.translated, new_stackFrame.state, runtime(new_stackFrame.translated, new_stackFrame.state,
new_stackFrame.stack, err); new_stackFrame.stack, err);
state->registers[0] = new_stackFrame.state.registers[0];
} else { } else {
*state->currentStackFramePointer = StackFrame *currentStackFrame = ar_alloc(sizeof(StackFrame));
ar_alloc(sizeof(StackFrame)); *currentStackFrame = new_stackFrame;
**state->currentStackFramePointer = new_stackFrame; *state->currentStackFramePointer = currentStackFrame;
if ((*state->currentStackFramePointer)->depth >= 10000) { if ((*state->currentStackFramePointer)->depth >= 10000) {
double logval = double logval =
log10((double)(*state->currentStackFramePointer)->depth); log10((double)(*state->currentStackFramePointer)->depth);

View File

@@ -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) || bool gonna_overflow = (a > 0 && b > 0 && a > INT64_MAX - b) ||
(a < 0 && b < 0 && a < INT64_MIN - b); (a < 0 && b < 0 && a < INT64_MIN - b);
if (!gonna_overflow) { 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_t a_GMP, b_GMP;
mpq_init(a_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) || bool gonna_overflow = (neg_a > 0 && b > 0 && b > INT64_MAX - neg_a) ||
(neg_a < 0 && b < 0 && b < INT64_MIN - neg_a); (neg_a < 0 && b < 0 && b < INT64_MIN - neg_a);
if (!gonna_overflow) { 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_t a_GMP, b_GMP;
mpq_init(a_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_min -256
#define small_ints_max 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() { void init_small_ints() {
for (int64_t i = 0; i <= small_ints_max-small_ints_min; i++) { for (int64_t i = 0; i <= small_ints_max - small_ints_min; i++) {
int64_t n = i+small_ints_min; int64_t n = i + small_ints_min;
small_ints[i].type = TYPE_NUMBER; small_ints[i].type = TYPE_NUMBER;
small_ints[i].dict = createHashmap_GC(); small_ints[i].dict = createHashmap_GC();
add_builtin_field(&small_ints[i], __class__, ARGON_NUMBER_TYPE); add_builtin_field(&small_ints[i], __class__, ARGON_NUMBER_TYPE);
@@ -436,25 +436,27 @@ void create_ARGON_NUMBER_TYPE() {
add_builtin_field( add_builtin_field(
ARGON_NUMBER_TYPE, __string__, ARGON_NUMBER_TYPE, __string__,
create_argon_native_function("__string__", ARGON_NUMBER_TYPE___string__)); create_argon_native_function("__string__", ARGON_NUMBER_TYPE___string__));
add_builtin_field(ARGON_NUMBER_TYPE, __new__, add_builtin_field(
ARGON_NUMBER_TYPE, __new__,
create_argon_native_function("__new__", ARGON_NUMBER_TYPE___new__)); create_argon_native_function("__new__", ARGON_NUMBER_TYPE___new__));
add_builtin_field( add_builtin_field(
ARGON_NUMBER_TYPE, __number__, ARGON_NUMBER_TYPE, __number__,
create_argon_native_function("__number__", ARGON_NUMBER_TYPE___number__)); create_argon_native_function("__number__", ARGON_NUMBER_TYPE___number__));
add_builtin_field(ARGON_NUMBER_TYPE, __boolean__, add_builtin_field(ARGON_NUMBER_TYPE, __boolean__,
create_argon_native_function("__boolean__", create_argon_native_function(
ARGON_NUMBER_TYPE___boolean__)); "__boolean__", ARGON_NUMBER_TYPE___boolean__));
add_builtin_field(ARGON_NUMBER_TYPE, __add__, add_builtin_field(
ARGON_NUMBER_TYPE, __add__,
create_argon_native_function("__add__", ARGON_NUMBER_TYPE___add__)); create_argon_native_function("__add__", ARGON_NUMBER_TYPE___add__));
add_builtin_field(ARGON_NUMBER_TYPE, __subtract__, add_builtin_field(ARGON_NUMBER_TYPE, __subtract__,
create_argon_native_function("__subtract__", create_argon_native_function(
ARGON_NUMBER_TYPE___subtract__)); "__subtract__", ARGON_NUMBER_TYPE___subtract__));
add_builtin_field(ARGON_NUMBER_TYPE, __multiply__, add_builtin_field(ARGON_NUMBER_TYPE, __multiply__,
create_argon_native_function("__multiply__", create_argon_native_function(
ARGON_NUMBER_TYPE___multiply__)); "__multiply__", ARGON_NUMBER_TYPE___multiply__));
add_builtin_field(ARGON_NUMBER_TYPE, __division__, add_builtin_field(ARGON_NUMBER_TYPE, __division__,
create_argon_native_function("__division__", create_argon_native_function(
ARGON_NUMBER_TYPE___division__)); "__division__", ARGON_NUMBER_TYPE___division__));
init_small_ints(); init_small_ints();
} }
@@ -534,7 +536,7 @@ ArgonObject *new_number_object(mpq_t number) {
int64_t i64 = 0; int64_t i64 = 0;
bool is_int64 = mpq_to_int64(number, &i64); bool is_int64 = mpq_to_int64(number, &i64);
if (is_int64 && i64 >= small_ints_min && i64 <= small_ints_max) { 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(); ArgonObject *object = new_object();
add_builtin_field(object, __class__, ARGON_NUMBER_TYPE); 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) { 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) { 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(); ArgonObject *object = new_object();
add_builtin_field(object, __class__, ARGON_NUMBER_TYPE); 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; 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) { ArgonObject *new_number_object_from_double(double d) {
int64_t i64 = 0; int64_t i64 = 0;
bool is_int64 = double_to_int64(d, &i64); bool is_int64 = double_to_int64(d, &i64);
if (is_int64 && i64 >= small_ints_min && i64 <= small_ints_max) { 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(); ArgonObject *object = new_object();
add_builtin_field(object, __class__, ARGON_NUMBER_TYPE); 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); uint8_t is_int64 = pop_byte(translated, state);
if (is_int64) { if (is_int64) {
state->registers[to_register] = 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; return;
} }
size_t num_size = pop_bytecode(translated, state); size_t num_size = pop_bytecode(translated, state);

View File

@@ -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_num_and_den(int64_t n, uint64_t d);
ArgonObject *new_number_object_from_int64(int64_t i64);
#endif // RUNTIME_NUMBER_H #endif // RUNTIME_NUMBER_H

View File

@@ -18,7 +18,7 @@ ArgonObject *new_string_object(char *data, size_t length, uint64_t prehash,
ArgonObject *object = new_object(); ArgonObject *object = new_object();
add_builtin_field(object, __class__, ARGON_STRING_TYPE); add_builtin_field(object, __class__, ARGON_STRING_TYPE);
add_builtin_field(object, field_length, 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->type = TYPE_STRING;
object->value.as_str.data = ar_alloc_atomic(length); object->value.as_str.data = ar_alloc_atomic(length);
memcpy(object->value.as_str.data, data, length); memcpy(object->value.as_str.data, data, length);

View File

@@ -388,7 +388,7 @@ ArgonObject *ARGON_BOOL_TYPE___number__(size_t argc, ArgonObject **argv,
"__number__ expects 1 arguments, got %" PRIu64, argc); "__number__ expects 1 arguments, got %" PRIu64, argc);
return ARGON_NULL; 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, 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", *err = create_err(0, 0, 0, "", "Runtime Error",
"__boolean__ expects 1 arguments, got %" PRIu64, argc); "__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, ArgonObject *ARGON_NULL_TYPE___string__(size_t argc, ArgonObject **argv,
ArErr *err, RuntimeState *state) { ArErr *err, RuntimeState *state) {
@@ -494,8 +494,10 @@ void bootstrap_types() {
ARGON_BOOL_TYPE = new_object(); ARGON_BOOL_TYPE = new_object();
add_builtin_field(ARGON_BOOL_TYPE, __base__, BASE_CLASS); add_builtin_field(ARGON_BOOL_TYPE, __base__, BASE_CLASS);
ARGON_TRUE = new_object(); ARGON_TRUE = new_object();
ARGON_TRUE->type = TYPE_BOOL;
add_builtin_field(ARGON_TRUE, __class__, ARGON_BOOL_TYPE); add_builtin_field(ARGON_TRUE, __class__, ARGON_BOOL_TYPE);
ARGON_FALSE = new_object(); ARGON_FALSE = new_object();
ARGON_FALSE->type = TYPE_BOOL;
add_builtin_field(ARGON_FALSE, __class__, ARGON_BOOL_TYPE); add_builtin_field(ARGON_FALSE, __class__, ARGON_BOOL_TYPE);
ARGON_NULL->as_bool = false; 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); uint64_t to_register = pop_byte(translated, state);
size_t length = pop_bytecode(translated, state); size_t length = pop_bytecode(translated, state);
uint64_t offset = 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; 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}; [OP_LOAD_ACCESS_FUNCTION] = &&DO_LOAD_ACCESS_FUNCTION};
_state.head = 0; _state.head = 0;
StackFrame *currentStackFrame = StackFrame *currentStackFrame = ar_alloc(sizeof(StackFrame));
ar_alloc(sizeof(StackFrame));
*currentStackFrame = (StackFrame){_translated, _state, stack, NULL, 0}; *currentStackFrame = (StackFrame){_translated, _state, stack, NULL, 0};
currentStackFrame->state.currentStackFramePointer = &currentStackFrame; currentStackFrame->state.currentStackFramePointer = &currentStackFrame;
while (currentStackFrame) { while (currentStackFrame) {
@@ -819,8 +821,8 @@ void runtime(Translated _translated, RuntimeState _state, Stack *stack,
} }
DO_ADDITION: { DO_ADDITION: {
uint8_t registerA = pop_byte(translated, state); uint8_t registerA = pop_byte(translated, state);
uint64_t registerB = pop_byte(translated, state); uint8_t registerB = pop_byte(translated, state);
uint64_t registerC = pop_byte(translated, state); uint8_t registerC = pop_byte(translated, state);
ArgonObject *valueA = state->registers[registerA]; ArgonObject *valueA = state->registers[registerA];
ArgonObject *valueB = state->registers[registerB]; 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) || bool gonna_overflow = (a > 0 && b > 0 && a > INT64_MAX - b) ||
(a < 0 && b < 0 && a < INT64_MIN - b); (a < 0 && b < 0 && a < INT64_MIN - b);
if (!gonna_overflow) { if (!gonna_overflow) {
state->registers[registerC] = state->registers[registerC] = new_number_object_from_int64(a + b);
new_number_object_from_num_and_den(a + b, 1);
continue; continue;
} }
mpq_t a_GMP, b_GMP; mpq_t a_GMP, b_GMP;
@@ -874,12 +875,14 @@ void runtime(Translated _translated, RuntimeState _state, Stack *stack,
} }
ArgonObject *args[] = {valueA, valueB}; ArgonObject *args[] = {valueA, valueB};
state->registers[registerC] = ARGON_ADDITION_FUNCTION(2, args, err, state); state->registers[registerC] =
goto START; ARGON_ADDITION_FUNCTION(2, args, err, state);
DO_SUBTRACTION:; continue;
registerA = pop_byte(translated, state); }
registerB = pop_byte(translated, state); DO_SUBTRACTION: {
registerC = pop_byte(translated, state); 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 *valueA = state->registers[registerA];
ArgonObject *valueB = state->registers[registerB]; 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) || bool gonna_overflow = (neg_a > 0 && b > 0 && b > INT64_MAX - neg_a) ||
(neg_a < 0 && b < 0 && b < INT64_MIN - neg_a); (neg_a < 0 && b < 0 && b < INT64_MIN - neg_a);
if (!gonna_overflow) { if (!gonna_overflow) {
state->registers[registerC] = state->registers[registerC] = new_number_object_from_int64(a - b);
new_number_object_from_num_and_den(a - b, 1);
continue; continue;
} }
mpq_t a_GMP, b_GMP; mpq_t a_GMP, b_GMP;
@@ -939,6 +941,9 @@ void runtime(Translated _translated, RuntimeState _state, Stack *stack,
continue; continue;
} }
} }
ArgonObject *result = currentStackFrame->state.registers[0];
currentStackFrame = currentStackFrame->previousStackFrame; currentStackFrame = currentStackFrame->previousStackFrame;
if(currentStackFrame) currentStackFrame->state.registers[0] = result;
} }
} }