diff options
Diffstat (limited to 'src/ninep')
| -rw-r--r-- | src/ninep/pty.zig | 29 |
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); |
