suppressed some buffer overflows - moved function generation to cpu specific code (XXX: should have less cpu specific code for that)

tcc-xref
bellard 2002-01-03 22:43:10 +00:00
parent 8b41bc57e1
commit 14799da838
2 changed files with 105 additions and 83 deletions

View File

@ -72,6 +72,8 @@ typedef struct GFuncContext {
/******************************************************/ /******************************************************/
static int *func_sub_sp_ptr;
void g(int c) void g(int c)
{ {
*(char *)ind++ = c; *(char *)ind++ = c;
@ -355,6 +357,48 @@ void gfunc_call(GFuncContext *c)
vtop--; vtop--;
} }
/* generate function prolog of type 't' */
void gfunc_prolog(int t)
{
int addr, align, size, u;
Sym *sym;
sym = sym_find((unsigned)t >> VT_STRUCT_SHIFT);
addr = 8;
/* if the function returns a structure, then add an
implicit pointer parameter */
func_vt = sym->t;
if ((func_vt & VT_BTYPE) == VT_STRUCT) {
func_vc = addr;
addr += 4;
}
/* define parameters */
while ((sym = sym->next) != NULL) {
u = sym->t;
sym_push(sym->v & ~SYM_FIELD, u,
VT_LOCAL | VT_LVAL, addr);
size = type_size(u, &align);
size = (size + 3) & ~3;
#ifdef FUNC_STRUCT_PARAM_AS_PTR
/* structs are passed as pointer */
if ((u & VT_BTYPE) == VT_STRUCT) {
size = 4;
}
#endif
addr += size;
}
o(0xe58955); /* push %ebp, mov %esp, %ebp */
func_sub_sp_ptr = (int *)oad(0xec81, 0); /* sub $xxx, %esp */
}
/* generate function epilog */
void gfunc_epilog(void)
{
o(0xc3c9); /* leave, ret */
*func_sub_sp_ptr = (-loc + 3) & -4; /* align local size to word &
save local variables */
}
int gjmp(int t) int gjmp(int t)
{ {
return psym(0xe9, t); return psym(0xe9, t);

144
tcc.c
View File

@ -32,11 +32,6 @@
/* preprocessor debug */ /* preprocessor debug */
//#define PP_DEBUG //#define PP_DEBUG
/* these sizes are dummy for unix, because malloc() does not use
memory when the pages are not used */
#define TEXT_SIZE (4*1024*1024)
#define DATA_SIZE (4*1024*1024)
/* amount of virtual memory associate to a section (currently, we do /* amount of virtual memory associate to a section (currently, we do
not realloc them) */ not realloc them) */
#define SECTION_VSIZE (1024 * 1024) #define SECTION_VSIZE (1024 * 1024)
@ -398,6 +393,8 @@ void gen_op(int op);
void force_charshort_cast(int t); void force_charshort_cast(int t);
void gen_cast(int t); void gen_cast(int t);
void vstore(void); void vstore(void);
Sym *sym_find(int v);
Sym *sym_push(int v, int t, int r, int c);
/* type handling */ /* type handling */
int type_size(int t, int *a); int type_size(int t, int *a);
@ -546,7 +543,7 @@ unsigned long long __ldtoull(long double a)
/********************************************************/ /********************************************************/
/* copy a string and trucate it */ /* copy a string and truncate it */
char *pstrcpy(char *buf, int buf_size, const char *s) char *pstrcpy(char *buf, int buf_size, const char *s)
{ {
char *q, *q_end; char *q, *q_end;
@ -564,6 +561,16 @@ char *pstrcpy(char *buf, int buf_size, const char *s)
return buf; return buf;
} }
/* strcat and truncate */
char *pstrcat(char *buf, int buf_size, const char *s)
{
int len;
len = strlen(buf);
if (len < buf_size)
pstrcpy(buf + len, buf_size - len, s);
return buf;
}
Section *new_section(const char *name) Section *new_section(const char *name)
{ {
Section *sec, **psec; Section *sec, **psec;
@ -1235,8 +1242,7 @@ void preprocess(void)
next(); next();
if (tok != TOK_STR) if (tok != TOK_STR)
error("#include syntax error"); error("#include syntax error");
/* XXX: buffer overflow */ pstrcpy(buf, sizeof(buf), get_tok_str(tok, &tokc));
strcpy(buf, get_tok_str(tok, &tokc));
c = '\"'; c = '\"';
} }
/* eat all spaces and comments after include */ /* eat all spaces and comments after include */
@ -1248,14 +1254,15 @@ void preprocess(void)
error("memory full"); error("memory full");
if (c == '\"') { if (c == '\"') {
/* first search in current dir if "header.h" */ /* first search in current dir if "header.h" */
/* XXX: buffer overflow */
size = 0; size = 0;
p = strrchr(filename, '/'); p = strrchr(filename, '/');
if (p) if (p)
size = p + 1 - filename; size = p + 1 - filename;
if (size > sizeof(buf1) - 1)
size = sizeof(buf1) - 1;
memcpy(buf1, filename, size); memcpy(buf1, filename, size);
buf1[size] = '\0'; buf1[size] = '\0';
strcat(buf1, buf); pstrcat(buf1, sizeof(buf1), buf);
f = fopen(buf1, "r"); f = fopen(buf1, "r");
if (f) if (f)
goto found; goto found;
@ -1850,13 +1857,12 @@ int *macro_arg_subst(Sym **nested_list, int *macro_str, Sym *args)
if (s) { if (s) {
token_buf[0] = '\0'; token_buf[0] = '\0';
st = (int *)s->c; st = (int *)s->c;
/* XXX: buffer overflow */
notfirst = 0; notfirst = 0;
while (*st) { while (*st) {
if (notfirst) if (notfirst)
strcat(token_buf, " "); pstrcat(token_buf, sizeof(token_buf), " ");
t = tok_get(&st, &cval); t = tok_get(&st, &cval);
strcat(token_buf, get_tok_str(t, &cval)); pstrcat(token_buf, sizeof(token_buf), get_tok_str(t, &cval));
notfirst = 1; notfirst = 1;
} }
#ifdef PP_DEBUG #ifdef PP_DEBUG
@ -1918,11 +1924,10 @@ int *macro_twosharps(int *macro_str)
ident + ident or ident + number */ ident + ident or ident + number */
if (tok >= TOK_IDENT && if (tok >= TOK_IDENT &&
(t >= TOK_IDENT || t == TOK_CINT)) { (t >= TOK_IDENT || t == TOK_CINT)) {
/* XXX: buffer overflow */
p = get_tok_str(tok, &tokc); p = get_tok_str(tok, &tokc);
strcpy(token_buf, p); pstrcpy(token_buf, sizeof(token_buf), p);
p = get_tok_str(t, &cval); p = get_tok_str(t, &cval);
strcat(token_buf, p); pstrcat(token_buf, sizeof(token_buf), p);
ts = tok_alloc(token_buf, 0); ts = tok_alloc(token_buf, 0);
tok = ts->tok; /* modify current token */ tok = ts->tok; /* modify current token */
} else { } else {
@ -3241,87 +3246,90 @@ int is_compatible_types(int t1, int t2)
printed in the type */ printed in the type */
/* XXX: union */ /* XXX: union */
/* XXX: add array and function pointers */ /* XXX: add array and function pointers */
/* XXX: buffer overflows */
void type_to_str(char *buf, int buf_size, void type_to_str(char *buf, int buf_size,
int t, const char *varstr) int t, const char *varstr)
{ {
int bt, v; int bt, v;
Sym *s, *sa; Sym *s, *sa;
char buf1[256]; char buf1[256];
const char *tstr;
t = t & VT_TYPE; t = t & VT_TYPE;
bt = t & VT_BTYPE; bt = t & VT_BTYPE;
buf[0] = '\0'; buf[0] = '\0';
if (t & VT_UNSIGNED) if (t & VT_UNSIGNED)
strcat(buf, "unsigned "); pstrcat(buf, buf_size, "unsigned ");
switch(bt) { switch(bt) {
case VT_VOID: case VT_VOID:
strcat(buf, "void"); tstr = "void";
break; goto add_tstr;
case VT_BOOL: case VT_BOOL:
strcat(buf, "_Bool"); tstr = "_Bool";
break; goto add_tstr;
case VT_BYTE: case VT_BYTE:
strcat(buf, "char"); tstr = "char";
break; goto add_tstr;
case VT_SHORT: case VT_SHORT:
strcat(buf, "short"); tstr = "short";
break; goto add_tstr;
case VT_INT: case VT_INT:
strcat(buf, "int"); tstr = "int";
break; goto add_tstr;
case VT_LONG: case VT_LONG:
strcat(buf, "long"); tstr = "long";
break; goto add_tstr;
case VT_LLONG: case VT_LLONG:
strcat(buf, "long long"); tstr = "long long";
break; goto add_tstr;
case VT_FLOAT: case VT_FLOAT:
strcat(buf, "float"); tstr = "float";
break; goto add_tstr;
case VT_DOUBLE: case VT_DOUBLE:
strcat(buf, "double"); tstr = "double";
break; goto add_tstr;
case VT_LDOUBLE: case VT_LDOUBLE:
strcat(buf, "long double"); tstr = "long double";
add_tstr:
pstrcat(buf, buf_size, tstr);
break; break;
case VT_ENUM: case VT_ENUM:
case VT_STRUCT: case VT_STRUCT:
if (bt == VT_STRUCT) if (bt == VT_STRUCT)
strcat(buf, "struct "); tstr = "struct ";
else else
strcat(buf, "enum "); tstr = "enum ";
pstrcat(buf, buf_size, tstr);
v = (unsigned)t >> VT_STRUCT_SHIFT; v = (unsigned)t >> VT_STRUCT_SHIFT;
if (v >= SYM_FIRST_ANOM) if (v >= SYM_FIRST_ANOM)
strcat(buf, "<anonymous>"); pstrcat(buf, buf_size, "<anonymous>");
else else
strcat(buf, get_tok_str(v, NULL)); pstrcat(buf, buf_size, get_tok_str(v, NULL));
break; break;
case VT_FUNC: case VT_FUNC:
s = sym_find((unsigned)t >> VT_STRUCT_SHIFT); s = sym_find((unsigned)t >> VT_STRUCT_SHIFT);
type_to_str(buf, buf_size, s->t, varstr); type_to_str(buf, buf_size, s->t, varstr);
strcat(buf, "("); pstrcat(buf, buf_size, "(");
sa = s->next; sa = s->next;
while (sa != NULL) { while (sa != NULL) {
type_to_str(buf1, sizeof(buf1), sa->t, NULL); type_to_str(buf1, sizeof(buf1), sa->t, NULL);
strcat(buf, buf1); pstrcat(buf, buf_size, buf1);
sa = sa->next; sa = sa->next;
if (sa) if (sa)
strcat(buf, ", "); pstrcat(buf, buf_size, ", ");
} }
strcat(buf, ")"); pstrcat(buf, buf_size, ")");
goto no_var; goto no_var;
case VT_PTR: case VT_PTR:
s = sym_find((unsigned)t >> VT_STRUCT_SHIFT); s = sym_find((unsigned)t >> VT_STRUCT_SHIFT);
strcpy(buf1, "*"); pstrcpy(buf1, sizeof(buf1), "*");
if (varstr) if (varstr)
strcat(buf1, varstr); pstrcat(buf1, sizeof(buf1), varstr);
type_to_str(buf, buf_size, s->t, buf1); type_to_str(buf, buf_size, s->t, buf1);
goto no_var; goto no_var;
} }
if (varstr) { if (varstr) {
strcat(buf, " "); pstrcat(buf, buf_size, " ");
strcat(buf, varstr); pstrcat(buf, buf_size, varstr);
} }
no_var: ; no_var: ;
} }
@ -5147,7 +5155,7 @@ int decl_initializer_alloc(int t, AttributeDef *ad, int r, int has_init)
/* 'l' is VT_LOCAL or VT_CONST to define default storage type */ /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
void decl(int l) void decl(int l)
{ {
int *a, t, b, v, addr, has_init, size, align, r, u; int t, b, v, addr, has_init, r;
Sym *sym; Sym *sym;
AttributeDef ad; AttributeDef ad;
@ -5207,41 +5215,12 @@ void decl(int l)
funcname = get_tok_str(v, NULL); funcname = get_tok_str(v, NULL);
/* push a dummy symbol to enable local sym storage */ /* push a dummy symbol to enable local sym storage */
sym_push1(&local_stack, 0, 0, 0); sym_push1(&local_stack, 0, 0, 0);
/* define parameters */ gfunc_prolog(t);
sym = sym_find((unsigned)t >> VT_STRUCT_SHIFT);
/* XXX: the following is x86 dependant -> move it to
x86 code gen */
addr = 8;
/* if the function returns a structure, then add an
implicit pointer parameter */
func_vt = sym->t;
if ((func_vt & VT_BTYPE) == VT_STRUCT) {
func_vc = addr;
addr += 4;
}
while ((sym = sym->next) != NULL) {
u = sym->t;
sym_push(sym->v & ~SYM_FIELD, u,
VT_LOCAL | VT_LVAL, addr);
size = type_size(u, &align);
size = (size + 3) & ~3;
#ifdef FUNC_STRUCT_PARAM_AS_PTR
/* structs are passed as pointer */
if ((u & VT_BTYPE) == VT_STRUCT) {
size = 4;
}
#endif
addr += size;
}
loc = 0; loc = 0;
o(0xe58955); /* push %ebp, mov %esp, %ebp */
a = (int *)oad(0xec81, 0); /* sub $xxx, %esp */
rsym = 0; rsym = 0;
block(NULL, NULL, NULL, NULL, 0); block(NULL, NULL, NULL, NULL, 0);
gsym(rsym); gsym(rsym);
o(0xc3c9); /* leave, ret */ gfunc_epilog();
*a = (-loc + 3) & -4; /* align local size to word &
save local variables */
cur_text_section->data_ptr = (unsigned char *)ind; cur_text_section->data_ptr = (unsigned char *)ind;
sym_pop(&label_stack, NULL); /* reset label stack */ sym_pop(&label_stack, NULL); /* reset label stack */
sym_pop(&local_stack, NULL); /* reset local stack */ sym_pop(&local_stack, NULL); /* reset local stack */
@ -5398,8 +5377,7 @@ void define_symbol(const char *sym)
p = strchr(sym, '='); p = strchr(sym, '=');
if (!p) { if (!p) {
/* XXX: buffer overflow */ pstrcpy(buf, sizeof(buf), sym);
strcpy(buf, sym);
p = "1"; p = "1";
} else { } else {
len = p - sym; len = p - sym;