Skip to content

Commit 5b9dfe7

Browse files
authored
Merge pull request #252 from sysprog21/fixes
Fix crash on pointer dereference after declaration
2 parents 748ffc9 + 5bf64d7 commit 5b9dfe7

File tree

2 files changed

+84
-9
lines changed

2 files changed

+84
-9
lines changed

src/parser.c

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3267,11 +3267,42 @@ basic_block_t *read_body_statement(block_t *parent, basic_block_t *bb)
32673267
}
32683268

32693269
/* is it a variable declaration? */
3270-
int find_type_flag = lex_accept(T_struct) ? 2 : 1;
3271-
if (find_type_flag == 1 && lex_accept(T_union)) {
3272-
find_type_flag = 2;
3270+
/* Special handling when statement starts with asterisk */
3271+
if (has_asterisk) {
3272+
/* For "*identifier", check if identifier is a type.
3273+
* If not, it's a dereference, not a declaration. */
3274+
int saved_size = SOURCE->size;
3275+
char saved_char = next_char;
3276+
int saved_token = next_token;
3277+
3278+
/* Skip the asterisk to peek at the identifier */
3279+
lex_accept(T_asterisk);
3280+
char next_ident[MAX_TOKEN_LEN];
3281+
bool could_be_type = false;
3282+
3283+
if (lex_peek(T_identifier, next_ident)) {
3284+
/* Check if it's a type name */
3285+
type = find_type(next_ident, 0);
3286+
if (type)
3287+
could_be_type = true;
3288+
}
3289+
3290+
/* Restore position */
3291+
SOURCE->size = saved_size;
3292+
next_char = saved_char;
3293+
next_token = saved_token;
3294+
3295+
/* If it's not a type, skip the declaration block */
3296+
if (!could_be_type)
3297+
type = NULL;
3298+
} else {
3299+
/* Normal type checking without asterisk */
3300+
int find_type_flag = lex_accept(T_struct) ? 2 : 1;
3301+
if (find_type_flag == 1 && lex_accept(T_union))
3302+
find_type_flag = 2;
3303+
type = find_type(token, find_type_flag);
32733304
}
3274-
type = find_type(token, find_type_flag);
3305+
32753306
if (type) {
32763307
var = require_typed_var(parent, type);
32773308
read_full_var_decl(var, 0, 0);
@@ -3280,9 +3311,7 @@ basic_block_t *read_body_statement(block_t *parent, basic_block_t *bb)
32803311
if (lex_accept(T_assign)) {
32813312
if (lex_peek(T_open_curly, NULL) &&
32823313
(var->array_size > 0 || var->is_ptr > 0)) {
3283-
parse_array_init(
3284-
var, parent, &bb,
3285-
1); /* FIXED: Emit code for locals in functions */
3314+
parse_array_init(var, parent, &bb, 1);
32863315
} else {
32873316
read_expr(parent, &bb);
32883317
read_ternary_operation(parent, &bb);
@@ -3305,8 +3334,7 @@ basic_block_t *read_body_statement(block_t *parent, basic_block_t *bb)
33053334
if (lex_accept(T_assign)) {
33063335
if (lex_peek(T_open_curly, NULL) &&
33073336
(nv->array_size > 0 || nv->is_ptr > 0)) {
3308-
parse_array_init(nv, parent, &bb,
3309-
1); /* FIXED: Emit code for locals */
3337+
parse_array_init(nv, parent, &bb, 1);
33103338
} else {
33113339
read_expr(parent, &bb);
33123340

tests/driver.sh

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -461,6 +461,53 @@ items 3 "int x; int *y; x = 3; y = &x; return y[0];"
461461
items 5 "int b; int *a; b = 10; a = &b; a[0] = 5; return b;"
462462
items 2 "int x[2]; int y; x[1] = 2; y = *(x + 1); return y;"
463463
items 2 "int x; int *y; int z; z = 2; y = &z; x = *y; return x;"
464+
465+
# pointer dereference immediately after declaration
466+
items 42 "int x; x = 10; int *p; p = &x; p[0] = 42; exit(x);"
467+
items 10 "int val; val = 5; int *ptr; ptr = &val; ptr[0] = 10; exit(val);"
468+
items 7 "int a; a = 3; int *b; b = &a; b[0] = 7; exit(a);"
469+
470+
# asterisk dereference for reading after declaration
471+
items 42 "int x; x = 42; int *p; p = &x; int y; y = *p; exit(y);"
472+
items 15 "int val; val = 15; int *ptr; ptr = &val; exit(*ptr);"
473+
items 100 "int a; a = 100; int *b; b = &a; int c; c = *b; exit(c);"
474+
475+
# complex pointer dereference patterns after declaration
476+
try_ 25 << EOF
477+
int main() {
478+
int x;
479+
int *p;
480+
x = 10;
481+
p = &x; /* pointer declaration and assignment */
482+
p[0] = 25; /* array-style assignment immediately after */
483+
return x;
484+
}
485+
EOF
486+
487+
try_ 50 << EOF
488+
int main() {
489+
int arr[3];
490+
int *ptr;
491+
arr[0] = 10; arr[1] = 20; arr[2] = 30;
492+
ptr = arr;
493+
ptr[0] = 50; /* should modify arr[0] */
494+
return arr[0];
495+
}
496+
EOF
497+
498+
try_ 50 << EOF
499+
int main() {
500+
int a, b;
501+
int *p1, *p2;
502+
a = 5; b = 15;
503+
p1 = &a;
504+
p2 = &b;
505+
p1[0] = 100; /* multiple pointer assignments in same block */
506+
p2[0] = 200;
507+
return p1[0] / 2; /* 100 / 2 = 50 */
508+
}
509+
EOF
510+
464511
try_ 10 << EOF
465512
void change_it(int *p) {
466513
if (p[0] == 0) {

0 commit comments

Comments
 (0)