Skip to content

Commit a235e67

Browse files
authored
Merge pull request #251 from sysprog21/sanitizers
Improve memory safety via sanitizers
2 parents b5e0cbc + ada731b commit a235e67

File tree

6 files changed

+50
-25
lines changed

6 files changed

+50
-25
lines changed

.github/workflows/main.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@ jobs:
2626
- name: IR regression tests
2727
run: |
2828
make check-snapshot || exit 1
29+
- name: Sanitizer-enabled stage 0 tests
30+
env:
31+
CC: ${{ matrix.compiler }}
32+
run: |
33+
make check-sanitizer || exit 1
2934
- name: Unit tests
3035
run: |
3136
make check || exit 1
@@ -48,6 +53,7 @@ jobs:
4853
apt-get install -yqq build-essential
4954
run: |
5055
make config ARCH=arm
56+
make check-sanitizer || exit 1
5157
make check || exit 1
5258
5359
coding-style:

Makefile

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,11 @@ SNAPSHOTS := $(foreach SNAPSHOT_ARCH,$(ARCHS), $(patsubst tests/%.c, tests/snaps
5252

5353
all: config bootstrap
5454

55+
sanitizer: CFLAGS += -fsanitize=address -fsanitize=undefined -fno-omit-frame-pointer -O0
56+
sanitizer: LDFLAGS += -fsanitize=address -fsanitize=undefined
57+
sanitizer: config $(OUT)/$(STAGE0)-sanitizer
58+
$(VECHO) " Built stage 0 compiler with sanitizers\n"
59+
5560
ifeq (,$(filter $(ARCH),$(ARCHS)))
5661
$(error Support ARM and RISC-V only. Select the target with "ARCH=arm" or "ARCH=riscv")
5762
endif
@@ -81,6 +86,12 @@ check-stage2: $(OUT)/$(STAGE2) $(TESTBINS) tests/driver.sh
8186
$(VECHO) " TEST STAGE 2\n"
8287
tests/driver.sh 2
8388

89+
check-sanitizer: $(OUT)/$(STAGE0)-sanitizer tests/driver.sh
90+
$(VECHO) " TEST STAGE 0 (with sanitizers)\n"
91+
$(Q)cp $(OUT)/$(STAGE0)-sanitizer $(OUT)/shecc
92+
tests/driver.sh 0
93+
$(Q)rm $(OUT)/shecc
94+
8495
check-snapshots: $(OUT)/$(STAGE0) $(SNAPSHOTS) tests/check-snapshots.sh
8596
$(Q)$(foreach SNAPSHOT_ARCH, $(ARCHS), $(MAKE) distclean config check-snapshot ARCH=$(SNAPSHOT_ARCH) --silent;)
8697
$(VECHO) "Switching backend back to %s\n" $(ARCH)
@@ -123,7 +134,11 @@ $(OUT)/inliner: tools/inliner.c
123134

124135
$(OUT)/$(STAGE0): $(OUT)/libc.inc $(OBJS)
125136
$(VECHO) " LD\t$@\n"
126-
$(Q)$(CC) $(OBJS) -o $@
137+
$(Q)$(CC) $(OBJS) $(LDFLAGS) -o $@
138+
139+
$(OUT)/$(STAGE0)-sanitizer: $(OUT)/libc.inc $(OBJS)
140+
$(VECHO) " LD\t$@ (with sanitizers)\n"
141+
$(Q)$(CC) $(OBJS) $(LDFLAGS) -o $@
127142

128143
$(OUT)/$(STAGE1): $(OUT)/$(STAGE0)
129144
$(Q)$(STAGE1_CHECK_CMD)

src/globals.c

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -164,8 +164,9 @@ void *arena_alloc(arena_t *arena, int size)
164164
abort();
165165
}
166166

167-
/* Align to PTR_SIZE bytes */
168-
size = (size + PTR_SIZE - 1) & ~(PTR_SIZE - 1);
167+
/* Align to sizeof(void*) bytes for host compatibility */
168+
int alignment = sizeof(void *);
169+
size = (size + alignment - 1) & ~(alignment - 1);
169170

170171
if (!arena->head || arena->head->offset + size > arena->head->capacity) {
171172
/* Need a new block: choose capacity = max(DEFAULT_ARENA_SIZE,
@@ -307,17 +308,17 @@ symbol_t *arena_alloc_symbol(void)
307308

308309
constant_t *arena_alloc_constant(void)
309310
{
310-
return arena_alloc(GENERAL_ARENA, sizeof(constant_t));
311+
return arena_calloc(GENERAL_ARENA, 1, sizeof(constant_t));
311312
}
312313

313314
alias_t *arena_alloc_alias(void)
314315
{
315-
return arena_alloc(GENERAL_ARENA, sizeof(alias_t));
316+
return arena_calloc(GENERAL_ARENA, 1, sizeof(alias_t));
316317
}
317318

318319
macro_t *arena_alloc_macro(void)
319320
{
320-
return arena_alloc(GENERAL_ARENA, sizeof(macro_t));
321+
return arena_calloc(GENERAL_ARENA, 1, sizeof(macro_t));
321322
}
322323

323324
bb_traversal_args_t *arena_alloc_traversal_args(void)
@@ -613,7 +614,7 @@ ph2_ir_t *add_existed_ph2_ir(ph2_ir_t *ph2_ir)
613614

614615
ph2_ir_t *add_ph2_ir(opcode_t op)
615616
{
616-
ph2_ir_t *ph2_ir = arena_alloc(BB_ARENA, sizeof(ph2_ir_t));
617+
ph2_ir_t *ph2_ir = arena_calloc(BB_ARENA, 1, sizeof(ph2_ir_t));
617618
ph2_ir->op = op;
618619
/* Set safe defaults; arch-lowering may annotate later */
619620
ph2_ir->next = NULL;
@@ -630,7 +631,7 @@ void set_var_liveout(var_t *var, int end)
630631

631632
block_t *add_block(block_t *parent, func_t *func, macro_t *macro)
632633
{
633-
block_t *blk = arena_alloc(BLOCK_ARENA, sizeof(block_t));
634+
block_t *blk = arena_calloc(BLOCK_ARENA, 1, sizeof(block_t));
634635

635636
blk->parent = parent;
636637
blk->func = func;
@@ -884,7 +885,7 @@ func_t *find_func(char *func_name)
884885
/* Create a basic block and set the scope of variables to 'parent' block */
885886
basic_block_t *bb_create(block_t *parent)
886887
{
887-
basic_block_t *bb = arena_alloc(BB_ARENA, sizeof(basic_block_t));
888+
basic_block_t *bb = arena_calloc(BB_ARENA, 1, sizeof(basic_block_t));
888889

889890
for (int i = 0; i < MAX_BB_PRED; i++) {
890891
bb->prev[i].bb = NULL;
@@ -1000,7 +1001,7 @@ void add_insn(block_t *block,
10001001

10011002
bb->scope = block;
10021003

1003-
insn_t *n = arena_alloc(INSN_ARENA, sizeof(insn_t));
1004+
insn_t *n = arena_calloc(INSN_ARENA, 1, sizeof(insn_t));
10041005
n->opcode = op;
10051006
n->rd = rd;
10061007
n->rs1 = rs1;

src/parser.c

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ var_t *require_var(block_t *blk)
5050
var_list->elements = new_locals;
5151
}
5252

53-
var_t *var = arena_alloc(BLOCK_ARENA, sizeof(var_t));
53+
var_t *var = arena_calloc(BLOCK_ARENA, 1, sizeof(var_t));
5454
var_list->elements[var_list->size++] = var;
5555
var->consumed = -1;
5656
var->base = var;
@@ -3232,7 +3232,8 @@ basic_block_t *read_body_statement(block_t *parent, basic_block_t *bb)
32323232
else if (lex_accept(T_decrement))
32333233
prefix_op = OP_sub;
32343234
/* must be an identifier or asterisk (for pointer dereference) */
3235-
if (!lex_peek(T_identifier, token) && !lex_peek(T_asterisk, NULL))
3235+
bool has_asterisk = lex_peek(T_asterisk, NULL);
3236+
if (!lex_peek(T_identifier, token) && !has_asterisk)
32363237
error("Unexpected token");
32373238

32383239
/* handle macro parameter substitution for statements */
@@ -3350,14 +3351,16 @@ basic_block_t *read_body_statement(block_t *parent, basic_block_t *bb)
33503351
return bb;
33513352
}
33523353

3353-
/* is a function call? */
3354-
func = find_func(token);
3355-
if (func) {
3356-
lex_expect(T_identifier);
3357-
read_func_call(func, parent, &bb);
3358-
perform_side_effect(parent, bb);
3359-
lex_expect(T_semicolon);
3360-
return bb;
3354+
/* is a function call? Skip function call check when has_asterisk is true */
3355+
if (!has_asterisk) {
3356+
func = find_func(token);
3357+
if (func) {
3358+
lex_expect(T_identifier);
3359+
read_func_call(func, parent, &bb);
3360+
perform_side_effect(parent, bb);
3361+
lex_expect(T_semicolon);
3362+
return bb;
3363+
}
33613364
}
33623365

33633366
/* handle pointer dereference expressions like *ptr = value */
@@ -3792,7 +3795,7 @@ void parse_internal(void)
37923795
/* set starting point of global stack manually */
37933796
GLOBAL_FUNC = add_func("", true);
37943797
GLOBAL_FUNC->stack_size = 4;
3795-
GLOBAL_FUNC->bbs = arena_alloc(BB_ARENA, sizeof(basic_block_t));
3798+
GLOBAL_FUNC->bbs = arena_calloc(BB_ARENA, 1, sizeof(basic_block_t));
37963799

37973800
/* built-in types */
37983801
TY_void = add_named_type("void");
@@ -3829,7 +3832,7 @@ void parse_internal(void)
38293832
func->return_def.type = TY_int;
38303833
func->num_params = 0;
38313834
func->va_args = 1;
3832-
func->bbs = arena_alloc(BB_ARENA, sizeof(basic_block_t));
3835+
func->bbs = arena_calloc(BB_ARENA, 1, sizeof(basic_block_t));
38333836

38343837
/* lexer initialization */
38353838
SOURCE->size = 0;

src/reg-alloc.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ void refresh(basic_block_t *bb, insn_t *insn)
5353

5454
ph2_ir_t *bb_add_ph2_ir(basic_block_t *bb, opcode_t op)
5555
{
56-
ph2_ir_t *n = arena_alloc(BB_ARENA, sizeof(ph2_ir_t));
56+
ph2_ir_t *n = arena_calloc(BB_ARENA, 1, sizeof(ph2_ir_t));
5757
n->op = op;
5858
/* Ensure deterministic defaults for newly created IR nodes */
5959
n->next = NULL; /* well-formed singly linked list */

src/ssa.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -583,7 +583,7 @@ bool insert_phi_insn(basic_block_t *bb, var_t *var)
583583
return false;
584584

585585
insn_t *head = bb->insn_list.head;
586-
insn_t *n = arena_alloc(INSN_ARENA, sizeof(insn_t));
586+
insn_t *n = arena_calloc(INSN_ARENA, 1, sizeof(insn_t));
587587
n->opcode = OP_phi;
588588
n->rd = var;
589589
n->rs1 = var;
@@ -805,7 +805,7 @@ void solve_phi_params(void)
805805

806806
void append_unwound_phi_insn(basic_block_t *bb, var_t *dest, var_t *rs)
807807
{
808-
insn_t *n = arena_alloc(INSN_ARENA, sizeof(insn_t));
808+
insn_t *n = arena_calloc(INSN_ARENA, 1, sizeof(insn_t));
809809
n->opcode = OP_unwound_phi;
810810
n->rd = dest;
811811
n->rs1 = rs;

0 commit comments

Comments
 (0)