diff --git a/lib/std/http/Client.zig b/lib/std/http/Client.zig index b71548d634..f9cf6c1d0e 100644 --- a/lib/std/http/Client.zig +++ b/lib/std/http/Client.zig @@ -1505,12 +1505,26 @@ pub const protocol_map = std.ComptimeStringMap(Connection.Protocol, .{ /// /// The caller is responsible for calling `deinit()` on the `Request`. /// This function is threadsafe. +/// +/// Asserts that "\r\n" does not occur in any header name or value. pub fn open( client: *Client, method: http.Method, uri: Uri, options: RequestOptions, ) RequestError!Request { + if (std.debug.runtime_safety) { + for (options.extra_headers) |header| { + assert(std.mem.indexOfScalar(u8, header.name, ':') == null); + assert(std.mem.indexOfPosLinear(u8, header.name, 0, "\r\n") == null); + assert(std.mem.indexOfPosLinear(u8, header.value, 0, "\r\n") == null); + } + for (options.privileged_headers) |header| { + assert(std.mem.indexOfPosLinear(u8, header.name, 0, "\r\n") == null); + assert(std.mem.indexOfPosLinear(u8, header.value, 0, "\r\n") == null); + } + } + const protocol = protocol_map.get(uri.scheme) orelse return error.UnsupportedUrlScheme; const port: u16 = uri.port orelse switch (protocol) { diff --git a/lib/std/http/Server.zig b/lib/std/http/Server.zig index 9c865bf604..226e13fc32 100644 --- a/lib/std/http/Server.zig +++ b/lib/std/http/Server.zig @@ -296,6 +296,7 @@ pub const Request = struct { /// /// Asserts status is not `continue`. /// Asserts there are at most 25 extra_headers. + /// Asserts that "\r\n" does not occur in any header name or value. pub fn respond( request: *Request, content: []const u8, @@ -304,6 +305,13 @@ pub const Request = struct { const max_extra_headers = 25; assert(options.status != .@"continue"); assert(options.extra_headers.len <= max_extra_headers); + if (std.debug.runtime_safety) { + for (options.extra_headers) |header| { + assert(std.mem.indexOfScalar(u8, header.name, ':') == null); + assert(std.mem.indexOfPosLinear(u8, header.name, 0, "\r\n") == null); + assert(std.mem.indexOfPosLinear(u8, header.value, 0, "\r\n") == null); + } + } const transfer_encoding_none = (options.transfer_encoding orelse .chunked) == .none; const server_keep_alive = !transfer_encoding_none and options.keep_alive; @@ -765,7 +773,7 @@ pub const Response = struct { /// Respects the value of `elide_body` to omit all data after the headers. /// Asserts there are at most 25 trailers. pub fn endChunked(r: *Response, options: EndChunkedOptions) WriteError!void { - assert(r.content_length == null); + assert(r.transfer_encoding == .chunked); try flush_chunked(r, options.trailers); r.* = undefined; }