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 {...@@ -1774,7 +1774,7 @@ fn parseTypeExpr(p: *Parse) Error!?Node.Index {
1774 },1774 },
1775 .asterisk => {1775 .asterisk => {
1776 const asterisk = p.nextToken();1776 const asterisk = p.nextToken();
1777 const mods = try p.parsePtrModifiers();1777 const mods = try p.parsePtrModifiers(.bit_align);
1778 const elem_type = try p.expectTypeExpr();1778 const elem_type = try p.expectTypeExpr();
1779 if (mods.bit_range_start != .none) {1779 if (mods.bit_range_start != .none) {
1780 return try p.addNode(.{1780 return try p.addNode(.{
...@@ -1829,14 +1829,8 @@ fn parseTypeExpr(p: *Parse) Error!?Node.Index {...@@ -1829,14 +1829,8 @@ fn parseTypeExpr(p: *Parse) Error!?Node.Index {
1829 sentinel = try p.expectExpr();1829 sentinel = try p.expectExpr();
1830 }1830 }
1831 _ = try p.expectToken(.r_bracket);1831 _ = try p.expectToken(.r_bracket);
1832 const mods = try p.parsePtrModifiers();1832 const mods = try p.parsePtrModifiers(.byte_align);
1833 const elem_type = try p.expectTypeExpr();1833 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 }
1840 if (sentinel == null and mods.addrspace_node == .none) {1834 if (sentinel == null and mods.addrspace_node == .none) {
1841 return try p.addNode(.{1835 return try p.addNode(.{
1842 .tag = .ptr_type_aligned,1836 .tag = .ptr_type_aligned,
...@@ -1879,14 +1873,8 @@ fn parseTypeExpr(p: *Parse) Error!?Node.Index {...@@ -1879,14 +1873,8 @@ fn parseTypeExpr(p: *Parse) Error!?Node.Index {
1879 null;1873 null;
1880 _ = try p.expectToken(.r_bracket);1874 _ = try p.expectToken(.r_bracket);
1881 if (len_expr == null) {1875 if (len_expr == null) {
1882 const mods = try p.parsePtrModifiers();1876 const mods = try p.parsePtrModifiers(.byte_align);
1883 const elem_type = try p.expectTypeExpr();1877 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 }
1890 if (sentinel == null and mods.addrspace_node == .none) {1878 if (sentinel == null and mods.addrspace_node == .none) {
1891 return try p.addNode(.{1879 return try p.addNode(.{
1892 .tag = .ptr_type_aligned,1880 .tag = .ptr_type_aligned,
...@@ -3065,7 +3053,7 @@ const PtrModifiers = struct {...@@ -3065,7 +3053,7 @@ const PtrModifiers = struct {
3065/// AddrSpace <- KEYWORD_addrspace LPAREN Expr RPAREN3053/// AddrSpace <- KEYWORD_addrspace LPAREN Expr RPAREN
3066/// ByteAlign <- KEYWORD_align LPAREN Expr RPAREN3054/// ByteAlign <- KEYWORD_align LPAREN Expr RPAREN
3067/// BitAlign <- KEYWORD_align LPAREN Expr (COLON Expr COLON Expr)? RPAREN3055/// 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 {
3069 var result: PtrModifiers = .{3057 var result: PtrModifiers = .{
3070 .align_node = .none,3058 .align_node = .none,
3071 .addrspace_node = .none,3059 .addrspace_node = .none,
...@@ -3082,7 +3070,10 @@ fn parsePtrModifiers(p: *Parse) !PtrModifiers {...@@ -3082,7 +3070,10 @@ fn parsePtrModifiers(p: *Parse) !PtrModifiers {
3082 _ = try p.expectToken(.l_paren);3070 _ = try p.expectToken(.l_paren);
3083 result.align_node = (try p.expectExpr()).toOptional();3071 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 }
3086 result.bit_range_start = (try p.expectExpr()).toOptional();3077 result.bit_range_start = (try p.expectExpr()).toOptional();
3087 _ = try p.expectToken(.colon);3078 _ = try p.expectToken(.colon);
3088 result.bit_range_end = (try p.expectExpr()).toOptional();3079 result.bit_range_end = (try p.expectExpr()).toOptional();