+ Builtins, strong types, - buffer overflow

This commit is contained in:
attilavs2 2025-03-24 18:28:51 +01:00
parent b5f0ebc258
commit dc208aed7c
4 changed files with 121 additions and 43 deletions

View file

@ -76,8 +76,9 @@ typedef struct {
typedef struct { typedef struct {
uint is_array : 1; uint is_array : 1;
uint type : 15; uint is_strong : 1;
uint type : 14;
} PACKED Tag; } PACKED Tag;

View file

@ -58,13 +58,11 @@ int evaluate(Value val){
case T_null: case T_null:
return 0; return 0;
case T_int: case T_int:
return val.v4B.value;
case T_fix: case T_fix:
return val.v4B.value; return val.v4B.value;
case T_float: case T_float:
return FL_EPSILON > fabs((float)val.v4B.value); return FL_EPSILON < fabs(val.v4B.vfl);
case T_str: case T_str:
return 0;
case T_fn: case T_fn:
return 0; return 0;
default: default:
@ -255,6 +253,11 @@ void print_ast(Statement *base){
Value str_to_val(char *str, i32 len){ Value str_to_val(char *str, i32 len){
if(len < 0) if(len < 0)
len = strlen(str); len = strlen(str);
if(len > 65536){
fprintf(stderr, "Warning : string is longer than 65k chars"
" - will be trunucated\n");
len = 65536;
}
Value retv; Value retv;
retv.tag = (Tag){.is_array = 0, .type = T_str}; retv.tag = (Tag){.is_array = 0, .type = T_str};
#if LOG #if LOG
@ -278,15 +281,14 @@ Value str_to_val(char *str, i32 len){
} }
void clean_strval(Value str){ void clean_strval(Value str){
if(str.vstr.len < 5) if(str.vstr.len > 4)
return; flisp_free(str.vstr.pos);
flisp_free(str.vstr.pos);
} }
// Lesser special functions // Lesser special functions
Value is(Tag tag, Value b){ Value is(Tag tag, Value b){
Value ret = {.tag = {0,T_int}}; Value ret = {.tag = {0,0,T_int}};
ret.v4B.value = tag.is_array == b.tag.is_array && tag.type == b.tag.type; ret.v4B.value = tag.is_array == b.tag.is_array && tag.type == b.tag.type;
return ret; return ret;
} }
@ -414,7 +416,7 @@ cast_fn_t *cast_table[4][4] = {
}; };
Value cast(Tag type, Value b){ Value cast(Tag type, Value b){
if(type.type == b.tag.type) if(type.type == b.tag.type && type.is_array == b.tag.is_array)
return b; return b;
if(type.type == T_null || b.tag.type == T_null || type.type == T_fn if(type.type == T_null || b.tag.type == T_null || type.type == T_fn
|| b.tag.type == T_fn || type.is_array || b.tag.is_array){ || b.tag.type == T_fn || type.is_array || b.tag.is_array){
@ -559,31 +561,108 @@ Value sml(Value a, Value b){
} }
Value sml_eq(Value a, Value b){ Value sml_eq(Value a, Value b){
Value returnv;
returnv.tag = (Tag){.is_array=0,.type=T_int};
if(a.tag.is_array || b.tag.is_array)
runtime_err("Sml_eq : Invalid types");
if(a.tag.type != b.tag.type)
runtime_err("Sml_eq : Types do not match");
switch(a.tag.type){
case T_int:
case T_fix:
returnv.v4B.value = a.v4B.value <= b.v4B.value;
break;
case T_float:
returnv.v4B.value = a.v4B.vfl <= b.v4B.vfl;
break;
default:
runtime_err("Sml_eq : Invalid types");
}
return returnv;
} }
Value eq(Value a, Value b){ Value eq(Value a, Value b){
Value returnv;
returnv.tag = (Tag){.is_array=0,.type=T_int};
if(a.tag.is_array || b.tag.is_array)
runtime_err("Eq : Invalid types");
if(a.tag.type != b.tag.type)
runtime_err("Eq : Types do not match");
switch(a.tag.type){
case T_int:
case T_fix:
returnv.v4B.value = a.v4B.value == b.v4B.value;
break;
case T_float:
returnv.v4B.value = abs(a.v4B.vfl-b.v4B.vfl) > FL_EPSILON;
break;
default:
runtime_err("Eq : Invalid types");
}
return returnv;
} }
Value gt_eq(Value a, Value b){ Value gt_eq(Value a, Value b){
Value returnv;
returnv.tag = (Tag){.is_array=0,.type=T_int};
if(a.tag.is_array || b.tag.is_array)
runtime_err("Gt_eq : Invalid types");
if(a.tag.type != b.tag.type)
runtime_err("Gt_eq : Types do not match");
switch(a.tag.type){
case T_int:
case T_fix:
returnv.v4B.value = a.v4B.value >= b.v4B.value;
break;
case T_float:
returnv.v4B.value = a.v4B.vfl >= b.v4B.vfl;
break;
default:
runtime_err("Gt_eq : Invalid types");
}
return returnv;
} }
Value gt(Value a, Value b){ Value gt(Value a, Value b){
Value returnv;
returnv.tag = (Tag){.is_array=0,.type=T_int};
if(a.tag.is_array || b.tag.is_array)
runtime_err("Gt : Invalid types");
if(a.tag.type != b.tag.type)
runtime_err("Gt : Types do not match");
switch(a.tag.type){
case T_int:
case T_fix:
returnv.v4B.value = a.v4B.value > b.v4B.value;
break;
case T_float:
returnv.v4B.value = a.v4B.vfl > b.v4B.vfl;
break;
default:
runtime_err("Gt : Invalid types");
}
return returnv;
} }
Value not(Value a){ Value not(Value a){
Value returnv;
returnv.tag = (Tag){.is_array=0,.type=T_int};
returnv.v4B.value = !evaluate(a);
return returnv;
} }
Value and(Value a, Value b){ Value and(Value a, Value b){
Value returnv;
returnv.tag = (Tag){.is_array=0,.type=T_int};
returnv.v4B.value = evaluate(a) && evaluate(b);
return returnv;
} }
Value or(Value a, Value b){ Value or(Value a, Value b){
Value returnv;
returnv.tag = (Tag){.is_array=0,.type=T_int};
returnv.v4B.value = evaluate(a) || evaluate(b);
return returnv;
} }
Value len(Value a){ Value len(Value a){
@ -633,21 +712,21 @@ Value fl_write(Value a){
default: default:
break; break;
} }
return (Value){.tag={0,T_null}}; return (Value){.tag={0,0,T_null}};
} }
Value nwline(){ Value nwline(){
printf("\n"); printf("\n");
return (Value){.tag={0,T_null}}; return (Value){.tag={0,0,T_null}};
} }
const Tag tany = {0,T_null}; const Tag tany = {0,0,T_any};
const Tag tint = {0,T_int}; const Tag tint = {0,0,T_int};
const Tag tfix = {0,T_fix}; const Tag tfix = {0,0,T_fix};
const Tag tfloat = {0,T_float}; const Tag tfloat = {0,0,T_float};
const Tag tstr = {0,T_str}; const Tag tstr = {0,0,T_str};
const Tag tfn = {0,T_fn}; const Tag tfn = {0,0,T_fn};
const Tag tvec = {1,T_null}; const Tag tvec = {1,0,T_any};
#define BICAST(x) ((bi_fn_t*)(x)) #define BICAST(x) ((bi_fn_t*)(x))
@ -669,7 +748,7 @@ FnSig builtins[] = {
{{tvec,tany},2,1,{.bi = BICAST(push)}}, {{tvec,tany},2,1,{.bi = BICAST(push)}},
{{tvec,tint},2,1,{.bi = BICAST(pop)}}, {{tvec,tint},2,1,{.bi = BICAST(pop)}},
{{tany} ,1,1,{.bi = BICAST(fl_write)}}, {{tany} ,1,1,{.bi = BICAST(fl_write)}},
{{0} ,0,1,{.bi = BICAST(nwline)}} {{tany} ,0,1,{.bi = BICAST(nwline)}}
}; };
char *bi_names[] = { char *bi_names[] = {
@ -694,7 +773,7 @@ char *bi_names[] = {
}; };
void symbol_map_add_bi(HashMap *map){ void symbol_map_add_bi(HashMap *map){
Tag fntag = {0,T_fn}; Tag fntag = {0,1,T_fn};
for(int i = BI_add; i < BI__end; i++){ for(int i = BI_add; i < BI__end; i++){
MapItem *ret = hashmap_insert(map, bi_names[i-BI_add]); MapItem *ret = hashmap_insert(map, bi_names[i-BI_add]);
ret->type = *((i16*)&fntag); ret->type = *((i16*)&fntag);

View file

@ -37,18 +37,17 @@ void assign(Value *dst, Value src){
#if LOG #if LOG
printf("Assign : %d -> %d\n", src.tag.type, dst->tag.type); printf("Assign : %d -> %d\n", src.tag.type, dst->tag.type);
#endif #endif
if((dst->tag.type == src.tag.type || dst->tag.type == T_any) if(dst->tag.is_array != src.tag.is_array)
&& dst->tag.is_array == src.tag.is_array) runtime_err("Invalid assignement");
if((dst->tag.type == src.tag.type || !dst->tag.is_strong) || dst->tag.type == T_any)
*dst = src; *dst = src;
else{ else{
fprintf(stderr, "Warning : Possibly incorrect assignement\n" runtime_err("Invalid assignement");
"This may error in the future\n");
*dst = src;
} }
} }
Value fncall(FnSig *fn, Statement **params){ Value fncall(FnSig *fn, Statement **params){
Value returnv = {.tag = {0, T_null}}; Value returnv = {.tag = {0,0,T_null}};
if(fn->is_builtin){ if(fn->is_builtin){
switch(fn->n_param){ switch(fn->n_param){
case 0: case 0:
@ -84,7 +83,7 @@ void init_exec(){
} }
Value execute(Statement *stat){ Value execute(Statement *stat){
Value returnv = {.tag = {0,T_null}}; Value returnv = {.tag = {0,0,T_null}};
switch(stat->type){ switch(stat->type){
case ST_Varuse: case ST_Varuse:
if(vars[stat->var_id].tag.type == T_fn){ if(vars[stat->var_id].tag.type == T_fn){

View file

@ -35,9 +35,9 @@ ASTStack *stack;
void yyerror(char *s); void yyerror(char *s);
Tag ntag = {0,T_null}; Tag ntag = {0,0,T_null};
Tag atag = {0,T_any}; Tag atag = {0,0,T_any};
int make_stack(){ int make_stack(){
stack = malloc(sizeof(ASTStack)+sizeof(Statement)*2048); stack = malloc(sizeof(ASTStack)+sizeof(Statement)*2048);
@ -68,15 +68,15 @@ char *bi_type_names[6] = {
Tag get_type(char *str){ Tag get_type(char *str){
for(int i = 1; i < 6; i++){ for(int i = 1; i < 6; i++){
if(!strcmp(bi_type_names[i], str)) if(!strcmp(bi_type_names[i], str))
return (Tag){0, i}; return (Tag){0,1,i};
} }
return (Tag){0, 0}; return (Tag){0,0,0};
} }
Statement *make_iconst(i32 val){ Statement *make_iconst(i32 val){
Statement *stat = &stack->statements[stack->curr_statement++]; Statement *stat = &stack->statements[stack->curr_statement++];
stat->type = ST_Const; stat->type = ST_Const;
stat->cons = (Value){{.v4B = {val}},{.is_array = 0, .type = T_int}}; stat->cons = (Value){{.v4B = {.value=val}},{.is_array = 0, .type = T_int}};
stat->is_const = 1; stat->is_const = 1;
stat->child_n = 0; stat->child_n = 0;
return stat; return stat;
@ -164,7 +164,6 @@ Statement *make_operation(i32 type, Tag vtype, char *name, i32 nparam, ...){
if(nparam) if(nparam)
stat->children = malloc(sizeof(void*)*nparam); stat->children = malloc(sizeof(void*)*nparam);
stat->child_n = 0; stat->child_n = 0;
FnSig *fnsig = NULL;
va_list prm; va_list prm;
va_start(prm, nparam); va_start(prm, nparam);