From 69bcdbefd0128c14a4ebb7f1a4cfb784f826b85b Mon Sep 17 00:00:00 2001 From: Nameless Date: Mon, 26 Feb 2024 09:38:27 -0600 Subject: [PATCH] std.http: clear confusing trailer check, add sanity check for invalid field name --- lib/std/http/HeaderIterator.zig | 53 +++++++++++++++++++++++++-------- 1 file changed, 41 insertions(+), 12 deletions(-) diff --git a/lib/std/http/HeaderIterator.zig b/lib/std/http/HeaderIterator.zig index 515058859d..943883d7e2 100644 --- a/lib/std/http/HeaderIterator.zig +++ b/lib/std/http/HeaderIterator.zig @@ -12,26 +12,39 @@ pub fn init(bytes: []const u8) HeaderIterator { pub fn next(it: *HeaderIterator) ?std.http.Header { const end = std.mem.indexOfPosLinear(u8, it.bytes, it.index, "\r\n").?; - var kv_it = std.mem.splitSequence(u8, it.bytes[it.index..end], ": "); - const name = kv_it.next().?; - const value = kv_it.rest(); - if (name.len == 0 and value.len == 0) { + if (it.index == end) { // found the trailer boundary (\r\n\r\n) if (it.is_trailer) return null; + const next_end = std.mem.indexOfPosLinear(u8, it.bytes, end + 2, "\r\n") orelse return null; + + var kv_it = std.mem.splitScalar(u8, it.bytes[end + 2 .. next_end], ':'); + const name = kv_it.first(); + const value = kv_it.rest(); + it.is_trailer = true; it.index = next_end + 2; - kv_it = std.mem.splitSequence(u8, it.bytes[end + 2 .. next_end], ": "); + if (name.len == 0) + return null; + return .{ - .name = kv_it.next().?, - .value = kv_it.rest(), + .name = name, + .value = std.mem.trim(u8, value, " \t"), + }; + } else { // normal header + var kv_it = std.mem.splitScalar(u8, it.bytes[it.index..end], ':'); + const name = kv_it.first(); + const value = kv_it.rest(); + + it.index = end + 2; + if (name.len == 0) + return null; + + return .{ + .name = name, + .value = std.mem.trim(u8, value, " \t"), }; } - it.index = end + 2; - return .{ - .name = name, - .value = value, - }; } test next { @@ -62,7 +75,23 @@ test next { try std.testing.expectEqualStrings("g", header.value); } try std.testing.expectEqual(null, it.next()); + + it = HeaderIterator.init("200 OK\r\n: ss\r\n\r\n"); + try std.testing.expect(!it.is_trailer); + try std.testing.expectEqual(null, it.next()); + + it = HeaderIterator.init("200 OK\r\na: b\r\n\r\n: ss\r\n\r\n"); + try std.testing.expect(!it.is_trailer); + { + const header = it.next().?; + try std.testing.expect(!it.is_trailer); + try std.testing.expectEqualStrings("a", header.name); + try std.testing.expectEqualStrings("b", header.value); + } + try std.testing.expectEqual(null, it.next()); + try std.testing.expect(it.is_trailer); } const HeaderIterator = @This(); const std = @import("../std.zig"); +const assert = std.debug.assert;