Skip to content

Commit c4aa86f

Browse files
committed
Fix incorrect deref behavior
Previously, using subscription operator (literally "[]") with arrow operator (literally "->") would cause incorrect dereference result due to inappropriate delayed dereference strategy. In this patch, by adding dereference instructin when encountered subscription operator and under correct circumstances fixes the issue.
1 parent 1fecccf commit c4aa86f

File tree

4 files changed

+54
-9
lines changed

4 files changed

+54
-9
lines changed

src/globals.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -250,9 +250,7 @@ void hashmap_free(hashmap_t *map)
250250
next = cur->next;
251251
free(cur->key);
252252
free(cur->val);
253-
/* FIXME: Remove this if-clause will cause double free error */
254-
if (cur != map->buckets[0])
255-
free(cur);
253+
free(cur);
256254
cur = next;
257255
}
258256
}

src/parser.c

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -805,7 +805,7 @@ void read_expr_operand(block_t *parent, basic_block_t **bb)
805805

806806
lex_peek(T_identifier, token);
807807
var_t *var = find_var(token, parent);
808-
read_lvalue(&lvalue, var, parent, bb, 0, OP_generic);
808+
read_lvalue(&lvalue, var, parent, bb, false, OP_generic);
809809

810810
if (!lvalue.is_reference) {
811811
ph1_ir = add_ph1_ir(OP_address_of);
@@ -825,7 +825,7 @@ void read_expr_operand(block_t *parent, basic_block_t **bb)
825825
int open_bracket = lex_accept(T_open_bracket);
826826
lex_peek(T_identifier, token);
827827
var_t *var = find_var(token, parent);
828-
read_lvalue(&lvalue, var, parent, bb, 1, OP_generic);
828+
read_lvalue(&lvalue, var, parent, bb, true, OP_generic);
829829
if (open_bracket)
830830
lex_expect(T_close_bracket);
831831

@@ -962,7 +962,7 @@ void read_expr_operand(block_t *parent, basic_block_t **bb)
962962
} else if (var) {
963963
/* evalue lvalue expression */
964964
lvalue_t lvalue;
965-
read_lvalue(&lvalue, var, parent, bb, 1, prefix_op);
965+
read_lvalue(&lvalue, var, parent, bb, true, prefix_op);
966966

967967
/* is it an indirect call with function pointer? */
968968
if (lex_peek(T_open_bracket, NULL)) {
@@ -1260,6 +1260,18 @@ void read_lvalue(lvalue_t *lvalue,
12601260
while (lex_peek(T_open_square, NULL) || lex_peek(T_arrow, NULL) ||
12611261
lex_peek(T_dot, NULL)) {
12621262
if (lex_accept(T_open_square)) {
1263+
if (lvalue->is_reference && lvalue->is_ptr && is_member) {
1264+
ph1_ir = add_ph1_ir(OP_read);
1265+
ph1_ir->src0 = opstack_pop();
1266+
vd = require_var(parent);
1267+
strcpy(vd->var_name, gen_name());
1268+
ph1_ir->dest = vd;
1269+
opstack_push(vd);
1270+
ph1_ir->size = 4;
1271+
add_insn(parent, *bb, OP_read, ph1_ir->dest, ph1_ir->src0, NULL,
1272+
ph1_ir->size, NULL);
1273+
}
1274+
12631275
/* var must be either a pointer or an array of some type */
12641276
if (var->is_ptr == 0 && var->array_size == 0)
12651277
error("Cannot apply square operator to non-pointer");
@@ -1860,7 +1872,7 @@ bool read_body_assignment(char *token,
18601872
int size = 0;
18611873

18621874
/* has memory address that we want to set */
1863-
read_lvalue(&lvalue, var, parent, bb, 0, OP_generic);
1875+
read_lvalue(&lvalue, var, parent, bb, false, OP_generic);
18641876
size = lvalue.size;
18651877

18661878
if (lex_accept(T_increment)) {

src/reg-alloc.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -320,10 +320,13 @@ void reg_alloc()
320320
if (fn->func->va_args) {
321321
for (int i = 0; i < MAX_PARAMS; i++) {
322322
ph2_ir_t *ir = bb_add_ph2_ir(fn->bbs, OP_store);
323+
// FIXME: Currently derefence issue caused by mixed subscription
324+
// and arrow operators is fixed, but the original code is now
325+
// causing problem, fixing it later.
326+
var_t *param_def = &fn->func->param_defs[i];
323327

324328
if (i < fn->func->num_params)
325-
fn->func->param_defs[i].subscripts[0]->offset =
326-
fn->func->stack_size;
329+
param_def->subscripts[0]->offset = fn->func->stack_size;
327330

328331
ir->src0 = i;
329332
ir->src1 = fn->func->stack_size;

tests/driver.sh

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -433,6 +433,38 @@ int main() {
433433
}
434434
EOF
435435

436+
# Mixed subscription and arrow operator,
437+
# excerpt from issue #165
438+
try_output 0 "DDD" << EOF
439+
#include <stdlib.h>
440+
#include <string.h>
441+
442+
char a[100];
443+
444+
typedef struct {
445+
char *raw;
446+
} data_t;
447+
448+
void init_data(data_t *data, char *raw) {
449+
data->raw = raw;
450+
}
451+
452+
int main() {
453+
strcpy(a, "DATA");
454+
data_t *data = malloc(sizeof(data_t));
455+
init_data(data, a);
456+
457+
char *raw = data->raw;
458+
printf("%c", a[0]);
459+
printf("%c", raw[0]);
460+
printf("%c", data->raw[0]);
461+
462+
463+
free(data);
464+
return 0;
465+
}
466+
EOF
467+
436468
# global initialization
437469
try_ 20 << EOF
438470
int a = 5 * 2;

0 commit comments

Comments
 (0)