MCPcopy Create free account
hub / github.com/DeusData/codebase-memory-mcp / cbm_http_parse_head

Function cbm_http_parse_head

src/ui/httpd.c:253–375  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

251}
252
253int cbm_http_parse_head(const char *data, size_t len, cbm_http_req_t *req, size_t *body_offset,
254 size_t *content_length) {
255 memset(req, 0, sizeof(*req));
256 *body_offset = 0;
257 *content_length = 0;
258
259 /* Scan for the CRLFCRLF terminator. While scanning, enforce the strict
260 * byte rules: no raw NUL, no LF that is not preceded by CR. */
261 size_t scan = len < CBM_HTTP_MAX_HEAD ? len : CBM_HTTP_MAX_HEAD;
262 size_t head_end = 0; /* offset just past CRLFCRLF */
263 for (size_t i = 0; i < scan; i++) {
264 char ch = data[i];
265 if (ch == '\0')
266 return 400;
267 if (ch == '\n' && (i == 0 || data[i - 1] != '\r'))
268 return 400;
269 if (ch == '\n' && i >= 3 && data[i - 3] == '\r' && data[i - 2] == '\n') {
270 head_end = i + 1;
271 break;
272 }
273 }
274 if (head_end == 0)
275 return len >= CBM_HTTP_MAX_HEAD ? 431 : CBM_HTTP_NEED_MORE;
276
277 /* ── Request line: METHOD SP request-target SP HTTP/1.x ── */
278 const char *line = data;
279 const char *line_end = memchr(line, '\r', head_end);
280 if (!line_end)
281 return 400;
282
283 const char *sp1 = memchr(line, ' ', (size_t)(line_end - line));
284 if (!sp1)
285 return 400;
286 size_t mlen = (size_t)(sp1 - line);
287 if (mlen == 0 || mlen >= sizeof(req->method))
288 return 400;
289 for (size_t i = 0; i < mlen; i++) {
290 if (!isupper((unsigned char)line[i]))
291 return 400;
292 }
293 memcpy(req->method, line, mlen);
294 req->method[mlen] = '\0';
295
296 const char *target = sp1 + 1;
297 const char *sp2 = memchr(target, ' ', (size_t)(line_end - target));
298 if (!sp2)
299 return 400;
300 const char *version = sp2 + 1;
301 size_t vlen = (size_t)(line_end - version);
302 /* Exactly HTTP/1.0 or HTTP/1.1 */
303 if (vlen != 8 || memcmp(version, "HTTP/1.", 7) != 0 || (version[7] != '0' && version[7] != '1'))
304 return 400;
305
306 size_t tlen = (size_t)(sp2 - target);
307 if (tlen == 0 || target[0] != '/')
308 return 400;
309 /* Reject percent-encoded NUL anywhere in the request target. */
310 for (size_t i = 0; i + 2 < tlen; i++) {

Callers 2

cbm_httpd_read_requestFunction · 0.85
test_httpd.cFile · 0.85

Calls 2

header_name_isFunction · 0.85
copy_header_valueFunction · 0.85

Tested by

no test coverage detected