authorgravatar for mail@isaacfreund.comIsaac Freund <mail@isaacfreund.com> 2025-08-17 09:45:08+02:00
committergravatar for mail@isaacfreund.comIsaac Freund <mail@isaacfreund.com> 2025-08-17 14:42:57+02:00
logc315f2bc2eacc33e2a6e0fcb5b775e20aa506aa7
tree3d61bec5d96b8dc46207bd130cac93addc8614cd
parent623290ea9b23780303e18f200fb0e4ca1861cf57

http.BodyWriter: improve clarity of chunked state machine

This is theoretically a bugfix as well, since it enforces the correct limit on the first write after writing the header. This theoretical bug hasn't been hit in practice though as far as I know.

1 files changed, 8 insertions(+), 11 deletions(-)

lib/std/http.zig+8-11
...@@ -864,7 +864,7 @@ pub const BodyWriter = struct {...@@ -864,7 +864,7 @@ pub const BodyWriter = struct {
864 const bw = w.http_protocol_output;864 const bw = w.http_protocol_output;
865 switch (w.state.chunk_len) {865 switch (w.state.chunk_len) {
866 0 => {},866 0 => {},
867 1 => try bw.writeByte('\n'),867 1 => unreachable, // Wrote more data than specified in chunk header.
868 2 => try bw.writeAll("\r\n"),868 2 => try bw.writeAll("\r\n"),
869 else => unreachable, // An earlier write call indicated more data would follow.869 else => unreachable, // An earlier write call indicated more data would follow.
870 }870 }
...@@ -963,17 +963,15 @@ pub const BodyWriter = struct {...@@ -963,17 +963,15 @@ pub const BodyWriter = struct {
963 return error.Unimplemented;963 return error.Unimplemented;
964 };964 };
965 const out = bw.http_protocol_output;965 const out = bw.http_protocol_output;
966 switch (bw.state.chunk_len) {966 l: switch (bw.state.chunk_len) {
967 0 => {967 0 => {
968 const header_buf = try out.writableArray(chunk_header_template.len);968 const header_buf = try out.writableArray(chunk_header_template.len);
969 @memcpy(header_buf, chunk_header_template);969 @memcpy(header_buf, chunk_header_template);
970 writeHex(header_buf[0..chunk_len_digits], data_len);970 writeHex(header_buf[0..chunk_len_digits], data_len);
971 const n = try out.sendFileHeader(w.buffered(), file_reader, limit);971 bw.state.chunk_len = data_len + 2;
972 bw.state.chunk_len = data_len + 2 - n;972 continue :l bw.state.chunk_len;
973 const ret = w.consume(n);
974 return ret;
975 },973 },
976 1 => unreachable,974 1 => unreachable, // Wrote more data than specified in chunk header.
977 2 => {975 2 => {
978 try out.writeAll("\r\n");976 try out.writeAll("\r\n");
979 bw.state.chunk_len = 0;977 bw.state.chunk_len = 0;
...@@ -1003,11 +1001,10 @@ pub const BodyWriter = struct {...@@ -1003,11 +1001,10 @@ pub const BodyWriter = struct {
1003 const header_buf = try out.writableArray(chunk_header_template.len);1001 const header_buf = try out.writableArray(chunk_header_template.len);
1004 @memcpy(header_buf, chunk_header_template);1002 @memcpy(header_buf, chunk_header_template);
1005 writeHex(header_buf[0..chunk_len_digits], data_len);1003 writeHex(header_buf[0..chunk_len_digits], data_len);
1006 const n = try out.writeSplatHeader(w.buffered(), data, splat);1004 bw.state.chunk_len = data_len + 2;
1007 bw.state.chunk_len = data_len + 2 - n;1005 continue :l bw.state.chunk_len;
1008 return w.consume(n);
1009 },1006 },
1010 1 => unreachable,1007 1 => unreachable, // Wrote more data than specified in chunk header.
1011 2 => {1008 2 => {
1012 try out.writeAll("\r\n");1009 try out.writeAll("\r\n");
1013 bw.state.chunk_len = 0;1010 bw.state.chunk_len = 0;