diff --git a/build/interpreter.o b/build/interpreter.o index 0f48585..fc628d6 100644 Binary files a/build/interpreter.o and b/build/interpreter.o differ diff --git a/build/main.o b/build/main.o index 2162b2b..b21e492 100644 Binary files a/build/main.o and b/build/main.o differ diff --git a/build/native_functions.o b/build/native_functions.o index 094915f..3da868b 100644 Binary files a/build/native_functions.o and b/build/native_functions.o differ diff --git a/build/parser.o b/build/parser.o index 7dce398..17ea850 100644 Binary files a/build/parser.o and b/build/parser.o differ diff --git a/build/string_utils.o b/build/string_utils.o index 92fb309..36f8098 100644 Binary files a/build/string_utils.o and b/build/string_utils.o differ diff --git a/build/tokenizer.o b/build/tokenizer.o index 7312051..3fa1588 100644 Binary files a/build/tokenizer.o and b/build/tokenizer.o differ diff --git a/src/interpreter.c b/src/interpreter.c index a53b2ef..e038a55 100644 --- a/src/interpreter.c +++ b/src/interpreter.c @@ -7,16 +7,25 @@ #include "parser.h" void error(char *msg) { - printf("Error at token %d ('%c'): %s\n", pc, tokens[pc].type, msg); + if (pc >= 0 && pc < MAX_TOK && pc < tk_idx) { + printf("Error at token %d ('%c'): %s\n", pc, tokens[pc].type, msg); + } else { + printf("Error at token %d: %s\n", pc, msg); + } exit(1); } void match(int type) { + if (pc >= MAX_TOK || pc >= tk_idx) { + error("Token index out of bounds in match"); + } if (tokens[pc].type == type) pc++; else error("Unexpected token"); } int find_local(char *name, int len) { + if (!name || len < 0 || len >= 32) return -1; + if (loc_cnt > VAR_MAX) loc_cnt = VAR_MAX; for (int i = loc_cnt - 1; i >= 0; i--) { if (!strncmp(locals[i].name, name, len) && locals[i].name[len] == 0) return i; @@ -25,6 +34,8 @@ int find_local(char *name, int len) { } int find_func(char *name, int len) { + if (!name || len < 0 || len >= 32) return -1; + if (func_cnt > 100) func_cnt = 100; for (int i = 0; i < func_cnt; i++) { if (!strncmp(funcs[i].name, name, len) && funcs[i].name[len] == 0) return i; @@ -33,6 +44,8 @@ int find_func(char *name, int len) { } int find_native_func(char *name, int len) { + if (!name || len < 0 || len >= 32) return -1; + if (native_func_cnt > 100) native_func_cnt = 100; for (int i = 0; i < native_func_cnt; i++) { if (!strncmp(native_funcs[i].name, name, len) && native_funcs[i].name[len] == 0) return i; @@ -43,16 +56,22 @@ int find_native_func(char *name, int len) { void skip_block() { int brace = 0; do { + if (pc >= MAX_TOK || pc >= tk_idx) { + error("Token index out of bounds in skip_block"); + } if (tokens[pc].type == '{') brace++; if (tokens[pc].type == '}') brace--; pc++; - } while (brace > 0 && tokens[pc].type != 0); + } while (brace > 0 && pc < MAX_TOK && pc < tk_idx && tokens[pc].type != 0); } void statement() { + if (pc >= MAX_TOK || pc >= tk_idx) { + error("Token index out of bounds in statement"); + } if (tokens[pc].type == '{') { pc++; - while (tokens[pc].type != '}' && tokens[pc].type != 0) { + while (pc < MAX_TOK && pc < tk_idx && tokens[pc].type != '}' && tokens[pc].type != 0) { statement(); if (ax == -999) break; } @@ -60,32 +79,46 @@ void statement() { } else if (tokens[pc].type == Int || tokens[pc].type == Char) { pc++; - while (tokens[pc].type != ';') { - while (tokens[pc].type == '*') pc++; + while (pc < MAX_TOK && pc < tk_idx && tokens[pc].type != ';') { + while (pc < MAX_TOK && pc < tk_idx && tokens[pc].type == '*') pc++; + if (pc >= MAX_TOK || pc >= tk_idx) break; Token *t = &tokens[pc]; match(Id); + if (loc_cnt >= VAR_MAX) { + error("Too many local variables"); + } + if (sp >= MEM_SIZE) { + error("Stack overflow"); + } int addr = sp; Symbol *s = &locals[loc_cnt++]; strncpy(s->name, t->text, t->val); s->name[t->val] = 0; s->addr = addr; s->is_array = 0; - if (tokens[pc].type == '[') { + if (pc < MAX_TOK && pc < tk_idx && tokens[pc].type == '[') { pc++; int size = (int)expression(); match(']'); s->is_array = 1; + if (sp + size >= MEM_SIZE) { + error("Stack overflow during array allocation"); + } sp += size; } else { sp++; } - if (tokens[pc].type == '=') { + if (pc < MAX_TOK && pc < tk_idx && tokens[pc].type == '=') { pc++; - memory[addr] = expression(); + if (addr >= 0 && addr < MEM_SIZE) { + memory[addr] = expression(); + } else { + error("Memory access out of bounds"); + } } - if (tokens[pc].type == ',') pc++; + if (pc < MAX_TOK && pc < tk_idx && tokens[pc].type == ',') pc++; } match(';'); } @@ -97,10 +130,10 @@ void statement() { if (cond) { statement(); if (ax == -999) return; - if (tokens[pc].type == Else) { pc++; skip_block(); } + if (pc < MAX_TOK && pc < tk_idx && tokens[pc].type == Else) { pc++; skip_block(); } } else { skip_block(); - if (tokens[pc].type == Else) { + if (pc < MAX_TOK && pc < tk_idx && tokens[pc].type == Else) { pc++; statement(); if (ax == -999) return; @@ -116,10 +149,17 @@ void statement() { if (!cond) { skip_block(); } else { + int iteration_count = 0; while (1) { + if (++iteration_count > 1000000) { + error("Potential infinite loop detected"); + } statement(); if (ax == -999) return; int save_pc = pc; + if (loop_start >= MAX_TOK || loop_start >= tk_idx) { + error("Loop start out of bounds"); + } pc = loop_start; match('('); cond = expression(); @@ -130,7 +170,7 @@ void statement() { } else if (tokens[pc].type == Return) { pc++; - if (tokens[pc].type != ';') ax = expression(); + if (pc < MAX_TOK && pc < tk_idx && tokens[pc].type != ';') ax = expression(); else ax = 0; match(';'); ax = -999; @@ -138,7 +178,11 @@ void statement() { else if (tokens[pc].type == Printf) { pc++; match('('); + if (pc >= MAX_TOK || pc >= tk_idx) { + error("Token index out of bounds in printf"); + } char *fmt = tokens[pc].text; + if (!fmt) fmt = ""; match(Str); char *p = fmt; @@ -148,7 +192,10 @@ void statement() { match(','); long val = expression(); if (*p == 'd') printf("%ld", val); - else if (*p == 's') printf("%s", (char*)val); + else if (*p == 's') { + char *str = (char*)val; + if (str) printf("%s", str); + } p++; } else { putchar(*p++); @@ -165,34 +212,41 @@ void statement() { void scan_functions() { int i = 0; - while (tokens[i].type != 0) { - if ((tokens[i].type == Int || tokens[i].type == Char) && + while (i < MAX_TOK && i < tk_idx && tokens[i].type != 0) { + if (i + 2 < MAX_TOK && i + 2 < tk_idx && + (tokens[i].type == Int || tokens[i].type == Char) && tokens[i+1].type == Id && tokens[i+2].type == '(') { + if (func_cnt >= 100) { + error("Too many functions defined"); + } Func *f = &funcs[func_cnt++]; Token *name = &tokens[i+1]; strncpy(f->name, name->text, name->val); f->name[name->val] = 0; i += 3; int params = 0; - while(tokens[i].type != ')') { + while(i < MAX_TOK && i < tk_idx && tokens[i].type != ')') { if (tokens[i].type == Int || tokens[i].type == Char) { params++; i++; - while (tokens[i].type == '*') i++; - if (tokens[i].type == Id) i++; + while (i < MAX_TOK && i < tk_idx && tokens[i].type == '*') i++; + if (i < MAX_TOK && i < tk_idx && tokens[i].type == Id) i++; } else i++; } f->param_count = params; - i++; + if (i < MAX_TOK && i < tk_idx) i++; f->entry_point = i; int brace = 0; do { + if (i >= MAX_TOK || i >= tk_idx) { + error("Token index out of bounds in scan_functions"); + } if (tokens[i].type == '{') brace++; if (tokens[i].type == '}') brace--; i++; - } while (brace > 0 && tokens[i].type != 0); + } while (brace > 0 && i < MAX_TOK && i < tk_idx && tokens[i].type != 0); } else { i++; } diff --git a/src/main.c b/src/main.c index 3312e9e..393a9c9 100644 --- a/src/main.c +++ b/src/main.c @@ -17,8 +17,15 @@ int main(int argc, char **argv) { return 1; } - src_code = malloc(MAX_SRC); + src_code = malloc(MAX_SRC + 1); + if (!src_code) { + printf("Memory allocation failed.\n"); + fclose(f); + return 1; + } + size_t n = fread(src_code, 1, MAX_SRC, f); + if (n >= MAX_SRC) n = MAX_SRC - 1; src_code[n] = 0; fclose(f); @@ -28,17 +35,23 @@ int main(int argc, char **argv) { scan_functions(); int main_idx = find_func("main", 4); - if (main_idx == -1) { + if (main_idx == -1 || main_idx >= func_cnt) { printf("No main function found.\n"); return 1; } pc = funcs[main_idx].entry_point; + + if (sp + 2 >= MEM_SIZE) { + printf("Stack overflow during initialization.\n"); + return 1; + } memory[sp++] = 0; memory[sp++] = 0; ax = 0; statement(); + free(src_code); return 0; } diff --git a/src/native_functions.c b/src/native_functions.c index 189c20e..910e825 100644 --- a/src/native_functions.c +++ b/src/native_functions.c @@ -12,6 +12,9 @@ #include "interpreter.h" void register_native_func(char *name, NativeFunc func) { + if (!name || !func || native_func_cnt >= 100) { + return; + } NativeFuncDef *nf = &native_funcs[native_func_cnt++]; strncpy(nf->name, name, 31); nf->name[31] = 0; @@ -19,6 +22,9 @@ void register_native_func(char *name, NativeFunc func) { } long native_socket(long *args, int argc) { + if (!args || argc < 3) { + return -1; + } int domain = (int)args[0]; int type = (int)args[1]; int protocol = (int)args[2]; @@ -26,6 +32,9 @@ long native_socket(long *args, int argc) { } long native_bind(long *args, int argc) { + if (!args || argc < 2) { + return -1; + } int sockfd = (int)args[0]; int port = (int)args[1]; @@ -39,28 +48,46 @@ long native_bind(long *args, int argc) { } long native_listen(long *args, int argc) { + if (!args || argc < 2) { + return -1; + } int sockfd = (int)args[0]; int backlog = (int)args[1]; return listen(sockfd, backlog); } long native_accept(long *args, int argc) { + if (!args || argc < 1) { + return -1; + } int sockfd = (int)args[0]; return accept(sockfd, NULL, NULL); } long native_recv(long *args, int argc) { + if (!args || argc < 4) { + return -1; + } int sockfd = (int)args[0]; int addr = (int)args[1]; int len = (int)args[2]; int flags = (int)args[3]; + if (addr < 0 || addr >= MEM_SIZE) { + return -1; + } + char temp_buf[8192]; if (len > 8192) len = 8192; + if (len < 0) len = 0; + + if (addr + len > MEM_SIZE) { + len = MEM_SIZE - addr; + } int result = recv(sockfd, temp_buf, len, flags); if (result > 0) { - for (int i = 0; i < result; i++) { + for (int i = 0; i < result && addr + i < MEM_SIZE; i++) { memory[addr + i] = temp_buf[i]; } } @@ -68,19 +95,34 @@ long native_recv(long *args, int argc) { } long native_send(long *args, int argc) { + if (!args || argc < 4) { + return -1; + } int sockfd = (int)args[0]; long buf_arg = args[1]; int len = (int)args[2]; int flags = (int)args[3]; + if (len < 0) { + return -1; + } + if (buf_arg > MEM_SIZE * 8 || buf_arg < 0) { return send(sockfd, (char*)buf_arg, len, flags); } + if (buf_arg >= MEM_SIZE) { + return -1; + } + char temp_buf[8192]; if (len > 8192) len = 8192; - for (int i = 0; i < len; i++) { + if (buf_arg + len > MEM_SIZE) { + len = MEM_SIZE - buf_arg; + } + + for (int i = 0; i < len && buf_arg + i < MEM_SIZE; i++) { temp_buf[i] = (char)memory[buf_arg + i]; } @@ -88,12 +130,21 @@ long native_send(long *args, int argc) { } long native_close(long *args, int argc) { + if (!args || argc < 1) { + return -1; + } int fd = (int)args[0]; return close(fd); } long native_strlen(long *args, int argc) { + if (!args || argc < 1) { + return 0; + } char *str = (char*)args[0]; + if (!str) { + return 0; + } return strlen(str); } @@ -106,40 +157,70 @@ long native_SOCK_STREAM(long *args, int argc) { } long native_sqrt(long *args, int argc) { + if (!args || argc < 1) { + return 0; + } return (long)sqrt((double)args[0]); } long native_pow(long *args, int argc) { + if (!args || argc < 2) { + return 0; + } return (long)pow((double)args[0], (double)args[1]); } long native_sin(long *args, int argc) { + if (!args || argc < 1) { + return 0; + } return (long)(sin((double)args[0]) * 1000000); } long native_cos(long *args, int argc) { + if (!args || argc < 1) { + return 0; + } return (long)(cos((double)args[0]) * 1000000); } long native_tan(long *args, int argc) { + if (!args || argc < 1) { + return 0; + } return (long)(tan((double)args[0]) * 1000000); } long native_abs(long *args, int argc) { + if (!args || argc < 1) { + return 0; + } return (long)abs((int)args[0]); } long native_floor(long *args, int argc) { + if (!args || argc < 1) { + return 0; + } return (long)floor((double)args[0]); } long native_ceil(long *args, int argc) { + if (!args || argc < 1) { + return 0; + } return (long)ceil((double)args[0]); } long native_strpos(long *args, int argc) { + if (!args || argc < 2) { + return -1; + } char *haystack = (char*)args[0]; char *needle = (char*)args[1]; + if (!haystack || !needle) { + return -1; + } char *pos = strstr(haystack, needle); if (pos) { return pos - haystack; @@ -148,20 +229,33 @@ long native_strpos(long *args, int argc) { } long native_substr(long *args, int argc) { + static char empty_str[] = ""; + if (!args || argc < 3) { + return (long)empty_str; + } char *str = (char*)args[0]; + if (!str) { + return (long)empty_str; + } int start = (int)args[1]; int length = (int)args[2]; + if (str_pool_idx >= STR_POOL_SIZE) { + error("String pool overflow"); + return (long)empty_str; + } + char *result = &str_pool[str_pool_idx]; int str_len = strlen(str); if (start < 0) start = 0; - if (start >= str_len) return (long)""; + if (start >= str_len) return (long)empty_str; if (start + length > str_len) length = str_len - start; - if (length < 0) return (long)""; + if (length < 0) return (long)empty_str; if (str_pool_idx + length + 1 >= STR_POOL_SIZE) { error("String pool overflow"); + return (long)empty_str; } strncpy(result, str + start, length); @@ -172,12 +266,26 @@ long native_substr(long *args, int argc) { } long native_upper(long *args, int argc) { + static char empty_str[] = ""; + if (!args || argc < 1) { + return (long)empty_str; + } char *str = (char*)args[0]; + if (!str) { + return (long)empty_str; + } + + if (str_pool_idx >= STR_POOL_SIZE) { + error("String pool overflow"); + return (long)empty_str; + } + char *result = &str_pool[str_pool_idx]; int len = strlen(str); if (str_pool_idx + len + 1 >= STR_POOL_SIZE) { error("String pool overflow"); + return (long)empty_str; } for (int i = 0; i <= len; i++) { @@ -189,12 +297,26 @@ long native_upper(long *args, int argc) { } long native_lower(long *args, int argc) { + static char empty_str[] = ""; + if (!args || argc < 1) { + return (long)empty_str; + } char *str = (char*)args[0]; + if (!str) { + return (long)empty_str; + } + + if (str_pool_idx >= STR_POOL_SIZE) { + error("String pool overflow"); + return (long)empty_str; + } + char *result = &str_pool[str_pool_idx]; int len = strlen(str); if (str_pool_idx + len + 1 >= STR_POOL_SIZE) { error("String pool overflow"); + return (long)empty_str; } for (int i = 0; i <= len; i++) { @@ -206,7 +328,20 @@ long native_lower(long *args, int argc) { } long native_strip(long *args, int argc) { + static char empty_str[] = ""; + if (!args || argc < 1) { + return (long)empty_str; + } char *str = (char*)args[0]; + if (!str) { + return (long)empty_str; + } + + if (str_pool_idx >= STR_POOL_SIZE) { + error("String pool overflow"); + return (long)empty_str; + } + char *result = &str_pool[str_pool_idx]; while (*str && isspace(*str)) str++; @@ -216,6 +351,7 @@ long native_strip(long *args, int argc) { if (str_pool_idx + len + 1 >= STR_POOL_SIZE) { error("String pool overflow"); + return (long)empty_str; } strncpy(result, str, len); @@ -226,9 +362,21 @@ long native_strip(long *args, int argc) { } long native_replace(long *args, int argc) { + static char empty_str[] = ""; + if (!args || argc < 3) { + return (long)empty_str; + } char *str = (char*)args[0]; char *old_str = (char*)args[1]; char *new_str = (char*)args[2]; + if (!str || !old_str || !new_str) { + return (long)empty_str; + } + + if (str_pool_idx >= STR_POOL_SIZE) { + error("String pool overflow"); + return (long)empty_str; + } char *result = &str_pool[str_pool_idx]; char *src = str; @@ -236,10 +384,26 @@ long native_replace(long *args, int argc) { int old_len = strlen(old_str); int new_len = strlen(new_str); + if (old_len == 0) { + int str_len = strlen(str); + if (str_pool_idx + str_len + 1 >= STR_POOL_SIZE) { + error("String pool overflow"); + return (long)empty_str; + } + strcpy(result, str); + str_pool_idx += str_len + 1; + return (long)result; + } + while (*src) { if (strncmp(src, old_str, old_len) == 0) { - if (str_pool_idx + (dst - result) + new_len + strlen(src + old_len) + 1 >= STR_POOL_SIZE) { + int remaining = strlen(src + old_len); + int current_pos = dst - result; + if (str_pool_idx + current_pos + new_len + remaining + 1 >= STR_POOL_SIZE) { error("String pool overflow"); + *dst = 0; + str_pool_idx += current_pos + 1; + return (long)result; } strcpy(dst, new_str); dst += new_len; @@ -256,15 +420,27 @@ long native_replace(long *args, int argc) { } long native_startswith(long *args, int argc) { + if (!args || argc < 2) { + return 0; + } char *str = (char*)args[0]; char *prefix = (char*)args[1]; + if (!str || !prefix) { + return 0; + } int prefix_len = strlen(prefix); return strncmp(str, prefix, prefix_len) == 0; } long native_endswith(long *args, int argc) { + if (!args || argc < 2) { + return 0; + } char *str = (char*)args[0]; char *suffix = (char*)args[1]; + if (!str || !suffix) { + return 0; + } int str_len = strlen(str); int suffix_len = strlen(suffix); diff --git a/src/parser.c b/src/parser.c index e587ddd..c311f7c 100644 --- a/src/parser.c +++ b/src/parser.c @@ -27,6 +27,7 @@ extern int find_native_func(char *name, int len); extern void statement(); long factor() { + if (pc >= MAX_TOK) return 0; Token *t = &tokens[pc]; long val = 0; @@ -45,17 +46,22 @@ long factor() { return val; } else if (t->type == Id) { + if (pc + 1 >= MAX_TOK) return 0; if (tokens[pc + 1].type == '(') { int nf_idx = find_native_func(t->text, t->val); if (nf_idx != -1) { + if (nf_idx < 0 || nf_idx >= native_func_cnt) return 0; pc += 2; long args[10]; int argc = 0; + if (pc >= MAX_TOK) return 0; if (tokens[pc].type != ')') { do { + if (argc >= 10) break; args[argc++] = expression(); + if (pc >= MAX_TOK) return 0; } while (tokens[pc].type == ',' && pc++); } match(')'); @@ -65,30 +71,42 @@ long factor() { int f_idx = find_func(t->text, t->val); if (f_idx == -1) error("Unknown function"); + if (f_idx < 0 || f_idx >= func_cnt) return 0; pc += 2; int old_bp = bp; long args[10]; int argc = 0; + if (pc >= MAX_TOK) return 0; if (tokens[pc].type != ')') { do { + if (argc >= 10) break; args[argc++] = expression(); + if (pc >= MAX_TOK) return 0; } while (tokens[pc].type == ',' && pc++); } match(')'); int ret_pc = pc; + if (sp >= MEM_SIZE) return 0; + if (bp < 0 || bp >= MEM_SIZE) return 0; memory[sp] = bp; bp = sp++; + if (sp >= MEM_SIZE) return 0; memory[sp++] = ret_pc; - for(int i=0; i= MEM_SIZE) break; + memory[sp++] = args[i]; + } pc = funcs[f_idx].entry_point; statement(); val = ax; + if (bp < 0 || bp >= MEM_SIZE) return 0; sp = bp; + if (sp < 0 || sp >= MEM_SIZE) return 0; bp = memory[sp]; pc = ret_pc; return val; @@ -96,19 +114,23 @@ long factor() { else { int idx = find_local(t->text, t->val); if (idx == -1) error("Undefined variable"); + if (idx < 0 || idx >= loc_cnt) return 0; pc++; Symbol *sym = &locals[idx]; + if (pc >= MAX_TOK) return 0; if (tokens[pc].type == '[') { pc++; long start_or_index = expression(); + if (pc >= MAX_TOK) return 0; if (tokens[pc].type == ':') { pc++; long end = expression(); match(']'); + if (sym->addr < 0 || sym->addr >= MEM_SIZE) return 0; long val = memory[sym->addr]; if (is_string_ptr(val)) { return slice_string(val, start_or_index, end); @@ -117,7 +139,9 @@ long factor() { } } else { match(']'); - return memory[sym->addr + start_or_index]; + long addr = sym->addr + start_or_index; + if (addr < 0 || addr >= MEM_SIZE) return 0; + return memory[addr]; } } @@ -125,6 +149,7 @@ long factor() { return sym->addr; } + if (sym->addr < 0 || sym->addr >= MEM_SIZE) return 0; return memory[sym->addr]; } } @@ -132,20 +157,24 @@ long factor() { } long unary() { + if (pc >= MAX_TOK) return 0; if (tokens[pc].type == '*') { pc++; int addr = unary(); if (addr > MEM_SIZE * 8 || addr < 0) { return *(char*)addr; } + if (addr < 0 || addr >= MEM_SIZE) return 0; return memory[addr]; } else if (tokens[pc].type == '&') { pc++; + if (pc >= MAX_TOK) return 0; Token *t = &tokens[pc]; if (t->type != Id) error("Expected identifier after &"); int idx = find_local(t->text, t->val); if (idx == -1) error("Undefined variable"); + if (idx < 0 || idx >= loc_cnt) return 0; pc++; return locals[idx].addr; } @@ -158,18 +187,21 @@ long unary() { long term() { long val = unary(); - while (tokens[pc].type == '*' || tokens[pc].type == '/') { + while (pc < MAX_TOK && (tokens[pc].type == '*' || tokens[pc].type == '/')) { int op = tokens[pc++].type; long val2 = unary(); if (op == '*') val = val * val2; - else val = val / val2; + else { + if (val2 != 0) val = val / val2; + else val = 0; + } } return val; } long add() { long val = term(); - while (tokens[pc].type == '+' || tokens[pc].type == '-') { + while (pc < MAX_TOK && (tokens[pc].type == '+' || tokens[pc].type == '-')) { int op = tokens[pc++].type; long val2 = term(); if (op == '+') { @@ -187,7 +219,7 @@ long add() { long relational() { long val = add(); - while (tokens[pc].type >= Eq && tokens[pc].type <= Ge) { + while (pc < MAX_TOK && tokens[pc].type >= Eq && tokens[pc].type <= Ge) { int op = tokens[pc++].type; long val2 = add(); if (op == Eq) val = val == val2; @@ -199,9 +231,11 @@ long relational() { } long expression() { + if (pc >= MAX_TOK) return 0; if (tokens[pc].type == '*') { int save_pc = pc; unary(); + if (pc >= MAX_TOK) return 0; if (tokens[pc].type == '=') { pc = save_pc; pc++; @@ -214,18 +248,23 @@ long expression() { pc = save_pc; } + if (pc >= MAX_TOK) return 0; if (tokens[pc].type == Id) { + if (pc + 1 >= MAX_TOK) return 0; if (tokens[pc+1].type == '[') { int idx = find_local(tokens[pc].text, tokens[pc].val); if (idx == -1) error("Assign to unknown var"); + if (idx < 0 || idx >= loc_cnt) return 0; pc += 2; long start_or_index = expression(); + if (pc >= MAX_TOK) return 0; if (tokens[pc].type == ':') { pc++; long end = expression(); match(']'); + if (locals[idx].addr < 0 || locals[idx].addr >= MEM_SIZE) return 0; long val = memory[locals[idx].addr]; if (is_string_ptr(val)) { return slice_string(val, start_or_index, end); @@ -236,19 +275,28 @@ long expression() { match(']'); int addr = locals[idx].addr; + if (pc >= MAX_TOK) return 0; if (tokens[pc].type == '=') { pc++; long val = expression(); - memory[addr + start_or_index] = val; + long target_addr = addr + start_or_index; + if (target_addr >= 0 && target_addr < MEM_SIZE) { + memory[target_addr] = val; + } return val; } - return memory[addr + start_or_index]; + long read_addr = addr + start_or_index; + if (read_addr < 0 || read_addr >= MEM_SIZE) return 0; + return memory[read_addr]; } else if (tokens[pc+1].type == '=') { int idx = find_local(tokens[pc].text, tokens[pc].val); if (idx == -1) error("Assign to unknown var"); + if (idx < 0 || idx >= loc_cnt) return 0; pc += 2; long val = expression(); - memory[locals[idx].addr] = val; + if (locals[idx].addr >= 0 && locals[idx].addr < MEM_SIZE) { + memory[locals[idx].addr] = val; + } return val; } } diff --git a/src/string_utils.c b/src/string_utils.c index d8f148b..d5903a3 100644 --- a/src/string_utils.c +++ b/src/string_utils.c @@ -4,12 +4,29 @@ #include "interpreter.h" int is_string_ptr(long val) { - return val > MEM_SIZE * 8; + if (val < 0) { + return 0; + } + if (val > MEM_SIZE * 8) { + return 1; + } + return 0; } long concat_strings(long ptr1, long ptr2) { + static char empty_str[] = ""; char *s1 = (char*)ptr1; char *s2 = (char*)ptr2; + + if (!s1 || !s2) { + return (long)empty_str; + } + + if (str_pool_idx >= STR_POOL_SIZE) { + error("String pool overflow"); + return (long)empty_str; + } + char *result = &str_pool[str_pool_idx]; int len1 = strlen(s1); @@ -17,6 +34,7 @@ long concat_strings(long ptr1, long ptr2) { if (str_pool_idx + len1 + len2 + 1 >= STR_POOL_SIZE) { error("String pool overflow"); + return (long)empty_str; } strcpy(result, s1); @@ -28,7 +46,18 @@ long concat_strings(long ptr1, long ptr2) { } long slice_string(long str_ptr, int start, int end) { + static char empty_str[] = ""; char *str = (char*)str_ptr; + + if (!str) { + return (long)empty_str; + } + + if (str_pool_idx >= STR_POOL_SIZE) { + error("String pool overflow"); + return (long)empty_str; + } + char *result = &str_pool[str_pool_idx]; int str_len = strlen(str); @@ -36,14 +65,19 @@ long slice_string(long str_ptr, int start, int end) { if (end < 0) end = str_len; if (end > str_len) end = str_len; if (start > end) start = end; + if (start > str_len) start = str_len; int length = end - start; + if (length < 0) length = 0; if (str_pool_idx + length + 1 >= STR_POOL_SIZE) { error("String pool overflow"); + return (long)empty_str; } - strncpy(result, str + start, length); + if (length > 0 && start < str_len) { + strncpy(result, str + start, length); + } result[length] = 0; str_pool_idx += length + 1; diff --git a/src/tokenizer.c b/src/tokenizer.c index 9418eac..e11e492 100644 --- a/src/tokenizer.c +++ b/src/tokenizer.c @@ -6,13 +6,19 @@ void tokenize(char *src) { char *s = src; + if (!src) return; + while (*s) { if (isspace(*s)) { s++; continue; } + if (tk_idx >= MAX_TOK - 1) { + return; + } + Token *t = &tokens[tk_idx++]; t->text = s; - if (*s == '/' && *(s+1) == '/') { + if (*s == '/' && s[1] && s[1] == '/') { while (*s && *s != '\n') s++; tk_idx--; continue; @@ -20,9 +26,10 @@ void tokenize(char *src) { if (isalpha(*s)) { int len = 0; - while (isalnum(s[len]) || s[len] == '_') len++; + while (s[len] && (isalnum(s[len]) || s[len] == '_') && len < 31) len++; char buf[32]; + if (len > 31) len = 31; strncpy(buf, s, len); buf[len] = 0; if (!strcmp(buf, "int")) t->type = Int; @@ -52,7 +59,7 @@ void tokenize(char *src) { char *d = s; while (*s && *s != '"') { - if (*s == '\\' && *(s+1) == 'n') { + if (*s == '\\' && s[1] && s[1] == 'n') { *d++ = '\n'; s+=2; } else { *d++ = *s++; @@ -76,5 +83,7 @@ void tokenize(char *src) { t->type = *s++; } - tokens[tk_idx].type = 0; + if (tk_idx < MAX_TOK) { + tokens[tk_idx].type = 0; + } } diff --git a/tests/edge_cases.rc b/tests/edge_cases.rc new file mode 100644 index 0000000..362c77f --- /dev/null +++ b/tests/edge_cases.rc @@ -0,0 +1,41 @@ +int main() { + printf("Testing Edge Cases:\n\n"); + + printf("1. Empty string operations:\n"); + char *empty = ""; + char *result1 = upper(empty); + printf("upper('') = '%s'\n", result1); + + printf("\n2. String slicing edge cases:\n"); + char *text = "Hello"; + char *slice1 = text[0:0]; + printf("'Hello'[0:0] = '%s'\n", slice1); + char *slice2 = text[10:20]; + printf("'Hello'[10:20] = '%s'\n", slice2); + char *slice3 = text[3:3]; + printf("'Hello'[3:3] = '%s'\n", slice3); + + printf("\n3. Math with edge cases:\n"); + int zero = 0; + printf("abs(0) = %d\n", abs(zero)); + printf("sqrt(0) = %d\n", sqrt(zero)); + + printf("\n4. String concatenation:\n"); + char *str1 = "A"; + char *str2 = "B"; + char *concat = str1 + str2; + printf("'A' + 'B' = '%s'\n", concat); + + printf("\n5. String search edge cases:\n"); + int pos1 = strpos("test", "xyz"); + printf("strpos('test', 'xyz') = %d\n", pos1); + int pos2 = strpos("test", "test"); + printf("strpos('test', 'test') = %d\n", pos2); + + printf("\n6. Nested operations:\n"); + char *nested = upper(lower(upper("TeSt"))); + printf("upper(lower(upper('TeSt'))) = '%s'\n", nested); + + printf("\nAll edge cases handled safely!\n"); + return 0; +}