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

Function cbm_http_parse_head

src/ui/httpd.c:457–599  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

455}
456
457int cbm_http_parse_head(const char *data, size_t len, cbm_http_req_t *req, size_t *body_offset,
458 size_t *content_length) {
459 memset(req, 0, sizeof(*req));
460 *body_offset = 0;
461 *content_length = 0;
462
463 /* Scan for the CRLFCRLF terminator. While scanning, enforce the strict
464 * byte rules: no raw NUL, no LF that is not preceded by CR. */
465 size_t scan = len < CBM_HTTP_MAX_HEAD ? len : CBM_HTTP_MAX_HEAD;
466 size_t head_end = 0; /* offset just past CRLFCRLF */
467 for (size_t i = 0; i < scan; i++) {
468 char ch = data[i];
469 if (ch == '\0')
470 return 400;
471 if (ch == '\n' && (i == 0 || data[i - 1] != '\r'))
472 return 400;
473 if (ch == '\n' && i >= 3 && data[i - 3] == '\r' && data[i - 2] == '\n') {
474 head_end = i + 1;
475 break;
476 }
477 }
478 if (head_end == 0)
479 return len >= CBM_HTTP_MAX_HEAD ? 431 : CBM_HTTP_NEED_MORE;
480
481 /* ── Request line: METHOD SP request-target SP HTTP/1.x ── */
482 const char *line = data;
483 const char *line_end = memchr(line, '\r', head_end);
484 if (!line_end)
485 return 400;
486
487 const char *sp1 = memchr(line, ' ', (size_t)(line_end - line));
488 if (!sp1)
489 return 400;
490 size_t mlen = (size_t)(sp1 - line);
491 if (mlen == 0 || mlen >= sizeof(req->method))
492 return 400;
493 for (size_t i = 0; i < mlen; i++) {
494 if (!isupper((unsigned char)line[i]))
495 return 400;
496 }
497 memcpy(req->method, line, mlen);
498 req->method[mlen] = '\0';
499
500 const char *target = sp1 + 1;
501 const char *sp2 = memchr(target, ' ', (size_t)(line_end - target));
502 if (!sp2)
503 return 400;
504 const char *version = sp2 + 1;
505 size_t vlen = (size_t)(line_end - version);
506 /* Exactly HTTP/1.0 or HTTP/1.1 */
507 if (vlen != 8 || memcmp(version, "HTTP/1.", 7) != 0 || (version[7] != '0' && version[7] != '1'))
508 return 400;
509 req->http_minor = (unsigned char)(version[7] - '0');
510
511 size_t tlen = (size_t)(sp2 - target);
512 if (tlen == 0 || target[0] != '/')
513 return 400;
514 /* Reject percent-encoded NUL anywhere in the request target. */

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