mirror of
https://github.com/norandom/OpenUltraSAST.git
synced 2026-10-21 14:09:27 +00:00
feat(real-world-vfc-slice): add labeled OpenSSL/Firefox/Chromium/curl pair corpus
Harvest 176 isolated vuln-vs-fix functions (109 CVEs, 352 training rows) into benchmarks/pairs/vfc with provenance and a JSONL training manifest. Score the slice as an honesty dashboard (ousast pairs --slice vfc); keep the pair gate on the local fixtures only.
This commit is contained in:
@@ -0,0 +1,163 @@
|
||||
/* Provenance: curl/curl Curl_add_custom_headers (fixed).
|
||||
* repo: curl/curl
|
||||
* commit: 6e659993952aa5f90f48864be84a1bbb047fc258
|
||||
* parent: 8f2079154f80561ccffcaa954268798b658e66b6
|
||||
* commit_url: https://github.com/curl/curl/commit/6e659993952aa5f90f48864be84a1bbb047fc258
|
||||
* cve: CVE-2022-27776
|
||||
* license: curl
|
||||
* function: Curl_add_custom_headers
|
||||
* relpath: lib/http.c
|
||||
*/
|
||||
|
||||
CURLcode Curl_add_custom_headers(struct Curl_easy *data,
|
||||
bool is_connect,
|
||||
#ifndef USE_HYPER
|
||||
struct dynbuf *req
|
||||
#else
|
||||
void *req
|
||||
#endif
|
||||
)
|
||||
{
|
||||
struct connectdata *conn = data->conn;
|
||||
char *ptr;
|
||||
struct curl_slist *h[2];
|
||||
struct curl_slist *headers;
|
||||
int numlists = 1; /* by default */
|
||||
int i;
|
||||
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
enum proxy_use proxy;
|
||||
|
||||
if(is_connect)
|
||||
proxy = HEADER_CONNECT;
|
||||
else
|
||||
proxy = conn->bits.httpproxy && !conn->bits.tunnel_proxy?
|
||||
HEADER_PROXY:HEADER_SERVER;
|
||||
|
||||
switch(proxy) {
|
||||
case HEADER_SERVER:
|
||||
h[0] = data->set.headers;
|
||||
break;
|
||||
case HEADER_PROXY:
|
||||
h[0] = data->set.headers;
|
||||
if(data->set.sep_headers) {
|
||||
h[1] = data->set.proxyheaders;
|
||||
numlists++;
|
||||
}
|
||||
break;
|
||||
case HEADER_CONNECT:
|
||||
if(data->set.sep_headers)
|
||||
h[0] = data->set.proxyheaders;
|
||||
else
|
||||
h[0] = data->set.headers;
|
||||
break;
|
||||
}
|
||||
#else
|
||||
(void)is_connect;
|
||||
h[0] = data->set.headers;
|
||||
#endif
|
||||
|
||||
/* loop through one or two lists */
|
||||
for(i = 0; i < numlists; i++) {
|
||||
headers = h[i];
|
||||
|
||||
while(headers) {
|
||||
char *semicolonp = NULL;
|
||||
ptr = strchr(headers->data, ':');
|
||||
if(!ptr) {
|
||||
char *optr;
|
||||
/* no colon, semicolon? */
|
||||
ptr = strchr(headers->data, ';');
|
||||
if(ptr) {
|
||||
optr = ptr;
|
||||
ptr++; /* pass the semicolon */
|
||||
while(*ptr && ISSPACE(*ptr))
|
||||
ptr++;
|
||||
|
||||
if(*ptr) {
|
||||
/* this may be used for something else in the future */
|
||||
optr = NULL;
|
||||
}
|
||||
else {
|
||||
if(*(--ptr) == ';') {
|
||||
/* copy the source */
|
||||
semicolonp = strdup(headers->data);
|
||||
if(!semicolonp) {
|
||||
#ifndef USE_HYPER
|
||||
Curl_dyn_free(req);
|
||||
#endif
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
/* put a colon where the semicolon is */
|
||||
semicolonp[ptr - headers->data] = ':';
|
||||
/* point at the colon */
|
||||
optr = &semicolonp [ptr - headers->data];
|
||||
}
|
||||
}
|
||||
ptr = optr;
|
||||
}
|
||||
}
|
||||
if(ptr && (ptr != headers->data)) {
|
||||
/* we require a colon for this to be a true header */
|
||||
|
||||
ptr++; /* pass the colon */
|
||||
while(*ptr && ISSPACE(*ptr))
|
||||
ptr++;
|
||||
|
||||
if(*ptr || semicolonp) {
|
||||
/* only send this if the contents was non-blank or done special */
|
||||
CURLcode result = CURLE_OK;
|
||||
char *compare = semicolonp ? semicolonp : headers->data;
|
||||
|
||||
if(data->state.aptr.host &&
|
||||
/* a Host: header was sent already, don't pass on any custom Host:
|
||||
header as that will produce *two* in the same request! */
|
||||
checkprefix("Host:", compare))
|
||||
;
|
||||
else if(data->state.httpreq == HTTPREQ_POST_FORM &&
|
||||
/* this header (extended by formdata.c) is sent later */
|
||||
checkprefix("Content-Type:", compare))
|
||||
;
|
||||
else if(data->state.httpreq == HTTPREQ_POST_MIME &&
|
||||
/* this header is sent later */
|
||||
checkprefix("Content-Type:", compare))
|
||||
;
|
||||
else if(conn->bits.authneg &&
|
||||
/* while doing auth neg, don't allow the custom length since
|
||||
we will force length zero then */
|
||||
checkprefix("Content-Length:", compare))
|
||||
;
|
||||
else if(data->state.aptr.te &&
|
||||
/* when asking for Transfer-Encoding, don't pass on a custom
|
||||
Connection: */
|
||||
checkprefix("Connection:", compare))
|
||||
;
|
||||
else if((conn->httpversion >= 20) &&
|
||||
checkprefix("Transfer-Encoding:", compare))
|
||||
/* HTTP/2 doesn't support chunked requests */
|
||||
;
|
||||
else if((checkprefix("Authorization:", compare) ||
|
||||
checkprefix("Cookie:", compare)) &&
|
||||
/* be careful of sending this potentially sensitive header to
|
||||
other hosts */
|
||||
!allow_auth_to_host(data))
|
||||
;
|
||||
else {
|
||||
#ifdef USE_HYPER
|
||||
result = Curl_hyper_header(data, req, compare);
|
||||
#else
|
||||
result = Curl_dyn_addf(req, "%s\r\n", compare);
|
||||
#endif
|
||||
}
|
||||
if(semicolonp)
|
||||
free(semicolonp);
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
}
|
||||
headers = headers->next;
|
||||
}
|
||||
}
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
@@ -0,0 +1,166 @@
|
||||
/* Provenance: curl/curl Curl_add_custom_headers (vuln).
|
||||
* repo: curl/curl
|
||||
* commit: 8f2079154f80561ccffcaa954268798b658e66b6
|
||||
* parent: 8f2079154f80561ccffcaa954268798b658e66b6
|
||||
* commit_url: https://github.com/curl/curl/commit/6e659993952aa5f90f48864be84a1bbb047fc258
|
||||
* cve: CVE-2022-27776
|
||||
* license: curl
|
||||
* function: Curl_add_custom_headers
|
||||
* relpath: lib/http.c
|
||||
*/
|
||||
|
||||
CURLcode Curl_add_custom_headers(struct Curl_easy *data,
|
||||
bool is_connect,
|
||||
#ifndef USE_HYPER
|
||||
struct dynbuf *req
|
||||
#else
|
||||
void *req
|
||||
#endif
|
||||
)
|
||||
{
|
||||
struct connectdata *conn = data->conn;
|
||||
char *ptr;
|
||||
struct curl_slist *h[2];
|
||||
struct curl_slist *headers;
|
||||
int numlists = 1; /* by default */
|
||||
int i;
|
||||
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
enum proxy_use proxy;
|
||||
|
||||
if(is_connect)
|
||||
proxy = HEADER_CONNECT;
|
||||
else
|
||||
proxy = conn->bits.httpproxy && !conn->bits.tunnel_proxy?
|
||||
HEADER_PROXY:HEADER_SERVER;
|
||||
|
||||
switch(proxy) {
|
||||
case HEADER_SERVER:
|
||||
h[0] = data->set.headers;
|
||||
break;
|
||||
case HEADER_PROXY:
|
||||
h[0] = data->set.headers;
|
||||
if(data->set.sep_headers) {
|
||||
h[1] = data->set.proxyheaders;
|
||||
numlists++;
|
||||
}
|
||||
break;
|
||||
case HEADER_CONNECT:
|
||||
if(data->set.sep_headers)
|
||||
h[0] = data->set.proxyheaders;
|
||||
else
|
||||
h[0] = data->set.headers;
|
||||
break;
|
||||
}
|
||||
#else
|
||||
(void)is_connect;
|
||||
h[0] = data->set.headers;
|
||||
#endif
|
||||
|
||||
/* loop through one or two lists */
|
||||
for(i = 0; i < numlists; i++) {
|
||||
headers = h[i];
|
||||
|
||||
while(headers) {
|
||||
char *semicolonp = NULL;
|
||||
ptr = strchr(headers->data, ':');
|
||||
if(!ptr) {
|
||||
char *optr;
|
||||
/* no colon, semicolon? */
|
||||
ptr = strchr(headers->data, ';');
|
||||
if(ptr) {
|
||||
optr = ptr;
|
||||
ptr++; /* pass the semicolon */
|
||||
while(*ptr && ISSPACE(*ptr))
|
||||
ptr++;
|
||||
|
||||
if(*ptr) {
|
||||
/* this may be used for something else in the future */
|
||||
optr = NULL;
|
||||
}
|
||||
else {
|
||||
if(*(--ptr) == ';') {
|
||||
/* copy the source */
|
||||
semicolonp = strdup(headers->data);
|
||||
if(!semicolonp) {
|
||||
#ifndef USE_HYPER
|
||||
Curl_dyn_free(req);
|
||||
#endif
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
/* put a colon where the semicolon is */
|
||||
semicolonp[ptr - headers->data] = ':';
|
||||
/* point at the colon */
|
||||
optr = &semicolonp [ptr - headers->data];
|
||||
}
|
||||
}
|
||||
ptr = optr;
|
||||
}
|
||||
}
|
||||
if(ptr && (ptr != headers->data)) {
|
||||
/* we require a colon for this to be a true header */
|
||||
|
||||
ptr++; /* pass the colon */
|
||||
while(*ptr && ISSPACE(*ptr))
|
||||
ptr++;
|
||||
|
||||
if(*ptr || semicolonp) {
|
||||
/* only send this if the contents was non-blank or done special */
|
||||
CURLcode result = CURLE_OK;
|
||||
char *compare = semicolonp ? semicolonp : headers->data;
|
||||
|
||||
if(data->state.aptr.host &&
|
||||
/* a Host: header was sent already, don't pass on any custom Host:
|
||||
header as that will produce *two* in the same request! */
|
||||
checkprefix("Host:", compare))
|
||||
;
|
||||
else if(data->state.httpreq == HTTPREQ_POST_FORM &&
|
||||
/* this header (extended by formdata.c) is sent later */
|
||||
checkprefix("Content-Type:", compare))
|
||||
;
|
||||
else if(data->state.httpreq == HTTPREQ_POST_MIME &&
|
||||
/* this header is sent later */
|
||||
checkprefix("Content-Type:", compare))
|
||||
;
|
||||
else if(conn->bits.authneg &&
|
||||
/* while doing auth neg, don't allow the custom length since
|
||||
we will force length zero then */
|
||||
checkprefix("Content-Length:", compare))
|
||||
;
|
||||
else if(data->state.aptr.te &&
|
||||
/* when asking for Transfer-Encoding, don't pass on a custom
|
||||
Connection: */
|
||||
checkprefix("Connection:", compare))
|
||||
;
|
||||
else if((conn->httpversion >= 20) &&
|
||||
checkprefix("Transfer-Encoding:", compare))
|
||||
/* HTTP/2 doesn't support chunked requests */
|
||||
;
|
||||
else if((checkprefix("Authorization:", compare) ||
|
||||
checkprefix("Cookie:", compare)) &&
|
||||
/* be careful of sending this potentially sensitive header to
|
||||
other hosts */
|
||||
(data->state.this_is_a_follow &&
|
||||
data->state.first_host &&
|
||||
!data->set.allow_auth_to_other_hosts &&
|
||||
!strcasecompare(data->state.first_host, conn->host.name)))
|
||||
;
|
||||
else {
|
||||
#ifdef USE_HYPER
|
||||
result = Curl_hyper_header(data, req, compare);
|
||||
#else
|
||||
result = Curl_dyn_addf(req, "%s\r\n", compare);
|
||||
#endif
|
||||
}
|
||||
if(semicolonp)
|
||||
free(semicolonp);
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
}
|
||||
headers = headers->next;
|
||||
}
|
||||
}
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
Reference in New Issue
Block a user