authorgravatar for truemedian@gmail.comNameless <truemedian@gmail.com> 2024-02-26 09:38:27-06:00
committergravatar for truemedian@gmail.comNameless <truemedian@gmail.com> 2024-02-28 15:12:41-06:00
log69bcdbefd0128c14a4ebb7f1a4cfb784f826b85b
treed1daf5394b1a0a7f75fdcf177a994874136cde15
parent9410b11ca663231e367e3adfd668979c4b870a41
signaturelock-open Commit is signed but in an unrecognized format.

std.http: clear confusing trailer check, add sanity check for invalid field name


1 files changed, 41 insertions(+), 12 deletions(-)

lib/std/http/HeaderIterator.zig+41-12
...@@ -12,26 +12,39 @@ pub fn init(bytes: []const u8) HeaderIterator {...@@ -12,26 +12,39 @@ pub fn init(bytes: []const u8) HeaderIterator {
1212
13pub fn next(it: *HeaderIterator) ?std.http.Header {13pub fn next(it: *HeaderIterator) ?std.http.Header {
14 const end = std.mem.indexOfPosLinear(u8, it.bytes, it.index, "\r\n").?;14 const end = std.mem.indexOfPosLinear(u8, it.bytes, it.index, "\r\n").?;
15 var kv_it = std.mem.splitSequence(u8, it.bytes[it.index..end], ": ");15 if (it.index == end) { // found the trailer boundary (\r\n\r\n)
16 const name = kv_it.next().?;
17 const value = kv_it.rest();
18 if (name.len == 0 and value.len == 0) {
19 if (it.is_trailer) return null;16 if (it.is_trailer) return null;
17
20 const next_end = std.mem.indexOfPosLinear(u8, it.bytes, end + 2, "\r\n") orelse18 const next_end = std.mem.indexOfPosLinear(u8, it.bytes, end + 2, "\r\n") orelse
21 return null;19 return null;
20
21 var kv_it = std.mem.splitScalar(u8, it.bytes[end + 2 .. next_end], ':');
22 const name = kv_it.first();
23 const value = kv_it.rest();
24
22 it.is_trailer = true;25 it.is_trailer = true;
23 it.index = next_end + 2;26 it.index = next_end + 2;
24 kv_it = std.mem.splitSequence(u8, it.bytes[end + 2 .. next_end], ": ");27 if (name.len == 0)
28 return null;
29
30 return .{
31 .name = name,
32 .value = std.mem.trim(u8, value, " \t"),
33 };
34 } else { // normal header
35 var kv_it = std.mem.splitScalar(u8, it.bytes[it.index..end], ':');
36 const name = kv_it.first();
37 const value = kv_it.rest();
38
39 it.index = end + 2;
40 if (name.len == 0)
41 return null;
42
25 return .{43 return .{
26 .name = kv_it.next().?,44 .name = name,
27 .value = kv_it.rest(),45 .value = std.mem.trim(u8, value, " \t"),
28 };46 };
29 }47 }
30 it.index = end + 2;
31 return .{
32 .name = name,
33 .value = value,
34 };
35}48}
3649
37test next {50test next {
...@@ -62,7 +75,23 @@ test next {...@@ -62,7 +75,23 @@ test next {
62 try std.testing.expectEqualStrings("g", header.value);75 try std.testing.expectEqualStrings("g", header.value);
63 }76 }
64 try std.testing.expectEqual(null, it.next());77 try std.testing.expectEqual(null, it.next());
78
79 it = HeaderIterator.init("200 OK\r\n: ss\r\n\r\n");
80 try std.testing.expect(!it.is_trailer);
81 try std.testing.expectEqual(null, it.next());
82
83 it = HeaderIterator.init("200 OK\r\na: b\r\n\r\n: ss\r\n\r\n");
84 try std.testing.expect(!it.is_trailer);
85 {
86 const header = it.next().?;
87 try std.testing.expect(!it.is_trailer);
88 try std.testing.expectEqualStrings("a", header.name);
89 try std.testing.expectEqualStrings("b", header.value);
90 }
91 try std.testing.expectEqual(null, it.next());
92 try std.testing.expect(it.is_trailer);
65}93}
6694
67const HeaderIterator = @This();95const HeaderIterator = @This();
68const std = @import("../std.zig");96const std = @import("../std.zig");
97const assert = std.debug.assert;