authorgravatar for mail@isaacfreund.comIsaac Freund <mail@isaacfreund.com> 2026-07-06 14:49:56+02:00
committergravatar for mail@isaacfreund.comIsaac Freund <mail@isaacfreund.com> 2026-07-08 11:49:01+02:00
logd37d6d39f7442892d261f0d80cf72226462ad2c4
treea0832759adcf0702ad933c49859776a8ca917fc5
parent910e3e51ba5e320a198ca5e9ca8584c94b735b04
signaturelock-open Commit is signed but in an unrecognized format.

parser: warn on invalid bit align before further parsing

Currently the fuzzer is able to hit a stack overflow due to an invalid bit align on a pointer type that is not a single item pointer: []align(a:(((((((((((((((((((((((((((((((((((((((... To fix this, warn (and return error.ParseError if recovery is disabled) before parsing the invalid bit align expression.

1 files changed, 8 insertions(+), 17 deletions(-)

lib/std/zig/Parse.zig+8-17
......@@ -1774,7 +1774,7 @@ fn parseTypeExpr(p: *Parse) Error!?Node.Index {
17741774 },
17751775 .asterisk => {
17761776 const asterisk = p.nextToken();
1777 const mods = try p.parsePtrModifiers();
1777 const mods = try p.parsePtrModifiers(.bit_align);
17781778 const elem_type = try p.expectTypeExpr();
17791779 if (mods.bit_range_start != .none) {
17801780 return try p.addNode(.{
......@@ -1829,14 +1829,8 @@ fn parseTypeExpr(p: *Parse) Error!?Node.Index {
18291829 sentinel = try p.expectExpr();
18301830 }
18311831 _ = try p.expectToken(.r_bracket);
1832 const mods = try p.parsePtrModifiers();
1832 const mods = try p.parsePtrModifiers(.byte_align);
18331833 const elem_type = try p.expectTypeExpr();
1834 if (mods.bit_range_start.unwrap()) |bit_range_start| {
1835 try p.warnMsg(.{
1836 .tag = .invalid_bit_range,
1837 .token = p.nodeMainToken(bit_range_start),
1838 });
1839 }
18401834 if (sentinel == null and mods.addrspace_node == .none) {
18411835 return try p.addNode(.{
18421836 .tag = .ptr_type_aligned,
......@@ -1879,14 +1873,8 @@ fn parseTypeExpr(p: *Parse) Error!?Node.Index {
18791873 null;
18801874 _ = try p.expectToken(.r_bracket);
18811875 if (len_expr == null) {
1882 const mods = try p.parsePtrModifiers();
1876 const mods = try p.parsePtrModifiers(.byte_align);
18831877 const elem_type = try p.expectTypeExpr();
1884 if (mods.bit_range_start.unwrap()) |bit_range_start| {
1885 try p.warnMsg(.{
1886 .tag = .invalid_bit_range,
1887 .token = p.nodeMainToken(bit_range_start),
1888 });
1889 }
18901878 if (sentinel == null and mods.addrspace_node == .none) {
18911879 return try p.addNode(.{
18921880 .tag = .ptr_type_aligned,
......@@ -3065,7 +3053,7 @@ const PtrModifiers = struct {
30653053/// AddrSpace <- KEYWORD_addrspace LPAREN Expr RPAREN
30663054/// ByteAlign <- KEYWORD_align LPAREN Expr RPAREN
30673055/// BitAlign <- KEYWORD_align LPAREN Expr (COLON Expr COLON Expr)? RPAREN
3068fn parsePtrModifiers(p: *Parse) !PtrModifiers {
3056fn parsePtrModifiers(p: *Parse, align_type: enum { bit_align, byte_align }) !PtrModifiers {
30693057 var result: PtrModifiers = .{
30703058 .align_node = .none,
30713059 .addrspace_node = .none,
......@@ -3082,7 +3070,10 @@ fn parsePtrModifiers(p: *Parse) !PtrModifiers {
30823070 _ = try p.expectToken(.l_paren);
30833071 result.align_node = (try p.expectExpr()).toOptional();
30843072
3085 if (p.eatToken(.colon)) |_| {
3073 if (p.eatToken(.colon)) |colon| {
3074 if (align_type == .byte_align) {
3075 try p.warnMsg(.{ .tag = .invalid_bit_range, .token = colon });
3076 }
30863077 result.bit_range_start = (try p.expectExpr()).toOptional();
30873078 _ = try p.expectToken(.colon);
30883079 result.bit_range_end = (try p.expectExpr()).toOptional();