mirror of
https://github.com/norandom/OpenUltraSAST.git
synced 2026-10-18 20:49:28 +00:00
Tasks 3.3 and 4.1. - vfc curl and openssl-cve-2021-3449 excerpts re-harvested through the shared library: whole functions with upstream_start headers, the vendored key redacted code-safely, no truncated bodies. - vfc/recipes.toml carries mode, fix_path and function anchors; training/manifest.jsonl regenerated. - Juliet CWE-121 strcpy pair gets its buffer declarations back so the vulnerable side is a real overflow again. Co-Authored-By: Claude Fable 5.1 <[email protected]> Claude-Session: https://claude.ai/code/session_01T7XD7x5KonMdmGRkp63EQG
189 lines
5.5 KiB
C
189 lines
5.5 KiB
C
/* Provenance: curl/curl tool_header_cb (fixed).
|
|
* repo: curl/curl
|
|
* commit: 8236aba58542c5f89f1d41ca09d84579efb05e22
|
|
* parent: 26d2755d7c3181e90e46014778941bff53d2309f
|
|
* commit_url: https://github.com/curl/curl/commit/8236aba58542c5f89f1d41ca09d84579efb05e22
|
|
* cve: CVE-2020-8177
|
|
* license: curl
|
|
* function: tool_header_cb
|
|
* relpath: src/tool_cb_hdr.c
|
|
* provenance: human
|
|
* mechanism: other
|
|
*/
|
|
|
|
size_t tool_header_cb(char *ptr, size_t size, size_t nmemb, void *userdata)
|
|
{
|
|
struct per_transfer *per = userdata;
|
|
struct HdrCbData *hdrcbdata = &per->hdrcbdata;
|
|
struct OutStruct *outs = &per->outs;
|
|
struct OutStruct *heads = &per->heads;
|
|
struct OutStruct *etag_save = &per->etag_save;
|
|
const char *str = ptr;
|
|
const size_t cb = size * nmemb;
|
|
const char *end = (char *)ptr + cb;
|
|
long protocol = 0;
|
|
|
|
/*
|
|
* Once that libcurl has called back tool_header_cb() the returned value
|
|
* is checked against the amount that was intended to be written, if
|
|
* it does not match then it fails with CURLE_WRITE_ERROR. So at this
|
|
* point returning a value different from sz*nmemb indicates failure.
|
|
*/
|
|
size_t failure = (size && nmemb) ? 0 : 1;
|
|
|
|
if(!per->config)
|
|
return failure;
|
|
|
|
#ifdef DEBUGBUILD
|
|
if(size * nmemb > (size_t)CURL_MAX_HTTP_HEADER) {
|
|
warnf(per->config->global, "Header data exceeds single call write "
|
|
"limit!\n");
|
|
return failure;
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
* Write header data when curl option --dump-header (-D) is given.
|
|
*/
|
|
|
|
if(per->config->headerfile && heads->stream) {
|
|
size_t rc = fwrite(ptr, size, nmemb, heads->stream);
|
|
if(rc != cb)
|
|
return rc;
|
|
/* flush the stream to send off what we got earlier */
|
|
(void)fflush(heads->stream);
|
|
}
|
|
|
|
/*
|
|
* Write etag to file when --etag-save option is given.
|
|
* etag string that we want is enveloped in double quotes
|
|
*/
|
|
if(per->config->etag_save_file && etag_save->stream) {
|
|
/* match only header that start with etag (case insensitive) */
|
|
if(curl_strnequal(str, "etag:", 5)) {
|
|
char *etag_h = NULL;
|
|
char *first = NULL;
|
|
char *last = NULL;
|
|
size_t etag_length = 0;
|
|
|
|
etag_h = ptr;
|
|
/* point to first occurrence of double quote */
|
|
first = memchr(etag_h, '\"', cb);
|
|
|
|
/*
|
|
* if server side messed with the etag header and doesn't include
|
|
* double quotes around the etag, kindly exit with a warning
|
|
*/
|
|
|
|
if(!first) {
|
|
warnf(per->config->global,
|
|
"\nReceived header etag is missing double quote/s\n");
|
|
return 1;
|
|
}
|
|
else {
|
|
/* discard first double quote */
|
|
first++;
|
|
}
|
|
|
|
/* point to last occurrence of double quote */
|
|
last = memchr(first, '\"', cb);
|
|
|
|
if(!last) {
|
|
warnf(per->config->global,
|
|
"\nReceived header etag is missing double quote/s\n");
|
|
return 1;
|
|
}
|
|
|
|
/* get length of desired etag */
|
|
etag_length = (size_t)last - (size_t)first;
|
|
|
|
fwrite(first, size, etag_length, etag_save->stream);
|
|
/* terminate with new line */
|
|
fputc('\n', etag_save->stream);
|
|
}
|
|
|
|
(void)fflush(etag_save->stream);
|
|
}
|
|
|
|
/*
|
|
* This callback sets the filename where output shall be written when
|
|
* curl options --remote-name (-O) and --remote-header-name (-J) have
|
|
* been simultaneously given and additionally server returns an HTTP
|
|
* Content-Disposition header specifying a filename property.
|
|
*/
|
|
|
|
curl_easy_getinfo(per->curl, CURLINFO_PROTOCOL, &protocol);
|
|
if(hdrcbdata->honor_cd_filename &&
|
|
(cb > 20) && checkprefix("Content-disposition:", str) &&
|
|
(protocol & (CURLPROTO_HTTPS|CURLPROTO_HTTP))) {
|
|
const char *p = str + 20;
|
|
|
|
/* look for the 'filename=' parameter
|
|
(encoded filenames (*=) are not supported) */
|
|
for(;;) {
|
|
char *filename;
|
|
size_t len;
|
|
|
|
while(*p && (p < end) && !ISALPHA(*p))
|
|
p++;
|
|
if(p > end - 9)
|
|
break;
|
|
|
|
if(memcmp(p, "filename=", 9)) {
|
|
/* no match, find next parameter */
|
|
while((p < end) && (*p != ';'))
|
|
p++;
|
|
continue;
|
|
}
|
|
p += 9;
|
|
|
|
/* this expression below typecasts 'cb' only to avoid
|
|
warning: signed and unsigned type in conditional expression
|
|
*/
|
|
len = (ssize_t)cb - (p - str);
|
|
filename = parse_filename(p, len);
|
|
if(filename) {
|
|
if(outs->stream) {
|
|
/* indication of problem, get out! */
|
|
free(filename);
|
|
return failure;
|
|
}
|
|
|
|
outs->is_cd_filename = TRUE;
|
|
outs->s_isreg = TRUE;
|
|
outs->fopened = FALSE;
|
|
outs->filename = filename;
|
|
outs->alloc_filename = TRUE;
|
|
hdrcbdata->honor_cd_filename = FALSE; /* done now! */
|
|
if(!tool_create_output_file(outs, per->config))
|
|
return failure;
|
|
}
|
|
break;
|
|
}
|
|
if(!outs->stream && !tool_create_output_file(outs, per->config))
|
|
return failure;
|
|
}
|
|
|
|
if(hdrcbdata->config->show_headers &&
|
|
(protocol &
|
|
(CURLPROTO_HTTP|CURLPROTO_HTTPS|CURLPROTO_RTSP|CURLPROTO_FILE))) {
|
|
/* bold headers only for selected protocols */
|
|
char *value = NULL;
|
|
|
|
if(!outs->stream && !tool_create_output_file(outs, per->config))
|
|
return failure;
|
|
|
|
if(hdrcbdata->global->isatty && hdrcbdata->global->styled_output)
|
|
value = memchr(ptr, ':', cb);
|
|
if(value) {
|
|
size_t namelen = value - ptr;
|
|
fprintf(outs->stream, BOLD "%.*s" BOLDOFF ":", namelen, ptr);
|
|
fwrite(&value[1], cb - namelen - 1, 1, outs->stream);
|
|
}
|
|
else
|
|
/* not "handled", just show it */
|
|
fwrite(ptr, cb, 1, outs->stream);
|
|
}
|
|
return cb;
|
|
}
|