fix: prevent error.Overflow for LSPs that send crazy large messages
This commit is contained in:
parent
a58ab986f1
commit
6fac0b1cb4
2 changed files with 31 additions and 9 deletions
|
@ -18,8 +18,8 @@
|
||||||
.hash = "1220220dbc7fe91c1c54438193ca765cebbcb7d58f35cdcaee404a9d2245a42a4362",
|
.hash = "1220220dbc7fe91c1c54438193ca765cebbcb7d58f35cdcaee404a9d2245a42a4362",
|
||||||
},
|
},
|
||||||
.thespian = .{
|
.thespian = .{
|
||||||
.url = "https://github.com/neurocyte/thespian/archive/09519fb5b004eaa41fcef7ffc4fa744232968cc8.tar.gz",
|
.url = "https://github.com/neurocyte/thespian/archive/06ff2a148c1e33095d4838579461f31141565958.tar.gz",
|
||||||
.hash = "1220efea19c3696d42570e3bef78035cf05ea0d63fb6288e4a1e74536fa20c2f2ff4",
|
.hash = "122064ef6d9da7aa0352da12804ab46dbecdabb033e9d6c1b4208844f9dd3694e373",
|
||||||
},
|
},
|
||||||
.themes = .{
|
.themes = .{
|
||||||
.url = "https://github.com/neurocyte/flow-themes/releases/download/master-803da089c5a0fc3b4513a7c34afe9bdaff83efdc/flow-themes.tar.gz",
|
.url = "https://github.com/neurocyte/flow-themes/releases/download/master-803da089c5a0fc3b4513a7c34afe9bdaff83efdc/flow-themes.tar.gz",
|
||||||
|
|
36
src/LSP.zig
36
src/LSP.zig
|
@ -146,7 +146,26 @@ const Process = struct {
|
||||||
return self.receive_safe(from, m) catch |e| return tp.exit_error(e, @errorReturnTrace());
|
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 });
|
const frame = tracy.initZone(@src(), .{ .name = module_name });
|
||||||
defer frame.deinit();
|
defer frame.deinit();
|
||||||
errdefer self.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);
|
try self.recv_buf.appendSlice(bytes);
|
||||||
self.write_log("### RECV:\n{s}\n###\n", .{bytes});
|
self.write_log("### RECV:\n{s}\n###\n", .{bytes});
|
||||||
self.frame_message_recv() catch |e| {
|
self.frame_message_recv() catch |e| {
|
||||||
|
@ -250,7 +269,7 @@ const Process = struct {
|
||||||
return tp.exit_normal();
|
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 sp = if (self.sp) |*sp| sp else return error.Closed;
|
||||||
|
|
||||||
const id = self.next_id;
|
const id = self.next_id;
|
||||||
|
@ -349,7 +368,7 @@ const Process = struct {
|
||||||
self.write_log("### SEND notification:\n{s}\n###\n", .{output.items});
|
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 sep = "\r\n\r\n";
|
||||||
const headers_end = std.mem.indexOf(u8, self.recv_buf.items, sep) orelse return;
|
const headers_end = std.mem.indexOf(u8, self.recv_buf.items, sep) orelse return;
|
||||||
const headers_data = self.recv_buf.items[0..headers_end];
|
const headers_data = self.recv_buf.items[0..headers_end];
|
||||||
|
@ -436,7 +455,7 @@ const Headers = struct {
|
||||||
content_length: usize = 0,
|
content_length: usize = 0,
|
||||||
content_type: ?[]const u8 = null,
|
content_type: ?[]const u8 = null,
|
||||||
|
|
||||||
fn parse(buf_: []const u8) !Headers {
|
fn parse(buf_: []const u8) Process.ReceiveError!Headers {
|
||||||
var buf = buf_;
|
var buf = buf_;
|
||||||
var ret: Headers = .{};
|
var ret: Headers = .{};
|
||||||
while (true) {
|
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)) {
|
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)) {
|
} else if (std.mem.eql(u8, "Content-Type", name)) {
|
||||||
self.content_type = value;
|
self.content_type = value;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue