summaryrefslogtreecommitdiff
path: root/src/regexp.zig
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-09-28 19:52:50 -0300
committerGabriel Schneider <[email protected]>2026-10-01 00:12:15 -0300
commit197fe7396e7f63e9471bb317f1341228a0690ce6 (patch)
tree9b2631b3c5f85e687a5c390c845287b09f4315e6 /src/regexp.zig
parentb8c5e8772e646fa21f6afdd2a875a1bd52848bd5 (diff)
downloadpardes-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]>
Diffstat (limited to 'src/regexp.zig')
-rw-r--r--src/regexp.zig11
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);
+}