diff options
| author | Gabriel Schneider <[email protected]> | 2026-09-28 19:52:50 -0300 |
|---|---|---|
| committer | Gabriel Schneider <[email protected]> | 2026-10-01 00:12:15 -0300 |
| commit | 197fe7396e7f63e9471bb317f1341228a0690ce6 (patch) | |
| tree | 9b2631b3c5f85e687a5c390c845287b09f4315e6 | |
| parent | b8c5e8772e646fa21f6afdd2a875a1bd52848bd5 (diff) | |
| download | pardes-197fe7396e7f63e9471bb317f1341228a0690ce6.tar.gz pardes-197fe7396e7f63e9471bb317f1341228a0690ce6.zip | |
A search pattern with a short \x escape is refused, where mvzr panicked on it
Co-Authored-By: Claude Opus 5.5 <[email protected]>
| -rw-r--r-- | src/regexp.zig | 11 |
1 files changed, 11 insertions, 0 deletions
diff --git a/src/regexp.zig b/src/regexp.zig index fe68585d..f6d540c4 100644 --- a/src/regexp.zig +++ b/src/regexp.zig @@ -62,6 +62,10 @@ pub const Regex = struct { i += 1; piece = pat[i - 1 .. i + 1]; if (pat[i] == 'n') spans = true; + // mvzr slices two hex digits after `\x` without looking, + // so a short one panics it: refuse it here. + if (pat[i] == 'x' and (i + 2 >= pat.len or + !std.ascii.isHex(pat[i + 1]) or !std.ascii.isHex(pat[i + 2]))) return error.Bad; } else if (in_class) { in_class = c != ']'; } else if (c == '[') { @@ -185,3 +189,10 @@ test "the match is the leftmost, however long the line" { try std.testing.expectEqual(@as(usize, 2), f.start); try std.testing.expectEqual(@as(usize, 7), f.end); } + +test "a \\x without two hex digits is refused, not handed to mvzr to panic on" { + for ([_][]const u8{ "\\x", "a\\x1", "\\x1b[\\x", "[\\x]", "\\xg1" }) |pat| + try std.testing.expectError(error.Bad, Regex.compile(pat)); + var rx = try Regex.compile("\\x41"); + try std.testing.expectEqual(@as(usize, 1), (try rx.find("xA", 0, 1, 2)).?.start); +} |
