Skip to content

Commit c63e4be

Browse files
committed
Fixing issues due to use-after-free in the wasm backend
1 parent c7232c7 commit c63e4be

4 files changed

Lines changed: 42 additions & 104 deletions

File tree

cmake/RunWasmTest.cmake

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ if(NOT _cc_rv EQUAL 0)
3737
message(FATAL_ERROR
3838
"Wasm compile failed for ${TEST_NAME}\n"
3939
"compiler: ${WASM_TCC}\n"
40+
"exit code: ${_cc_rv}\n"
4041
"stdout:\n${_cc_stdout}\n"
4142
"stderr:\n${_cc_stderr}")
4243
endif()
@@ -51,6 +52,7 @@ if(NOT _node_rv EQUAL 0)
5152
message(FATAL_ERROR
5253
"Wasm run failed for ${TEST_NAME}\n"
5354
"node: ${NODE_EXECUTABLE}\n"
55+
"exit code: ${_node_rv}\n"
5456
"stdout:\n${_node_stdout}\n"
5557
"stderr:\n${_node_stderr}")
5658
endif()

tccwasm.c

Lines changed: 16 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,7 @@ static int wasm_find_func_index_by_tok(int tok)
245245
{
246246
int i;
247247
for (i = 0; i < tcc_wasm_nb_funcs; ++i) {
248-
if (tcc_wasm_funcs[i].sym && tcc_wasm_funcs[i].sym->v == tok)
248+
if (tcc_wasm_funcs[i].sym_tok == tok)
249249
return i;
250250
}
251251
return -1;
@@ -255,8 +255,7 @@ static int wasm_find_func_index_by_sym_index(int sym_index)
255255
{
256256
int i;
257257
for (i = 0; i < tcc_wasm_nb_funcs; ++i) {
258-
Sym *fsym = tcc_wasm_funcs[i].sym;
259-
if (fsym && fsym->c == sym_index)
258+
if (tcc_wasm_funcs[i].sym_index == sym_index)
260259
return i;
261260
}
262261
return -1;
@@ -343,94 +342,6 @@ static void wasm_store_i64_to_i32_pair(WasmBuf *b, int local_tmp64, int lo_local
343342
wb_local_set(b, hi_local);
344343
}
345344

346-
static int wasm_sym_addr(Sym *sym, int addend)
347-
{
348-
ElfSym *es;
349-
Sym *ps;
350-
const char *name = NULL;
351-
int sym_index;
352-
int sh;
353-
int base = 0;
354-
355-
if (!sym)
356-
return addend;
357-
sym_index = sym->c;
358-
es = elfsym(sym);
359-
sh = es->st_shndx;
360-
361-
if (sh == SHN_UNDEF) {
362-
int si;
363-
for (ps = sym->prev_tok; ps; ps = ps->prev_tok) {
364-
if (!ps->c)
365-
continue;
366-
es = elfsym(ps);
367-
if (es->st_shndx != SHN_UNDEF) {
368-
sym = ps;
369-
sh = es->st_shndx;
370-
break;
371-
}
372-
}
373-
if (sh == SHN_UNDEF && sym->v >= TOK_IDENT) {
374-
for (ps = sym_find(sym->v); ps; ps = ps->prev_tok) {
375-
if (!ps->c)
376-
continue;
377-
es = elfsym(ps);
378-
if (es->st_shndx != SHN_UNDEF) {
379-
sym = ps;
380-
sh = es->st_shndx;
381-
break;
382-
}
383-
}
384-
}
385-
if (sh == SHN_UNDEF && sym->v >= TOK_IDENT) {
386-
name = get_tok_str(sym->v, NULL);
387-
si = wasm_find_defined_sym_index_by_name(name);
388-
if (si > 0) {
389-
sym_index = si;
390-
es = &((ElfSym *)symtab_section->data)[si];
391-
sh = es->st_shndx;
392-
}
393-
}
394-
if (sh == SHN_UNDEF) {
395-
int bt = sym->type.t & VT_BTYPE;
396-
if (bt == VT_FUNC
397-
|| (bt == VT_PTR && sym->type.ref
398-
&& (sym->type.ref->type.t & VT_BTYPE) == VT_FUNC)) {
399-
return wasm_func_ptr_value_from_sym_index(sym_index, name, addend);
400-
}
401-
}
402-
if (sh == SHN_UNDEF && (!name || !*name)) {
403-
int t = sym->type.t;
404-
int ro_size = wasm_sec_rodata ? (int)wasm_sec_rodata->data_offset : 0;
405-
int data_size = wasm_sec_data ? (int)wasm_sec_data->data_offset : 0;
406-
int bss_size = wasm_sec_bss ? (int)wasm_sec_bss->data_offset : 0;
407-
if ((t & VT_STATIC) && (((t & VT_BTYPE) == VT_PTR) || (t & VT_ARRAY))) {
408-
if (addend >= 0 && addend < ro_size)
409-
return wasm_layout.rodata_base + addend;
410-
if (addend >= 0 && addend < data_size)
411-
return wasm_layout.data_base + addend;
412-
if (addend >= 0 && addend < bss_size)
413-
return wasm_layout.bss_base + addend;
414-
}
415-
}
416-
}
417-
if (sh == SHN_UNDEF)
418-
tcc_error("wasm32 backend: unresolved symbol (tok=%d)", sym->v);
419-
420-
if (wasm_sec_rodata && sh == wasm_sec_rodata->sh_num)
421-
base = wasm_layout.rodata_base;
422-
else if (wasm_sec_data && sh == wasm_sec_data->sh_num)
423-
base = wasm_layout.data_base;
424-
else if (wasm_sec_bss && sh == wasm_sec_bss->sh_num)
425-
base = wasm_layout.bss_base;
426-
else if (wasm_sec_text && sh == wasm_sec_text->sh_num)
427-
return wasm_func_ptr_value_from_sym_index(sym_index, name, addend);
428-
else
429-
tcc_error("wasm32 backend: unsupported symbol section for '%s'", get_tok_str(sym->v, NULL));
430-
431-
return base + (int)es->st_value + addend;
432-
}
433-
434345
static int wasm_sym_addr_from_elfsym(int sym_index, int addend)
435346
{
436347
ElfSym *es;
@@ -473,14 +384,14 @@ static int wasm_sym_addr_from_elfsym(int sym_index, int addend)
473384
return base + (int)es->st_value + addend;
474385
}
475386

476-
static int wasm_sym_addr_from_tok(int tok, int addend)
387+
static int wasm_sym_addr_from_tok(int tok, const char *name, int addend)
477388
{
478-
const char *name;
479389
int si;
480390

481391
if (tok < TOK_IDENT)
482392
return addend;
483-
name = get_tok_str(tok, NULL);
393+
if (!name || !*name)
394+
tcc_error("wasm32 backend: unresolved symbol token %d", tok);
484395
si = wasm_find_defined_sym_index_by_name(name);
485396
if (si > 0)
486397
return wasm_sym_addr_from_elfsym(si, addend);
@@ -492,8 +403,9 @@ static int wasm_sym_addr_from_op(WasmOp *op)
492403
if (op->sym_index > 0)
493404
return wasm_sym_addr_from_elfsym(op->sym_index, op->imm);
494405
if (op->sym_tok >= TOK_IDENT)
495-
return wasm_sym_addr_from_tok(op->sym_tok, op->imm);
496-
return wasm_sym_addr(op->sym, op->imm);
406+
return wasm_sym_addr_from_tok(op->sym_tok, op->sym_name, op->imm);
407+
tcc_error("wasm32 backend: unresolved symbol reference in IR");
408+
return 0;
497409
}
498410

499411
static void wasm_apply_data_relocs(Section *s)
@@ -632,7 +544,7 @@ static int wasm_emit_libcall(WasmBuf *b, WasmOp *op,
632544
case TOK___moddi3:
633545
case TOK___umoddi3:
634546
if (op->call_nb_args != 2)
635-
tcc_error("wasm32 backend: invalid helper arity for %s", get_tok_str(tok, NULL));
547+
tcc_error("wasm32 backend: invalid helper arity for token %d", tok);
636548
wasm_emit_call_arg(b, op, 0, local_fp, local_i0, local_f0);
637549
wasm_emit_call_arg(b, op, 1, local_fp, local_i0, local_f0);
638550
if (tok == TOK___divdi3) wb_u8(b, 0x7f); /* i64.div_s */
@@ -648,7 +560,7 @@ static int wasm_emit_libcall(WasmBuf *b, WasmOp *op,
648560
case TOK___lshrdi3:
649561
case TOK___ashrdi3:
650562
if (op->call_nb_args != 2)
651-
tcc_error("wasm32 backend: invalid helper arity for %s", get_tok_str(tok, NULL));
563+
tcc_error("wasm32 backend: invalid helper arity for token %d", tok);
652564
wasm_emit_call_arg(b, op, 0, local_fp, local_i0, local_f0); /* i64 */
653565
wasm_emit_call_arg(b, op, 1, local_fp, local_i0, local_f0); /* i32 */
654566
if (op->call_arg_type[1] != WASM_VAL_I64)
@@ -663,7 +575,7 @@ static int wasm_emit_libcall(WasmBuf *b, WasmOp *op,
663575

664576
case TOK___floatundisf:
665577
if (op->call_nb_args != 1)
666-
tcc_error("wasm32 backend: invalid helper arity for %s", get_tok_str(tok, NULL));
578+
tcc_error("wasm32 backend: invalid helper arity for token %d", tok);
667579
wasm_emit_call_arg(b, op, 0, local_fp, local_i0, local_f0);
668580
wb_u8(b, 0xb5); /* f32.convert_i64_u */
669581
wb_u8(b, 0xbb); /* f64.promote_f32 */
@@ -673,7 +585,7 @@ static int wasm_emit_libcall(WasmBuf *b, WasmOp *op,
673585
case TOK___floatundidf:
674586
case TOK___floatundixf:
675587
if (op->call_nb_args != 1)
676-
tcc_error("wasm32 backend: invalid helper arity for %s", get_tok_str(tok, NULL));
588+
tcc_error("wasm32 backend: invalid helper arity for token %d", tok);
677589
wasm_emit_call_arg(b, op, 0, local_fp, local_i0, local_f0);
678590
wb_u8(b, 0xba); /* f64.convert_i64_u */
679591
wb_local_set(b, wasm_f64_reg_local(REG_FRET, local_f0));
@@ -683,7 +595,7 @@ static int wasm_emit_libcall(WasmBuf *b, WasmOp *op,
683595
case TOK___fixunsdfdi:
684596
case TOK___fixunsxfdi:
685597
if (op->call_nb_args != 1)
686-
tcc_error("wasm32 backend: invalid helper arity for %s", get_tok_str(tok, NULL));
598+
tcc_error("wasm32 backend: invalid helper arity for token %d", tok);
687599
if (tok == TOK___fixunssfdi && op->call_arg_type[0] == WASM_VAL_F32) {
688600
wasm_emit_call_arg(b, op, 0, local_fp, local_i0, local_f0);
689601
wb_u8(b, 0xaf); /* i64.trunc_f32_u */
@@ -1031,8 +943,9 @@ static void wasm_emit_case(WasmBuf *b, WasmFuncIR *f, WasmOp *op,
1031943
} else {
1032944
libcall_done = wasm_emit_libcall(b, op, local_fp, local_i0, local_f0, local_tmp64);
1033945
if (!libcall_done) {
1034-
tcc_error("wasm32 backend: unresolved direct call '%s'",
1035-
get_tok_str(op->call_tok, NULL));
946+
if (op->call_name && *op->call_name)
947+
tcc_error("wasm32 backend: unresolved direct call '%s'", op->call_name);
948+
tcc_error("wasm32 backend: unresolved direct call token %d", op->call_tok);
1036949
}
1037950
}
1038951
} else {

wasm-backend.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,9 @@ typedef struct WasmOp {
8787
Sym *sym;
8888
int sym_index;
8989
int sym_tok;
90+
char *sym_name;
9091
int call_tok;
92+
char *call_name;
9193
unsigned char call_nb_args;
9294
unsigned char call_arg_reg[WASM_MAX_CALL_ARGS];
9395
unsigned char call_arg_hi[WASM_MAX_CALL_ARGS];
@@ -97,6 +99,8 @@ typedef struct WasmOp {
9799

98100
typedef struct WasmFuncIR {
99101
Sym *sym;
102+
int sym_index;
103+
int sym_tok;
100104
char *name;
101105
int start_pc;
102106
int end_pc;

wasm-gen.c

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,10 +136,23 @@ static int wasm_type_to_val(int t, int for_ret)
136136
return WASM_VAL_VOID;
137137
}
138138

139+
static char *wasm_tok_strdup(int tok)
140+
{
141+
const char *s;
142+
if (tok < TOK_IDENT)
143+
return NULL;
144+
s = get_tok_str(tok, NULL);
145+
return s ? tcc_strdup(s) : NULL;
146+
}
147+
139148
ST_FUNC void tcc_wasm_reset(void)
140149
{
141-
int i;
150+
int i, j;
142151
for (i = 0; i < tcc_wasm_nb_funcs; ++i) {
152+
for (j = 0; j < tcc_wasm_funcs[i].nb_ops; ++j) {
153+
tcc_free(tcc_wasm_funcs[i].ops[j].sym_name);
154+
tcc_free(tcc_wasm_funcs[i].ops[j].call_name);
155+
}
143156
tcc_free(tcc_wasm_funcs[i].name);
144157
tcc_free(tcc_wasm_funcs[i].param_types);
145158
tcc_free(tcc_wasm_funcs[i].param_offsets);
@@ -168,6 +181,8 @@ static WasmFuncIR *wasm_new_func(Sym *sym)
168181
f = &tcc_wasm_funcs[tcc_wasm_nb_funcs++];
169182
memset(f, 0, sizeof(*f));
170183
f->sym = sym;
184+
f->sym_index = sym ? sym->c : 0;
185+
f->sym_tok = sym ? sym->v : 0;
171186
f->ret_type = WASM_VAL_VOID;
172187
return f;
173188
}
@@ -249,6 +264,7 @@ static void wasm_set_addr(WasmOp *op, int fr, Sym *sym, int fc)
249264
op->sym = sym;
250265
op->sym_index = sym->c;
251266
op->sym_tok = sym->v;
267+
op->sym_name = wasm_tok_strdup(sym->v);
252268
} else {
253269
op->flags = WASM_ADDR_ABS;
254270
}
@@ -351,6 +367,7 @@ ST_FUNC void load(int r, SValue *sv)
351367
wo->sym = sv->sym;
352368
wo->sym_index = sv->sym ? sv->sym->c : 0;
353369
wo->sym_tok = sv->sym ? sv->sym->v : 0;
370+
wo->sym_name = sv->sym ? wasm_tok_strdup(sv->sym->v) : NULL;
354371
wo->imm = fc;
355372
return;
356373
}
@@ -371,6 +388,7 @@ ST_FUNC void load(int r, SValue *sv)
371388
wo->sym = sv->sym;
372389
wo->sym_index = sv->sym ? sv->sym->c : 0;
373390
wo->sym_tok = sv->sym ? sv->sym->v : 0;
391+
wo->sym_name = sv->sym ? wasm_tok_strdup(sv->sym->v) : NULL;
374392
wo->imm = fc;
375393
return;
376394
}
@@ -552,6 +570,7 @@ ST_FUNC void gfunc_call(int nb_args)
552570
int bt = func_sym->type.t & VT_BTYPE;
553571
wo->sym = vtop->sym;
554572
wo->call_tok = vtop->sym ? vtop->sym->v : func_sym->v;
573+
wo->call_name = wasm_tok_strdup(wo->call_tok);
555574
wo->r0 = func_reg;
556575
wo->call_nb_args = nb_args;
557576
for (i = 0; i < nb_args; ++i) {

0 commit comments

Comments
 (0)