summaryrefslogtreecommitdiff
path: root/src/ninep
diff options
context:
space:
mode:
Diffstat (limited to 'src/ninep')
-rw-r--r--src/ninep/pty.zig29
1 files changed, 24 insertions, 5 deletions
diff --git a/src/ninep/pty.zig b/src/ninep/pty.zig
index 6b84af61..76cef83b 100644
--- a/src/ninep/pty.zig
+++ b/src/ninep/pty.zig
@@ -25,7 +25,22 @@ fn dimension(word: []const u8) ?u16 {
if (word.len == 0 or word.len > 5) return null;
for (word) |c| if (c < '0' or c > '9') return null;
const n = std.fmt.parseInt(u16, word, 10) catch return null;
- return if (n == 0) null else n;
+ return if (n == 0 or n > winsize_max) null else n;
+}
+
+/// As the root ctl's `size` (4096 a side).
+const winsize_max = 4096;
+const e_winsize_range = std.fmt.comptimePrint("invalid winsize: out of range, 1x1 to {d}x{d}", .{ winsize_max, winsize_max });
+
+/// A winsize whose numbers are numbers but not sizes: said as such.
+fn outOfRange(line: []const u8) bool {
+ var words = std.mem.tokenizeAny(u8, line, " \t");
+ if (!std.mem.eql(u8, words.next() orelse return false, "winsize")) return false;
+ var n: u8 = 0;
+ while (words.next()) |w| : (n += 1) {
+ _ = std.fmt.parseInt(u32, w, 10) catch return false;
+ }
+ return n == 2;
}
fn signalNamed(word: []const u8) ?pardes.PtySignal {
@@ -43,7 +58,7 @@ pub fn writeCtl(p: *Pardes, req: Req, id: usize) Reply {
while (it.next()) |raw| {
const line = std.mem.trim(u8, raw, " \t\r");
if (line.len == 0) continue;
- if (!verb(p, id, line, apply)) return tree.failText(req.tag, E.INVAL, e_bad_pty_ctl);
+ if (!verb(p, id, line, apply)) return tree.failText(req.tag, E.INVAL, if (outOfRange(line)) e_winsize_range else e_bad_pty_ctl);
}
}
return .{ .tag = req.tag, .written = @intCast(req.data.len) };
@@ -533,10 +548,7 @@ test "every pty/ctl verb, and every refusal" {
"winsize", // no arguments
"winsize 80", // one argument
"winsize 80 24 extra", // three
- "winsize 0 24", // zero is "unknown", never a width
- "winsize 80 0",
"winsize -1 24", // not a decimal
- "winsize 999999 24", // wider than a u16
"sig", // no name
"sig INT TERM", // two
"sig SIGINT",
@@ -558,6 +570,13 @@ test "every pty/ctl verb, and every refusal" {
try testing.expect(a.signal == null);
try testing.expect(!a.spawned);
}
+ // Numbers, but no size: said as out of range, the bound size's.
+ for ([_][]const u8{ "winsize 0 24", "winsize 80 0", "winsize 0 0", "winsize 4097 24", "winsize 999999 24" }) |bad| {
+ const a = wr(p, ctl, bad);
+ try testing.expectEqual(E.INVAL, a.errno());
+ try testing.expectEqualStrings(e_winsize_range, a.reply.ename);
+ try testing.expect(a.winsize == null);
+ }
const spaced = wr(p, ctl, "\n winsize 90 20 \n\n");
try testing.expectEqual(Status.ok, spaced.reply.status);