From 0ed7a45baf7e7e5dd852bf16cd7d10bc1544803f Mon Sep 17 00:00:00 2001 From: Pierre Tachoire Date: Fri, 29 Nov 2024 09:40:33 +0100 Subject: [PATCH 1/2] reproduce invalid free when requesting same srv twice --- src/tests.zig | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/tests.zig b/src/tests.zig index cf4db19..748884f 100644 --- a/src/tests.zig +++ b/src/tests.zig @@ -37,8 +37,19 @@ pub fn onRequestConnect(ctx: *Ctx, res: anyerror!void) anyerror!void { return ctx.req.async_send(ctx, onRequestSend); } -test "example.com" { +test "PLAIN example.com" { var urls = [_][]const u8{ + "http://www.example.com", + "http://www.example.com", + "http://www.example.com", + }; + try do(&urls); +} + +test "TLS example.com" { + var urls = [_][]const u8{ + "https://www.example.com", + "https://www.example.com", "https://www.example.com", }; try do(&urls); From ea422e005064f2dd9531254890e97b6182d9c959 Mon Sep 17 00:00:00 2001 From: Pierre Tachoire Date: Fri, 29 Nov 2024 11:26:19 +0100 Subject: [PATCH 2/2] fix mem leak on conn reuse --- src/std/http/Client.zig | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/src/std/http/Client.zig b/src/std/http/Client.zig index 0506dc1..895802a 100644 --- a/src/std/http/Client.zig +++ b/src/std/http/Client.zig @@ -1695,6 +1695,7 @@ fn setConnection(ctx: *Ctx, res: anyerror!void) !void { .port = ctx.data.conn.port, }, }; + // remove old pointer, now useless const old_conn = ctx.data.conn; defer ctx.req.client.allocator.destroy(old_conn); @@ -1777,6 +1778,11 @@ pub fn async_connectTcp( .port = port, .protocol = protocol, })) |conn| { + // remove old ctx pointer, now useless + const old_conn = ctx.data.conn; + defer ctx.req.client.allocator.destroy(old_conn); + defer ctx.req.client.allocator.free(old_conn.host); + ctx.data.conn = conn; ctx.req.connection = conn; return ctx.pop({}); @@ -2256,7 +2262,13 @@ pub fn async_open( // add fields to connection ctx.data.conn.protocol = protocol; + + // free the previous host + client.allocator.free(ctx.data.conn.host); + ctx.data.conn.host = try client.allocator.dupe(u8, host.raw); + errdefer client.allocator.free(ctx.data.conn.host); + ctx.data.conn.port = port; return client.async_connect(host.raw, port, protocol, ctx, setRequestConnection); @@ -2419,14 +2431,22 @@ pub const Ctx = struct { _tls_write_buf: [cipher.max_ciphertext_record_len]u8 = undefined, pub fn init(io: *IO, req: *Request) !Ctx { - const connection = try req.client.allocator.create(Connection); + const allocator = req.client.allocator; + + const connection = try allocator.create(Connection); + errdefer allocator.destroy(connection); + + const host = try allocator.dupe(u8, ""); + errdefer allocator.free(host); + connection.* = .{ .stream = undefined, .tls_client = undefined, .protocol = undefined, - .host = undefined, + .host = host, .port = undefined, }; + return .{ .req = req, .io = io,