Fix segfault: keep JSON body alive for parsed string refs
- Root cause: parseFromSlice returns slices pointing into the raw JSON body, but body was freed immediately after parsing in getUpdates - Fix: return OwnedParsed wrapper that keeps both parsed result and raw body alive together - Switch HTTP layer to curl subprocess (more reliable than std.http with static linking) - Fix downloadToFile: use spawnAndWait instead of collectOutput (collectOutput requires both pipes) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -42,6 +42,21 @@ pub const SendMessageBody = struct {
|
||||
reply_to_message_id: ?i64 = null,
|
||||
};
|
||||
|
||||
/// Parsed JSON result that also owns the raw JSON body.
|
||||
/// Must call deinit() to free both.
|
||||
pub fn OwnedParsed(comptime T: type) type {
|
||||
return struct {
|
||||
parsed: std.json.Parsed(T),
|
||||
raw_body: []u8,
|
||||
allocator: Allocator,
|
||||
|
||||
pub fn deinit(self: *@This()) void {
|
||||
self.parsed.deinit();
|
||||
self.allocator.free(self.raw_body);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
pub const TelegramBot = struct {
|
||||
allocator: Allocator,
|
||||
token: []const u8,
|
||||
@@ -60,14 +75,22 @@ pub const TelegramBot = struct {
|
||||
self.allocator.free(self.api_base);
|
||||
}
|
||||
|
||||
pub fn getUpdates(self: *TelegramBot, offset: i64, timeout: u32) !std.json.Parsed(GetUpdatesResponse) {
|
||||
const url = try std.fmt.allocPrint(self.allocator, "{s}/getUpdates?offset={d}&timeout={d}&allowed_updates=[\"message\"]", .{ self.api_base, offset, timeout });
|
||||
pub fn getUpdates(self: *TelegramBot, offset: i64, timeout: u32) !OwnedParsed(GetUpdatesResponse) {
|
||||
const url = try std.fmt.allocPrint(self.allocator, "{s}/getUpdates?offset={d}&timeout={d}", .{ self.api_base, offset, timeout });
|
||||
defer self.allocator.free(url);
|
||||
|
||||
const body = try http.httpGet(self.allocator, url);
|
||||
defer self.allocator.free(body);
|
||||
|
||||
return std.json.parseFromSlice(GetUpdatesResponse, self.allocator, body, .{ .ignore_unknown_fields = true });
|
||||
const parsed = std.json.parseFromSlice(GetUpdatesResponse, self.allocator, body, .{ .ignore_unknown_fields = true }) catch {
|
||||
self.allocator.free(body);
|
||||
return error.HttpRequestFailed;
|
||||
};
|
||||
|
||||
return .{
|
||||
.parsed = parsed,
|
||||
.raw_body = body,
|
||||
.allocator = self.allocator,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn getFilePath(self: *TelegramBot, file_id: []const u8) ![]u8 {
|
||||
|
||||
Reference in New Issue
Block a user