From bd8d9d819ed4fafca64c94b9836c13303bbf91e4 Mon Sep 17 00:00:00 2001 From: retoor Date: Sat, 22 Nov 2025 23:15:15 +0100 Subject: [PATCH] Update. --- build/interpreter.o | Bin 8736 -> 12496 bytes build/main.o | Bin 3080 -> 3616 bytes build/native_functions.o | Bin 14704 -> 14424 bytes build/parser.o | Bin 8992 -> 9536 bytes build/string_utils.o | Bin 2792 -> 3168 bytes build/tokenizer.o | Bin 3320 -> 3448 bytes src/interpreter.c | 94 +++++++++++++++----- src/main.c | 17 +++- src/native_functions.c | 186 +++++++++++++++++++++++++++++++++++++-- src/parser.c | 66 ++++++++++++-- src/string_utils.c | 38 +++++++- src/tokenizer.c | 17 +++- tests/edge_cases.rc | 41 +++++++++ 13 files changed, 417 insertions(+), 42 deletions(-) create mode 100644 tests/edge_cases.rc diff --git a/build/interpreter.o b/build/interpreter.o index 0f485858e58524ef67216390d8d3010f0007b050..fc628d60cf0706489a4043585f7507499637b002 100644 GIT binary patch literal 12496 zcmd5@ac~q>ntzj!5Ft)SHewW%Q3E6hsSKjWKyatY1Ufn>g^BAb8i&b5azK)s>4BgL zFxwe*7#ec7daGCKg6CPgWtCgEwJxh$$cBUfQmd6^b+t}b+&yIzqnzBj7^0B-zSr+f zzBJR`)%wr9s_uUMd*AoH-}~P8zW1gB+iQX=a$GJZi;LaH#@{5$Soi$#x}R75>(~XaY2jYYyd1IG z)Cd>RHuRJTm2{y?C=9=$%-Vrc*dOmL58swyPut6v@|Vu*weWyu7Ov4u-m|ajc>Efp z$Ccu(nsKn&{ST;X)d%`A`bW7*?DDn0z-`!U8t1Ca@>_iG5sZOt9kRVE zkmfE2x~g%par>H@18Ffmg?=psQ77MySpmB};_dOC8?Lg(VT^PtPxdJLd&-X( zy{^P)5d@m@RFCQ#@GEG@r7>ml*2Go@ua(0#-0;CXdO0Z&)$EgxJu+ z5Z{yh=|Dd-1|Ky>+*_uJm7s+ueNS@@+&1<>w^&b>EBNwJ_KbojtRbXX3m*e{pO~%qySJ z@58&8&;;;Ff(0eH4ZzI65?}HWB)_@qk70J3ivWP@g#Bov7dIQV*!h6)|2Iz0&ne%~D)o1b=_|%_f`7-@?D%w5*&ir%RW&MI zCxJs%OzCOl=|`G6JzTdkhLP$_aDmcLe#WU1x7kV>In#k%%BDP(~wYn zy~^(QF|lNp1uU)?Kp29=Vr*MnBsQ&VwGXZEb-HZ{O;018`n+V1K1XIFED(6@k5W*0yxhN1il1I6mv+RiW#m0hSb zbQ-I({0tKJWDy*R^WWoh_B@X%m^jEBW*Ao4Y^*NB?OEC50y2R#KhUU&^OhI>hze%m z4s$gK2TKcs<|6IY&*~X_#RG~~B-S1}ouh?+SL=HdP7-Tsm1=nEZ^IPdQ=p|c7X{1D zYQ95Ss<>2BRvr_3SFP(vF!cqWdM#aC8c2g}_2`N+q@y00G@aF??krUkU*YQ4^J;vb zbX>2Rs>pu=kI$QsJGyJbhh+}DU+GH2n8sB^ezJnA#`n>-gPlTZMq#DkPPtNW;pVje$!tJTzV}aCvg4?V~?H^Cr;0185vWo%5p&7_?Je*`4|1*fo9c$-!ZWlY& zYM>~TFcD^g_>%Pn+Yz!Rxlf#G)WnFzYXS0-PV>M^?YPq(P?8wexjc4j%!gbUEzq@f zjuwF&NEenWyWg?xDl&ibg#J?;03M-urltq`A>6mDh@^SF|BJD)2{ZdL0FvZSppG-U z;Y3NI<4UpBeIGzFxf2~RH0Rvd*u>mnP2-RW-SgC{dnd$o=6vr!`y>oElZS`;AS9{! zH>qbkuZ#0t(Bv^zf4BEN{*#6u=iun%gY&h>b85QyaPovc7t(X$%ggx*@I{y~^Nt+f zQ0LUd#|BKEG3we}lIrsfcN_;d6_Dc@x5JlAty%n5VhQH2_}g0ebv&l1M%8c1;zxsF z-mPj}2rGN`f^F5TalN`vVeFs>#DnQa3M}8=VFq4eL2JsjLm%X7zGJm!RlcTFAJfVY zX}+_NncmdW(V}2#lt;kwBa;@xzLG15cijrcz2|&`9oGzR&g5&c-AsZu-(cs1Vud4J zJQkMg)rlcK#vYe(-nHeoaH!@Q`XXQd_N#|0x*PhwWS;&Z9P4)N z2Go1P*RSmDbq(BM*1g2MuY>j9r=q2)Mr{&*o6H zIkawLB*yO6L*Wgc*3FS<)5g{7giq6B=f3Y-F=z<9#&6Tf%yCYfH@27-?#5i8O)>u+;GpG`BQH+9z7@G`9ddJ-q(^ zAQ#)v+}5xThOy!6?Ez6evMJJ{Gus$Fjqzx6%fp^fG#Y}DZbXkDTgFzm>LA|?{%LLj z-pzUh+y!H9jOg5#7Q6pt9Bp7+Z{ng~JKk70)Y6dglr;UfJy%v&FY%PsuZy?nagX=r zikmAc7u*`>uM4*=TvSoHs9eC@J{(`*s}5thMXbEDp24ozgBToPcqtZ7*CT6~tG&oI zqi}LTH!R)~z-NlKW_;GTi&S?(zzxQ*ZLw&(2cMd|C_cqqpiZ^$I??tVK3BMl%$()! zl3lr~+w<5Y)m>)f1>BW6ZByK3)ozdKE?Mp_TJA2meJZO0@ou5JQ|RtST{CyN+p`OG zAInqSl}3I}gQX2^mUaNT=K2HQKp%Zk1Y^g-x#v8E!)5;t7vEOl`P<9j24mWTymlim zbJB8m*)HVuSib6BY)lTgSLgiW6!&64fH6p9SXNKXc_C|qIyHAqu2W0BQ%laptSU9= ziy&Ml#aLFsq-W)J`*T)iwZ=UQ`VIxVn8ePGWoypO`sER0Z}KJLus=b`W7pYQ ztoY;yoCz&g^Ede6Xe*X}9^)q&(sm=S=QDnoCb;#U&sGx*t9%n>`K;ZBFXZoe?8i3T zS`T^bc^iHkf6r(8YJIp$4)_xexaojD2{`g;gC`cAf8hBq za3MZ`AQZlS;rRkw*?7L>fWPd39{?Qf?+|NB&fEJA@@E|IBf?G*u1P4;&O1=g#`Dh( z_~(ElpMAoP94{_J#8-<1&+`>vmjUl=_KO|xs~qs_9Pk?*@Hr0nA_sga;K;x7av%+b z=PsXUM}k8T3)Wl-wiuC?hRo$ zh48l+i|Nsp@TNA#C2;$Uvle~le`0;1_gae1YD4f^u5EE*LE*jx{ z#@ga~n8n(FD(|yxE9bh2AMjY#(?=ot6bgpVbhzMGDlh!=iNLQS_#CKXL3unsNO>zC zS{R-SB#wJI7L>(YEpeHT(9Sgk|1Q+AAdcBy%7+nzf_A9=M>u*Z|HlbV`Tv06v|r2* zSnPiInFVt^AL^3Net{#OD+&IZz|juwZc@Hi;CA_si9GsT$}156SkMmcWfGq!aI`av z;OmGy+8Gh^_zc0XC-Ofd_zeU{o+|g;;#~U+V63K(|(5uPUZ8^FciCg{@wxaAUL)EEWxS$UpU|&Ip7}) z93OPNpE=0qV6uRM{3)NC2u}IjDsVK1IZgT#|LTOr?uWYwPVH|dIJIwmTe0lmPX%dz zH|dwg&t3;R?>OKmi5=>nKRL*MPH@V91|~Hq_VF$gIQnNUT#|o)$d>~y*J(Y$sr|JC zr~YYiz&jl9guw0b@VJBgGX$r6enoJ~2meNf#qNi99q@ci?pfqD2Yfrh=YgK|=Mw_Q zaot4lr-?k}`69vTxZWT*l^=D$r(sfqVjpiQ!Kr;!;P!Y}N#tq2cM_b&NfW`T{ig^{ z?er3y%D+x;979jaA18Kb-WVkE)Xskqocisr1gHL)J_S01VvmP12YihK9ws>Lw~OGk-?YH( z>$=ZDe!xNgJqP)Z2wnl>lm2A*aRdsEm+~wjcsaDm{8mA5D!+>0RQ^7K)A6=D;GF`u z`=QH0{%L|!KKlty zGX;+Rr+%AHaLRKT!RdHI1gG+y0=N6qaFE|gaO5L-K1*;+r4s*FVxRhFKat0(l&)It7pB9GtPr2X>_@=W{=$N9qV2U0#y;PyBv zB=T1f`70dcONjh5B7d!e{I`ibJwLA^IE|CT1jpYmlK*K3{J#l)1ChT9oeKrWy8td} zXRY<&lIN3e5j-StyMJ^dUrgk;I>>_vFX(@~E*JY5+QlOAm&N&BG-vQv1TLmGgC7vM z{3ayr^avceVUalg>mV!`!&oGKOyKfw1rq;_z&%`gT;3yym)h`BftT6vcZHq#HvFWJ zue9OE#Cdm-4L>X#v)G1D73U<64HvKcZwgqK<7yKP_ll>)2gLi6He7x$e9MN*?|=CH z4U4q14=YgS+i>|k?*khyzmu_w*w#&YXdOKDsP$YgYthKYP=y|8*I7klNDr}!b+H($ zh_>PjihC>Is~CNSk7r!R!dOMPbrb*VT15-|)vN;kjI;p0N5LQEtoMgo;uUSt*0xAg z-zpR%>l>P)p-mBMEZ^kr0c9MrIF4sb`9-Z$tQ*-N<5|AXfC`3+UjpJ;hRFlUPlP@$ zZ|p~|9~tL!1TMl5-mLPPtzU_Y>5;Dt;}&iHt@>WjMVsHoEWp-3fMw0t1?mw7?9N#62_At>uo2A_qv*<>kp**M4`FZ=k5gucgSL-Lof2^F+y z*RK@%Wwr*p{u7{^&3}t;vU=#T9t{15IbP~Z|7GhNRqiduJ7YUU9>s9RbA?_1GQjMy e3lMu(ba1=PVYXNJKLy$KM+E;LpfOVH`u_toB`Zz< literal 8736 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 diff --git a/build/native_functions.o b/build/native_functions.o index 094915f7743ca0130856f2c8a77983566e4a3d60..3da868b8137593628bb0272182e16cecfd2cdbc9 100644 GIT binary patch literal 14424 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 Tw^5W`$y61I9afZk+U@@j2!gnG diff --git a/build/parser.o b/build/parser.o index 7dce398069ae995d6998bff5e56903b9cc852e95..17ea85013d7753b586979e76435ccef8b6094ca0 100644 GIT binary patch literal 9536 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 E-%VZJW&i*H 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; +}