diff options
| author | Gabriel Schneider <[email protected]> | 2026-09-29 12:35:40 -0300 |
|---|---|---|
| committer | Gabriel Schneider <[email protected]> | 2026-10-01 00:12:16 -0300 |
| commit | 2d9f40667197ac775d5215ffd164c800f83cab4c (patch) | |
| tree | 7db6fb0ead682803ad406909c3c2cb81def335d0 /src | |
| parent | d8b35f18817faaba340059cc2bd88ab3b3bc919b (diff) | |
| download | pardes-2d9f40667197ac775d5215ffd164c800f83cab4c.tar.gz pardes-2d9f40667197ac775d5215ffd164c800f83cab4c.zip | |
A pattern with a newline and an anchor mvzr would misread is refused EINVAL, as the doc says
Its words named no malformed input, so 9ns read the refusal as EIO, and Edit's failed EIO directly. It now says bad regular expression: ..., and Edit's failure with those words is EINVAL too.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Diffstat (limited to 'src')
| -rw-r--r-- | src/ninep/addr.zig | 10 | ||||
| -rw-r--r-- | src/ninep/ctl.zig | 5 | ||||
| -rw-r--r-- | src/regexp.zig | 2 | ||||
| -rw-r--r-- | src/sam_edit.zig | 2 |
4 files changed, 16 insertions, 3 deletions
diff --git a/src/ninep/addr.zig b/src/ninep/addr.zig index 09ef2b66..f60c07b1 100644 --- a/src/ninep/addr.zig +++ b/src/ninep/addr.zig @@ -377,6 +377,16 @@ test "an address is evaluated from the current one, as acme's are" { try testing.expectEqualStrings(e_order, th.wr(q, qaddr, "/a/,/b/").reply.ename); } +test "a pattern with a newline and an anchor mvzr would misread is refused EINVAL, by addr and by Edit" { + const p = try th.withFile(testing.allocator, "a\nfoo\n"); + defer p.deinit(); + const r = th.wr(p, Node.of(th.serialOf(p), .addr), "/(^|\\n)foo/"); + try testing.expectEqual(E.INVAL, r.errno()); + try testing.expectEqualStrings(regexp_.Regex.e_anchor, r.reply.ename); + const e = th.wr(p, Node.of(th.serialOf(p), .ctl), "Edit ,x/(^|\\n)foo/d\n"); + try testing.expectEqual(E.INVAL, e.errno()); +} + test "a row's range, L:C-L2:C2 or L:C-C2, is an address through its last character" { const p = try th.withFile(testing.allocator, "one\ntwo three\nfour\n"); defer p.deinit(); diff --git a/src/ninep/ctl.zig b/src/ninep/ctl.zig index 978ce707..b79b1ab8 100644 --- a/src/ninep/ctl.zig +++ b/src/ninep/ctl.zig @@ -250,7 +250,10 @@ pub fn captured(p: *Pardes, req: Req, id: usize, exec: bool, text: []const u8, i /// there (`no such`, `not found`, the words 9ns reads as ENOENT too), else /// EIO. fn failureErrno(failure: []const u8) u16 { - return if (std.mem.indexOf(u8, failure, "no such") != null or std.mem.indexOf(u8, failure, "not found") != null) E.NOENT else E.IO; + if (std.mem.indexOf(u8, failure, "no such") != null or std.mem.indexOf(u8, failure, "not found") != null) return E.NOENT; + // A pattern refused (Edit's too) is malformed input, as 9ns reads it. + if (std.mem.indexOf(u8, failure, "bad regular expression") != null) return E.INVAL; + return E.IO; } pub fn resultsLen(p: *Pardes) u64 { diff --git a/src/regexp.zig b/src/regexp.zig index 64e1d75a..27b3c0ba 100644 --- a/src/regexp.zig +++ b/src/regexp.zig @@ -41,7 +41,7 @@ pub const Regex = struct { /// patterns take 45-80 ms, and a Debug build is ten times slower. pub const budget: u64 = if (builtin.mode == .Debug) 4_000_000 else 32_000_000; - pub const e_anchor = "in a pattern with \\n, ^ can only come first and $ only just before a \\n"; + pub const e_anchor = "bad regular expression: in a pattern with \\n, ^ can only come first and $ only just before a \\n"; /// `Anchor`: a pattern that names a newline has `^` other than first, /// or `$` other than just before a `\n`, which mvzr would read as the diff --git a/src/sam_edit.zig b/src/sam_edit.zig index cd2998ef..a88728aa 100644 --- a/src/sam_edit.zig +++ b/src/sam_edit.zig @@ -735,7 +735,7 @@ test "an Edit that fails halfway changes nothing, and says why in acme's words" .{ "w /tmp/x", "w is not supported in pardes" }, .{ ",s/(a)/\\1/", "no \\1: mvzr keeps no submatches" }, .{ "1 m 1,2", "move overlaps itself" }, - .{ ",x/(^|\\n)foo/d", "in a pattern with \\n, ^ can only come first and $ only just before a \\n" }, + .{ ",x/(^|\\n)foo/d", "bad regular expression: in a pattern with \\n, ^ can only come first and $ only just before a \\n" }, }) |c| { var why: Why = .{}; try std.testing.expectError(error.Edit, run(arena_state.allocator(), "foo a\nfoo\n", .{}, "t", c[0], &why)); |
