From 6fac0b1cb4003bffe859dfd8c8bc8a6e7b035d01 Mon Sep 17 00:00:00 2001 From: CJ van den Berg Date: Wed, 18 Sep 2024 21:33:19 +0200 Subject: [PATCH] fix: prevent error.Overflow for LSPs that send crazy large messages --- build.zig.zon | 4 ++-- src/LSP.zig | 36 +++++++++++++++++++++++++++++------- 2 files changed, 31 insertions(+), 9 deletions(-) diff --git a/build.zig.zon b/build.zig.zon index 038c926..52aa86d 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -18,8 +18,8 @@ .hash = "1220220dbc7fe91c1c54438193ca765cebbcb7d58f35cdcaee404a9d2245a42a4362", }, .thespian = .{ - .url = "https://github.com/neurocyte/thespian/archive/09519fb5b004eaa41fcef7ffc4fa744232968cc8.tar.gz", - .hash = "1220efea19c3696d42570e3bef78035cf05ea0d63fb6288e4a1e74536fa20c2f2ff4", + .url = "https://github.com/neurocyte/thespian/archive/06ff2a148c1e33095d4838579461f31141565958.tar.gz", + .hash = "122064ef6d9da7aa0352da12804ab46dbecdabb033e9d6c1b4208844f9dd3694e373", }, .themes = .{ .url = "https://github.com/neurocyte/flow-themes/releases/download/master-803da089c5a0fc3b4513a7c34afe9bdaff83efdc/flow-themes.tar.gz", diff --git a/src/LSP.zig b/src/LSP.zig index e4d914e..f65922f 100644 --- a/src/LSP.zig +++ b/src/LSP.zig @@ -146,7 +146,26 @@ const Process = struct { return self.receive_safe(from, m) catch |e| return tp.exit_error(e, @errorReturnTrace()); } - fn receive_safe(self: *Process, from: tp.pid_ref, m: tp.message) !void { + const ReceiveError = error{ + OutOfMemory, + NoSpaceLeft, + BufferUnderrun, + CborIntegerTooLarge, + CborIntegerTooSmall, + CborInvalidType, + CborTooShort, + CborUnsupportedType, + SyntaxError, + UnexpectedEndOfInput, + InvalidSyntax, + InvalidMessageField, + InvalidMessage, + InvalidContentLength, + Closed, + Exit, + }; + + fn receive_safe(self: *Process, from: tp.pid_ref, m: tp.message) ReceiveError!void { const frame = tracy.initZone(@src(), .{ .name = module_name }); defer frame.deinit(); errdefer self.deinit(); @@ -233,7 +252,7 @@ const Process = struct { } } - fn handle_output(self: *Process, bytes: []u8) !void { + fn handle_output(self: *Process, bytes: []u8) ReceiveError!void { try self.recv_buf.appendSlice(bytes); self.write_log("### RECV:\n{s}\n###\n", .{bytes}); self.frame_message_recv() catch |e| { @@ -250,7 +269,7 @@ const Process = struct { return tp.exit_normal(); } - fn send_request(self: *Process, from: tp.pid_ref, method: []const u8, params_cb: []const u8) !void { + fn send_request(self: *Process, from: tp.pid_ref, method: []const u8, params_cb: []const u8) ReceiveError!void { const sp = if (self.sp) |*sp| sp else return error.Closed; const id = self.next_id; @@ -349,7 +368,7 @@ const Process = struct { self.write_log("### SEND notification:\n{s}\n###\n", .{output.items}); } - fn frame_message_recv(self: *Process) !void { + fn frame_message_recv(self: *Process) ReceiveError!void { const sep = "\r\n\r\n"; const headers_end = std.mem.indexOf(u8, self.recv_buf.items, sep) orelse return; const headers_data = self.recv_buf.items[0..headers_end]; @@ -436,7 +455,7 @@ const Headers = struct { content_length: usize = 0, content_type: ?[]const u8 = null, - fn parse(buf_: []const u8) !Headers { + fn parse(buf_: []const u8) Process.ReceiveError!Headers { var buf = buf_; var ret: Headers = .{}; while (true) { @@ -456,9 +475,12 @@ const Headers = struct { } } - fn parse_one(self: *Headers, name: []const u8, value: []const u8) !void { + fn parse_one(self: *Headers, name: []const u8, value: []const u8) Process.ReceiveError!void { if (std.mem.eql(u8, "Content-Length", name)) { - self.content_length = try std.fmt.parseInt(@TypeOf(self.content_length), value, 10); + self.content_length = std.fmt.parseInt(@TypeOf(self.content_length), value, 10) catch |e| switch (e) { + error.Overflow => return error.InvalidContentLength, + error.InvalidCharacter => return error.InvalidContentLength, + }; } else if (std.mem.eql(u8, "Content-Type", name)) { self.content_type = value; }