From 5e3bad3556435663fa9220390248a5ed4f75be47 Mon Sep 17 00:00:00 2001 From: wooster0 Date: Sun, 23 Jun 2024 21:37:11 +0900 Subject: [PATCH] Make 0e.0 and 0xp0 not crash This fixes those sequences of characters crashing. --- lib/std/zig/AstGen.zig | 1 + lib/std/zig/number_literal.zig | 14 +++++++++ .../invalid_number_literals.zig | 29 +++++++++++++++++++ 3 files changed, 44 insertions(+) create mode 100644 test/cases/compile_errors/invalid_number_literals.zig diff --git a/lib/std/zig/AstGen.zig b/lib/std/zig/AstGen.zig index febd6b60bb..18012b802c 100644 --- a/lib/std/zig/AstGen.zig +++ b/lib/std/zig/AstGen.zig @@ -8637,6 +8637,7 @@ fn failWithNumberError(astgen: *AstGen, err: std.zig.number_literal.Error, token assert(bytes.len >= 2 and bytes[0] == '0' and bytes[1] == 'x'); // Validated by tokenizer return astgen.failOff(token, @intCast(i), "sign '{c}' cannot follow digit '{c}' in hex base", .{ bytes[i], bytes[i - 1] }); }, + .period_after_exponent => |i| return astgen.failOff(token, @intCast(i), "unexpected period after exponent", .{}), } } diff --git a/lib/std/zig/number_literal.zig b/lib/std/zig/number_literal.zig index aba588a3ea..a4dc33eb91 100644 --- a/lib/std/zig/number_literal.zig +++ b/lib/std/zig/number_literal.zig @@ -56,6 +56,8 @@ pub const Error = union(enum) { invalid_character: usize, /// [+-] not immediately after [pPeE] invalid_exponent_sign: usize, + /// Period comes directly after exponent. + period_after_exponent: usize, }; /// Parse Zig number literal accepted by fmt.parseInt, fmt.parseFloat and big_int.setString. @@ -108,6 +110,9 @@ pub fn parseNumberLiteral(bytes: []const u8) Result { continue; }, 'p', 'P' => if (base == 16) { + if (i == 2) { + return .{ .failure = .{ .digit_after_base = {} } }; + } float = true; if (exponent) return .{ .failure = .{ .duplicate_exponent = i } }; if (underscore) return .{ .failure = .{ .exponent_after_underscore = i } }; @@ -116,6 +121,15 @@ pub fn parseNumberLiteral(bytes: []const u8) Result { continue; }, '.' => { + if (exponent) { + const digit_index = i - ".e".len; + if (digit_index < bytes.len) { + switch (bytes[digit_index]) { + '0'...'9' => return .{ .failure = .{ .period_after_exponent = i } }, + else => {}, + } + } + } float = true; if (base != 10 and base != 16) return .{ .failure = .{ .invalid_float_base = 2 } }; if (period) return .{ .failure = .duplicate_period }; diff --git a/test/cases/compile_errors/invalid_number_literals.zig b/test/cases/compile_errors/invalid_number_literals.zig new file mode 100644 index 0000000000..3d5f8b9dc4 --- /dev/null +++ b/test/cases/compile_errors/invalid_number_literals.zig @@ -0,0 +1,29 @@ +comptime { + _ = 0e.0; +} +comptime { + _ = 0E.0; +} +comptime { + _ = 12e.0; +} +comptime { + _ = 12E.0; +} +comptime { + _ = 0xp0; +} +comptime { + _ = 0xP0; +} + +// error +// backend=stage2 +// target=native +// +// :2:11: error: unexpected period after exponent +// :5:11: error: unexpected period after exponent +// :8:12: error: unexpected period after exponent +// :11:12: error: unexpected period after exponent +// :14:9: error: expected a digit after base prefix +// :17:9: error: expected a digit after base prefix