diff --git a/lib/std/zig/Parse.zig b/lib/std/zig/Parse.zig index ad767a41ead1a338681ccf9472b550f2fdea8441..b587f7459bd3fd7f6287d35832c2b2f2de055abb 100644 --- a/lib/std/zig/Parse.zig +++ b/lib/std/zig/Parse.zig @@ -1637,13 +1637,17 @@ fn parseExprPrecedence(p: *Parse, min_prec: i32) Error!?Node.Index { if (tok_tag == .keyword_catch) { _ = try p.parsePayload(); } - const rhs = try p.parseExprPrecedence(info.prec + 1) orelse { - try p.warn(.expected_expr); - return node; - }; + // Check for whitespace error before parsing the rhs to facilitate fuzzing. + // Consider the case where there is a mismatched whitespace error but the rhs + // expression triggers stack overflow when parsing is attempted. In this case + // we want to return with an error rather than crashing on stack overflow. { const tok_len = tok_tag.lexeme().?.len; + if (p.tokenStart(oper_token) + tok_len >= p.source.len) { + try p.warn(.expected_expr); + return node; + } const char_before = p.source[p.tokenStart(oper_token) - 1]; const char_after = p.source[p.tokenStart(oper_token) + tok_len]; if (tok_tag == .ampersand and char_after == '&') { @@ -1655,6 +1659,11 @@ fn parseExprPrecedence(p: *Parse, min_prec: i32) Error!?Node.Index { } } + const rhs = try p.parseExprPrecedence(info.prec + 1) orelse { + try p.warn(.expected_expr); + return node; + }; + node = try p.addNode(.{ .tag = info.tag, .main_token = oper_token, diff --git a/lib/std/zig/parser_fuzz.zig b/lib/std/zig/parser_fuzz.zig index fc11e25cddf839f12937248071086e538fefeea4..f182436dbb4296e05bdc8c2e272f127ce946cbd1 100644 --- a/lib/std/zig/parser_fuzz.zig +++ b/lib/std/zig/parser_fuzz.zig @@ -131,6 +131,15 @@ test "nosuspend multi assign" { try checkAgainstOracle("test{nosuspend*0,var _=0;}"); } +// Found using AFL++ +test "bin op at end of file" { + try checkAgainstOracle( + \\test { + \\ _ = 00 + \\| + ); +} + fn checkAgainstOracle(source: [:0]const u8) !void { var fba_buf: [1 << 18]u8 = undefined; var fba: std.heap.FixedBufferAllocator = .init(&fba_buf); diff --git a/lib/std/zig/parser_test.zig b/lib/std/zig/parser_test.zig index 3f54d2217453eb547c43d6c0877cf9847a7aa821..e64c030d3074b874bb52652b1f1afb1c42332fce 100644 --- a/lib/std/zig/parser_test.zig +++ b/lib/std/zig/parser_test.zig @@ -6976,6 +6976,7 @@ test "recovery: missing comma" { , &[_]Error{ .expected_comma_after_switch_prong, .expected_comma_after_switch_prong, + .mismatched_binary_op_whitespace, .expected_expr, }); }