Fixed a hash collision causing null variables to be overwritten

Andrew, don't you dare run my code through a clanker again or I'll hunt
your Canuck ass down and beat you with a hockey stick.
This commit is contained in:
2026-05-26 17:52:07 +10:00
parent b0387edeb0
commit 69175e801a
9 changed files with 24 additions and 10 deletions
+1 -1
View File
@@ -13,7 +13,7 @@ int inspect_bucket(Toy_Bucket** bucketHandle) {
unsigned char* ptr = iter->data; unsigned char* ptr = iter->data;
while ((ptr - iter->data < iter->count) && *((int*)ptr) != 0) { //for each partition while ((ptr >= iter->data) && (ptr < iter->data + iter->count) && *((int*)ptr) != 0) { //for each partition
if ( ( *((int*)ptr) & 1) == 0) { //is this partition still in use? if ( ( *((int*)ptr) & 1) == 0) { //is this partition still in use?
occupied++; occupied++;
+3 -3
View File
@@ -26,7 +26,7 @@ unsigned char* readFile(char* path, int* size) {
//determine the file's length //determine the file's length
fseek(file, 0L, SEEK_END); fseek(file, 0L, SEEK_END);
*size = ftell(file); *size = (int)ftell(file);
rewind(file); rewind(file);
//make some space //make some space
@@ -44,7 +44,7 @@ unsigned char* readFile(char* path, int* size) {
return NULL; return NULL;
} }
buffer[(*size)++] = '\0'; buffer[(*size)] = '\0';
//clean up and return //clean up and return
fclose(file); fclose(file);
@@ -334,7 +334,7 @@ int repl(const char* filepath, bool verbose) {
inputBuffer[--length] = '\0'; inputBuffer[--length] = '\0';
} }
if (length == 0 || !inputBuffer[ strspn(inputBuffer, " \r\n\t") ]) { if (length == 0 || inputBuffer[ strspn(inputBuffer, " \r\n\t") ] == '\0') {
printf("%s> ", prompt); //shows the terminal prompt and restart printf("%s> ", prompt); //shows the terminal prompt and restart
continue; continue;
} }
+1 -1
View File
@@ -172,7 +172,7 @@ static void attr_tableRemove(Toy_VM* vm, Toy_FunctionNative* self) {
Toy_Value Toy_private_handleTableAttributes(Toy_VM* vm, Toy_Value compound, Toy_Value attribute) { Toy_Value Toy_private_handleTableAttributes(Toy_VM* vm, Toy_Value compound, Toy_Value attribute) {
if (MATCH_VALUE_AND_CSTRING(attribute, "length")) { if (MATCH_VALUE_AND_CSTRING(attribute, "length")) {
return TOY_VALUE_FROM_INTEGER(TOY_VALUE_AS_ARRAY(compound)->count); return TOY_VALUE_FROM_INTEGER(TOY_VALUE_AS_TABLE(compound)->count);
} }
else if (MATCH_VALUE_AND_CSTRING(attribute, "insert")) { else if (MATCH_VALUE_AND_CSTRING(attribute, "insert")) {
Toy_Function* fn = Toy_createFunctionFromCallback(&vm->memoryBucket, attr_tableInsert); Toy_Function* fn = Toy_createFunctionFromCallback(&vm->memoryBucket, attr_tableInsert);
+3 -2
View File
@@ -78,6 +78,7 @@ static void emitByte(unsigned char** handle, unsigned int* capacity, unsigned in
((unsigned char*)(*handle))[(*count)++] = byte; ((unsigned char*)(*handle))[(*count)++] = byte;
} }
//BUG: There might be issues here when compiled on big-endian platforms
static void emitInt(unsigned char** handle, unsigned int* capacity, unsigned int* count, unsigned int bytes) { static void emitInt(unsigned char** handle, unsigned int* capacity, unsigned int* count, unsigned int bytes) {
char* ptr = (char*)&bytes; char* ptr = (char*)&bytes;
emitByte(handle, capacity, count, *(ptr++)); emitByte(handle, capacity, count, *(ptr++));
@@ -200,8 +201,8 @@ static unsigned int emitParameters(Toy_Bytecode* mb, Toy_Ast* ast) {
} }
//the address within the data section //the address within the data section
char buffer[128]; char buffer[256];
snprintf(buffer, 128, "%.*s", ast->varDeclare.name->info.length, ast->varDeclare.name->leaf.data); snprintf(buffer, 256, "%.*s", ast->varDeclare.name->info.length, ast->varDeclare.name->leaf.data);
unsigned int dataAddr = emitCStringToData(&(mb->data), &(mb->dataCapacity), &(mb->dataCount), buffer); unsigned int dataAddr = emitCStringToData(&(mb->data), &(mb->dataCapacity), &(mb->dataCount), buffer);
//check the param index for that entry i.e. don't reuse parameter names //check the param index for that entry i.e. don't reuse parameter names
+2 -2
View File
@@ -324,7 +324,7 @@ static Toy_AstFlag literal(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_As
case TOY_TOKEN_LITERAL_INTEGER: { case TOY_TOKEN_LITERAL_INTEGER: {
//filter the '_' character //filter the '_' character
char buffer[parser->previous.length]; char buffer[parser->previous.length + 1];
unsigned int i = 0, o = 0; unsigned int i = 0, o = 0;
do { do {
@@ -341,7 +341,7 @@ static Toy_AstFlag literal(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_As
case TOY_TOKEN_LITERAL_FLOAT: { case TOY_TOKEN_LITERAL_FLOAT: {
//filter the '_' character //filter the '_' character
char buffer[parser->previous.length]; char buffer[parser->previous.length + 1];
unsigned int i = 0, o = 0; unsigned int i = 0, o = 0;
do { do {
+4
View File
@@ -1,5 +1,6 @@
#include "toy_print.h" #include "toy_print.h"
#include <assert.h>
#include <stdio.h> #include <stdio.h>
static Toy_callbackType printCallback = puts; static Toy_callbackType printCallback = puts;
@@ -19,14 +20,17 @@ void Toy_assertFailure(const char* msg) {
} }
void Toy_setPrintCallback(Toy_callbackType cb) { void Toy_setPrintCallback(Toy_callbackType cb) {
assert(cb);
printCallback = cb; printCallback = cb;
} }
void Toy_setErrorCallback(Toy_callbackType cb) { void Toy_setErrorCallback(Toy_callbackType cb) {
assert(cb);
errorCallback = cb; errorCallback = cb;
} }
void Toy_setAssertFailureCallback(Toy_callbackType cb) { void Toy_setAssertFailureCallback(Toy_callbackType cb) {
assert(cb);
assertCallback = cb; assertCallback = cb;
} }
+1 -1
View File
@@ -48,7 +48,7 @@ static void probeAndInsert(Toy_Scope* scope, Toy_String* key, Toy_Value value, T
} }
//if this spot is free, insert and return //if this spot is free, insert and return
if (TOY_VALUE_IS_NULL(scope->data[probe].value)) { if (scope->data[probe].key == NULL) { //fuck my life
scope->data[probe] = entry; scope->data[probe] = entry;
scope->count++; scope->count++;
scope->maxPsl = entry.psl > scope->maxPsl ? entry.psl : scope->maxPsl; scope->maxPsl = entry.psl > scope->maxPsl ? entry.psl : scope->maxPsl;
+2
View File
@@ -73,6 +73,8 @@ static void processRead(Toy_VM* vm) {
//grab the jump as an integer //grab the jump as an integer
unsigned int jump = *((int*)(vm->code + vm->jumpsAddr + READ_INT(vm))); unsigned int jump = *((int*)(vm->code + vm->jumpsAddr + READ_INT(vm)));
//BUG: the jump parameter could cause an out of bounds read if it's malformed
//jumps are relative to the data address //jumps are relative to the data address
char* cstring = (char*)(vm->code + vm->dataAddr + jump); char* cstring = (char*)(vm->code + vm->dataAddr + jump);
+7
View File
@@ -157,4 +157,11 @@ print !false; //true
print a; print a;
} }
{
//Yet Another Cosmic Joke
var a = null;
var i = 42;
print a;
}
//TODO: type casting //TODO: type casting