fix a buffer overflow in new_label_expr

use reference counting for temp defs and call PR_FreeTempDefs at the end
of emit_sub_expr as well as emit_expr.
fix a (relatively harmless) bug in type processesing of foo.bar =
This commit is contained in:
Bill Currie 2001-08-22 21:55:01 +00:00
parent 3177d9c7eb
commit 4c48851096
4 changed files with 116 additions and 42 deletions

View file

@ -290,6 +290,9 @@ typedef struct def_s {
int initialized;// 1 when a declaration included "= immediate"
statref_t *refs; // for relocations
int users; // ref counted temps
struct expr_s *expr; // temp expr using this def
struct def_s *def_next; // for writing out the global defs list
struct def_s *next; // general purpose linking
struct def_s *scope_next; // to facilitate hash table removal
@ -425,6 +428,7 @@ type_t *PR_ParseType (void);
char *PR_ParseName (void);
def_t *PR_ParseImmediate (def_t *def);
def_t *PR_ReuseConstant (expr_t *expr, def_t *def);
type_t *PR_FindType (type_t *new);
qboolean PR_Check (token_type_t type, const char *string);
void PR_Expect (token_type_t type, const char *string);

View file

@ -7,6 +7,8 @@
#include "scope.h"
#include "qc-parse.h"
def_t *emit_sub_expr (expr_t *e, def_t *dest);
def_t *
emit_statement (int sline, opcode_t *op, def_t *var_a, def_t *var_b, def_t *var_c)
{
@ -41,11 +43,19 @@ emit_statement (int sline, opcode_t *op, def_t *var_a, def_t *var_b, def_t *var_
statement->c = 0;
ret = var_a;
} else { // allocate result space
if (!var_c)
if (!var_c) {
var_c = PR_GetTempDef (types[op->type_c], pr_scope);
var_c->users += 2;
}
statement->c = var_c->ofs;
ret = var_c;
}
if (var_a)
var_a->users--;
if (var_b)
var_b->users--;
if (var_c)
var_c->users--;
PR_AddStatementRef (var_a, statement, 0);
PR_AddStatementRef (var_b, statement, 1);
PR_AddStatementRef (var_c, statement, 2);
@ -55,8 +65,6 @@ emit_statement (int sline, opcode_t *op, def_t *var_a, def_t *var_b, def_t *var_
return var_c;
}
def_t *emit_sub_expr (expr_t *e, def_t *dest);
void
emit_branch (int line, opcode_t *op, expr_t *e, expr_t *l)
{
@ -125,7 +133,7 @@ emit_assign_expr (expr_t *e)
expr_t *e2 = e->e.expr.e2;
def_a = emit_sub_expr (e1, 0);
if (def_a->type == &type_pointer) {
if (def_a->type->type == ev_pointer) {
def_b = emit_sub_expr (e2, 0);
op = PR_Opcode_Find ("=", 5, def_b, def_a, &def_void);
emit_statement (e->line, op, def_b, def_a, 0);
@ -154,27 +162,31 @@ emit_assign_expr (expr_t *e)
def_t *
emit_sub_expr (expr_t *e, def_t *dest)
{
opcode_t *op;
char *operator;
def_t *def_a, *def_b;
int priority;
opcode_t *op;
char *operator;
def_t *def_a, *def_b, *d = 0;
int priority;
switch (e->type) {
case ex_block:
if (e->e.block.result) {
def_t *res = emit_sub_expr (e->e.block.result, dest);
d = emit_sub_expr (e->e.block.result, dest);
for (e = e->e.block.head; e; e = e->next)
emit_expr (e);
return res;
break;
}
case ex_label:
error (e, "internal error");
abort ();
case ex_expr:
if (e->e.expr.op == 'c')
return emit_function_call (e, dest);
if (e->e.expr.op == '=')
return emit_assign_expr (e);
if (e->e.expr.op == 'c') {
d = emit_function_call (e, dest);
break;
}
if (e->e.expr.op == '=') {
d = emit_assign_expr (e);
break;
}
def_a = emit_sub_expr (e->e.expr.e1, 0);
def_b = emit_sub_expr (e->e.expr.e2, 0);
switch (e->e.expr.op) {
@ -257,10 +269,13 @@ emit_sub_expr (expr_t *e, def_t *dest)
default:
abort ();
}
if (!dest)
if (!dest) {
dest = PR_GetTempDef (e->e.expr.type, pr_scope);
dest->users += 2;
}
op = PR_Opcode_Find (operator, priority, def_a, def_b, dest);
return emit_statement (e->line, op, def_a, def_b, dest);
d = emit_statement (e->line, op, def_a, def_b, dest);
break;
case ex_uexpr:
if (e->e.expr.op == '!') {
operator = "!";
@ -281,23 +296,30 @@ emit_sub_expr (expr_t *e, def_t *dest)
priority = 3;
def_a = PR_ReuseConstant (&zero, 0);
def_b = emit_sub_expr (e->e.expr.e1, 0);
if (!dest)
if (!dest) {
dest = PR_GetTempDef (e->e.expr.type, pr_scope);
dest->users += 2;
}
} else {
abort ();
}
op = PR_Opcode_Find (operator, priority, def_a, def_b, dest);
return emit_statement (e->line, op, def_a, def_b, dest);
d = emit_statement (e->line, op, def_a, def_b, dest);
break;
case ex_def:
return e->e.def;
d = e->e.def;
break;
case ex_temp:
if (!e->e.temp.def) {
if (dest)
e->e.temp.def = dest;
else
e->e.temp.def = PR_GetTempDef (e->e.temp.type, pr_scope);
e->e.temp.def->users = e->e.temp.users;
e->e.temp.def->expr = e;
}
return e->e.temp.def;
d = e->e.temp.def;
break;
case ex_string:
case ex_float:
case ex_vector:
@ -307,9 +329,11 @@ emit_sub_expr (expr_t *e, def_t *dest)
case ex_pointer:
case ex_quaternion:
case ex_integer:
return PR_ReuseConstant (e, 0);
d = PR_ReuseConstant (e, 0);
break;
}
return 0;
PR_FreeTempDefs ();
return d;
}
void
@ -320,10 +344,6 @@ emit_expr (expr_t *e)
def_t *def_b;
statref_t *ref;
elabel_t *label;
//opcode_t *op;
static int level = 0;
level++;
switch (e->type) {
case ex_label:
@ -404,6 +424,5 @@ emit_expr (expr_t *e)
warning (e, "Ignoring useless expression");
break;
}
if (--level == 0)
PR_FreeTempDefs ();
PR_FreeTempDefs ();
}

View file

@ -199,6 +199,15 @@ type_mismatch (expr_t *e1, expr_t *e2, int op)
type_names[t1], get_op_string (op), type_names[t2]);
}
void
inc_users (expr_t *e)
{
if (e && e->type == ex_temp)
e->e.temp.users++;
else if (e && e->type == ex_block)
inc_users (e->e.block.result);
}
expr_t *
new_expr (void)
{
@ -211,13 +220,14 @@ new_expr (void)
expr_t *
new_label_expr (void)
{
static int label = 0;
int lnum = ++label;
static int label = 0;
int lnum = ++label;
const char *fname = current_func->def->name;
int len = 1 + strlen (fname) + 1 + ceil (log10 (lnum) + 1) + 1;
expr_t *l = new_expr ();
l->type = ex_label;
l->e.label.name = malloc (1 + strlen (fname) + 1 + ceil (log10 (lnum)) + 1);
l->e.label.name = malloc (len);
sprintf (l->e.label.name, "$%s_%d", fname, lnum);
return l;
}
@ -238,6 +248,9 @@ new_binary_expr (int op, expr_t *e1, expr_t *e2)
{
expr_t *e = new_expr ();
inc_users (e1);
inc_users (e2);
e->type = ex_expr;
e->e.expr.op = op;
e->e.expr.e1 = e1;
@ -250,6 +263,8 @@ new_unary_expr (int op, expr_t *e1)
{
expr_t *e = new_expr ();
inc_users (e1);
e->type = ex_uexpr;
e->e.expr.op = op;
e->e.expr.e1 = e1;
@ -327,11 +342,28 @@ print_expr (expr_t *e)
printf (" u%s", get_op_string (e->e.expr.op));
break;
case ex_def:
printf ("%s", e->e.def->name);
if (e->e.def->name)
printf ("%s", e->e.def->name);
if (e->e.def->scope) {
printf ("<%d>", e->e.def->ofs);
} else {
printf ("[%d]", e->e.def->ofs);
}
break;
case ex_temp:
printf ("(");
print_expr (e->e.temp.expr);
printf ("@");
printf (":");
if (e->e.temp.def) {
if (e->e.temp.def->name) {
printf("%s", e->e.temp.def->name);
} else {
printf("<%d>", e->e.temp.def->ofs);
}
} else {
printf("<>");
}
printf (":%s)@", type_names [e->e.temp.type->type]);
break;
case ex_string:
printf ("\"%s\"", e->e.string_val);
@ -797,7 +829,12 @@ type_mismatch:
type = &type_float;
}
if (op == '=' && e1->type == ex_expr && e1->e.expr.op == '.') {
e1->e.expr.type = &type_pointer;
type_t new;
memset (&new, 0, sizeof (new));
new.type = ev_pointer;
type = new.aux_type = e1->e.expr.type;
e1->e.expr.type = PR_FindType (&new);
}
if (!type)
error (e1, "internal error");

View file

@ -204,6 +204,7 @@ PR_GetTempDef (type_t *type, def_t *scope)
def->ofs = scope->num_locals;
scope->num_locals += type_size[size];
}
def->users = 0;
def->next = temp_scope.next;
temp_scope.next = def;
return def;
@ -212,27 +213,40 @@ PR_GetTempDef (type_t *type, def_t *scope)
void
PR_FreeTempDefs (void)
{
def_t *def, *d;
def_t **def, *d;
int size;
for (def = temp_scope.next; def; def = d) {
size = type_size[def->type->type];
d = def->next;
def->next = free_temps[size];
free_temps[size] = def;
def = &temp_scope.next;
while (*def) {
if ((*def)->users <= 0) {
d = *def;
*def = d->next;
size = type_size[d->type->type];
if (d->expr)
d->expr->e.temp.def = 0;
d->next = free_temps[size];
free_temps[size] = d;
} else {
def = &(*def)->next;
}
}
temp_scope.next = 0;
}
void
PR_ResetTempDefs (void)
{
int i;
//def_t *d;
def_t *d;
for (i = 0; i < sizeof (free_temps) / sizeof (free_temps[0]); i++) {
free_temps[i] = 0;
}
for (d = temp_scope.next; d; d = d->next)
printf ("%3d %3d\n", d->ofs, d->users);
temp_scope.next = 0;
}
void