← Commit list

e9b291cf9b

Stefan Eissing
Stefan Eissing
2026-08-12
SUCCESS Duration: 416s

Subject

header api: add guards

Binary

No binary (build failed)

Architecture & Compiler Flags

Architecture: x86_64-linux-gnu Compiler: gcc (Ubuntu 11.4.0-1ubuntu1~22.04.3) 11.4.0

—

Build Log

(log yok)

Commit Diff GitHub →

lib/api.c+20 -0
@@ -43,6 +43,8 @@ static const struct Curl_eapi_fn_props eapi_fn_props[CURL_EAPI_FN_LAST] = {
{ CURL_EAPI_FN_easy_cleanup, 1, 0, 0, 0 },
{ CURL_EAPI_FN_easy_duphandle, 0, 1, 0, 0 },
{ CURL_EAPI_FN_easy_getinfo, 0, 1, 0, 0 },
+ { CURL_EAPI_FN_easy_header, 0, 1, 0, 0 },
+ { CURL_EAPI_FN_easy_nextheader, 0, 1, 0, 0 },
{ CURL_EAPI_FN_easy_pause, 0, 1, 1, 0 },
{ CURL_EAPI_FN_easy_perform_ev, 0, 0, 0, 1 },
{ CURL_EAPI_FN_easy_perform, 0, 0, 0, 1 },
@@ -303,6 +305,24 @@ void Curl_eapi_leave(struct Curl_eapi_guard *guard)
}
}
+CURLHcode Curl_eapi_hcode(CURLcode result)
+{
+ switch(result) {
+ case CURLE_OK:
+ return CURLHE_OK;
+ case CURLE_BAD_FUNCTION_ARGUMENT:
+ return CURLHE_BAD_ARGUMENT;
+ case CURLE_OUT_OF_MEMORY:
+ return CURLHE_OUT_OF_MEMORY;
+ case CURLE_NOT_BUILT_IN:
+ return CURLHE_NOT_BUILT_IN;
+ default:
+ /* Unfortunately, we cannot convert RECURSIVE_API_CALL,
+ * but since the header API is reentrant, this should not happen. */
+ return CURLHE_BAD_ARGUMENT;
+ }
+}
+
bool Curl_mapi_enter(struct Curl_mapi_guard *guard,
CURLM *m,
Curl_mapi_fn fn,
lib/api.h+5 -0
@@ -57,6 +57,8 @@ typedef enum {
CURL_EAPI_FN_easy_cleanup,
CURL_EAPI_FN_easy_duphandle,
CURL_EAPI_FN_easy_getinfo,
+ CURL_EAPI_FN_easy_header,
+ CURL_EAPI_FN_easy_nextheader,
CURL_EAPI_FN_easy_pause,
CURL_EAPI_FN_easy_perform_ev,
CURL_EAPI_FN_easy_perform,
@@ -151,6 +153,9 @@ bool Curl_eapi_enter(struct Curl_eapi_guard *guard,
CURLcode *presult);
void Curl_eapi_leave(struct Curl_eapi_guard *guard);
+/* Convert an EAPI failure to a header API result */
+CURLHcode Curl_eapi_hcode(CURLcode result);
+
/* Curl_eapi_enter() checks for curl being NULL, but windows compiler
* analyzers do not realize this. *sigh* */
#define CURL_EAPI_ENTER(g, curl, fn, r) \
lib/headers.c+126 -97
@@ -59,62 +59,84 @@ CURLHcode curl_easy_header(CURL *curl,
int request,
struct curl_header **hout)
{
- struct Curl_llist_node *e;
- struct Curl_llist_node *e_pick = NULL;
- struct Curl_easy *data = curl;
- size_t match = 0;
- size_t amount = 0;
- struct Curl_header_store *hs = NULL;
- struct Curl_header_store *pick = NULL;
- if(!name || !hout || !data ||
- (origin > (CURLH_HEADER | CURLH_TRAILER | CURLH_CONNECT | CURLH_1XX |
- CURLH_PSEUDO)) || !origin || (request < -1))
- return CURLHE_BAD_ARGUMENT;
- if(!Curl_llist_count(&data->state.httphdrs))
- return CURLHE_NOHEADERS; /* no headers available */
- if(request > data->state.requests)
- return CURLHE_NOREQUEST;
- if(request == -1)
- request = data->state.requests;
-
- /* we need a first round to count amount of this header */
- for(e = Curl_llist_head(&data->state.httphdrs); e; e = Curl_node_next(e)) {
- hs = Curl_node_elem(e);
- if(curl_strequal(hs->name, name) &&
- (hs->type & origin) &&
- (hs->request == request)) {
- amount++;
- pick = hs;
- e_pick = e;
+ struct Curl_eapi_guard guard;
+ CURLHcode hresult = CURLHE_OK;
+ CURLcode result;
+
+ if(CURL_EAPI_ENTER(&guard, curl, easy_header, &result)) {
+ struct Curl_easy *data = curl;
+ struct Curl_llist_node *e;
+ struct Curl_llist_node *e_pick = NULL;
+ size_t match = 0;
+ size_t amount = 0;
+ struct Curl_header_store *hs = NULL;
+ struct Curl_header_store *pick = NULL;
+ if(!name || !hout || !data ||
+ (origin > (CURLH_HEADER | CURLH_TRAILER | CURLH_CONNECT | CURLH_1XX |
+ CURLH_PSEUDO)) || !origin || (request < -1)) {
+ hresult = CURLHE_BAD_ARGUMENT;
+ goto out;
}
- }
- if(!amount)
- return CURLHE_MISSING;
- else if(nameindex >= amount)
- return CURLHE_BADINDEX;
-
- if(nameindex == amount - 1)
- /* if the last or only occurrence is what's asked for, then we know it */
- hs = pick;
- else {
+ if(!Curl_llist_count(&data->state.httphdrs)) {
+ hresult = CURLHE_NOHEADERS; /* no headers available */
+ goto out;
+ }
+ if(request > data->state.requests) {
+ hresult = CURLHE_NOREQUEST;
+ goto out;
+ }
+ if(request == -1)
+ request = data->state.requests;
+
+ /* we need a first round to count amount of this header */
for(e = Curl_llist_head(&data->state.httphdrs); e; e = Curl_node_next(e)) {
hs = Curl_node_elem(e);
if(curl_strequal(hs->name, name) &&
(hs->type & origin) &&
- (hs->request == request) &&
- (match++ == nameindex)) {
+ (hs->request == request)) {
+ amount++;
+ pick = hs;
e_pick = e;
- break;
}
}
- if(!e) /* this should not happen */
- return CURLHE_MISSING;
+ if(!amount)
+ hresult = CURLHE_MISSING;
+ else if(nameindex >= amount)
+ hresult = CURLHE_BADINDEX;
+ if(hresult)
+ goto out;
+
+ if(nameindex == amount - 1)
+ /* if the last or only occurrence is what's asked for, then we know it */
+ hs = pick;
+ else {
+ for(e = Curl_llist_head(&data->state.httphdrs); e;
+ e = Curl_node_next(e)) {
+ hs = Curl_node_elem(e);
+ if(curl_strequal(hs->name, name) &&
+ (hs->type & origin) &&
+ (hs->request == request) &&
+ (match++ == nameindex)) {
+ e_pick = e;
+ break;
+ }
+ }
+ if(!e) { /* this should not happen */
+ hresult = CURLHE_MISSING;
+ goto out;
+ }
+ }
+ /* this is the name we want */
+ copy_header_external(hs, nameindex, amount, e_pick,
+ &data->state.headerout[0]);
+ *hout = &data->state.headerout[0];
+ hresult = CURLHE_OK;
}
- /* this is the name we want */
- copy_header_external(hs, nameindex, amount, e_pick,
- &data->state.headerout[0]);
- *hout = &data->state.headerout[0];
- return CURLHE_OK;
+out:
+ CURL_EAPI_LEAVE(&guard);
+ if(result)
+ hresult = Curl_eapi_hcode(result);
+ return hresult;
}
/* public API */
@@ -123,59 +145,68 @@ struct curl_header *curl_easy_nextheader(CURL *curl,
int request,
struct curl_header *prev)
{
- struct Curl_easy *data = curl;
- struct Curl_llist_node *pick;
- struct Curl_llist_node *e;
- struct Curl_header_store *hs;
- size_t amount = 0;
- size_t index = 0;
+ struct Curl_eapi_guard guard;
+ struct curl_header *hd = NULL;
+ CURLcode result;
- if(request > data->state.requests)
- return NULL;
- if(request == -1)
- request = data->state.requests;
+ if(CURL_EAPI_ENTER(&guard, curl, easy_nextheader, &result)) {
+ struct Curl_easy *data = curl;
+ struct Curl_llist_node *pick;
+ struct Curl_llist_node *e;
+ struct Curl_header_store *hs;
+ size_t amount = 0;
+ size_t index = 0;
+
+ if(request > data->state.requests)
+ goto out;
+ if(request == -1)
+ request = data->state.requests;
+
+ if(prev) {
+ pick = prev->anchor;
+ if(!pick)
+ /* something is wrong */
+ goto out;
+ pick = Curl_node_next(pick);
+ }
+ else
+ pick = Curl_llist_head(&data->state.httphdrs);
+
+ if(pick) {
+ /* make sure it is the next header of the desired type */
+ do {
+ hs = Curl_node_elem(pick);
+ if((hs->type & origin) && (hs->request == request))
+ break;
+ pick = Curl_node_next(pick);
+ } while(pick);
+ }
- if(prev) {
- pick = prev->anchor;
if(!pick)
- /* something is wrong */
- return NULL;
- pick = Curl_node_next(pick);
- }
- else
- pick = Curl_llist_head(&data->state.httphdrs);
-
- if(pick) {
- /* make sure it is the next header of the desired type */
- do {
- hs = Curl_node_elem(pick);
- if((hs->type & origin) && (hs->request == request))
- break;
- pick = Curl_node_next(pick);
- } while(pick);
- }
+ /* no more headers available */
+ goto out;
- if(!pick)
- /* no more headers available */
- return NULL;
-
- hs = Curl_node_elem(pick);
-
- /* count number of occurrences of this name within the mask and figure out
- the index for the currently selected entry */
- for(e = Curl_llist_head(&data->state.httphdrs); e; e = Curl_node_next(e)) {
- struct Curl_header_store *check = Curl_node_elem(e);
- if(curl_strequal(hs->name, check->name) &&
- (check->request == request) &&
- (check->type & origin))
- amount++;
- if(e == pick)
- index = amount - 1;
- }
+ hs = Curl_node_elem(pick);
+
+ /* count number of occurrences of this name within the mask and figure out
+ the index for the currently selected entry */
+ for(e = Curl_llist_head(&data->state.httphdrs); e; e = Curl_node_next(e)) {
+ struct Curl_header_store *check = Curl_node_elem(e);
+ if(curl_strequal(hs->name, check->name) &&
+ (check->request == request) &&
+ (check->type & origin))
+ amount++;
+ if(e == pick)
+ index = amount - 1;
+ }
- copy_header_external(hs, index, amount, pick,
- &data->state.headerout[1]);
- return &data->state.headerout[1];
+ copy_header_external(hs, index, amount, pick,
+ &data->state.headerout[1]);
+ hd = &data->state.headerout[1];
+ }
+out:
+ CURL_EAPI_LEAVE(&guard);
+ return hd;
}
static CURLcode namevalue(char *header, size_t hlen, unsigned int type,
@@ -271,7 +302,6 @@ CURLcode Curl_headers_push(struct Curl_easy *data, const char *header,
/* insert this node into the list of headers */
Curl_llist_append(&data->state.httphdrs, hs, &hs->node);
- data->state.prevhead = hs;
}
else {
failf(data, "Invalid response header");
@@ -286,7 +316,6 @@ CURLcode Curl_headers_push(struct Curl_easy *data, const char *header,
static void headers_reset(struct Curl_easy *data)
{
Curl_llist_init(&data->state.httphdrs, NULL);
- data->state.prevhead = NULL;
}
struct hds_cw_collect_ctx {
lib/urldata.h+0 -1
@@ -630,7 +630,6 @@ struct UrlState {
headers */
struct Curl_llist httphdrs; /* received headers */
struct curl_header headerout[2]; /* for external purposes */
- struct Curl_header_store *prevhead; /* the latest added header */
#endif
#ifndef CURL_DISABLE_COOKIES
struct curl_slist *cookielist; /* list of cookie files set by
tests/libtest/lib1940.c+41 -0
@@ -68,6 +68,45 @@ static void t1940_showem(CURL *curl, int header_request, unsigned int type)
}
}
+static CURLHcode t1940_negative(CURL *curl, int req_index)
+{
+ struct curl_header *hd1, *hd2;
+ CURLHcode result;
+
+ result = curl_easy_header(NULL, "x", 0, CURLH_HEADER, -1, &hd1);
+ if(result != CURLHE_BAD_ARGUMENT)
+ return result;
+
+ result = curl_easy_header(curl, NULL, 0, CURLH_HEADER, -1, &hd1);
+ if(result != CURLHE_BAD_ARGUMENT)
+ return result;
+
+ result = curl_easy_header(curl, "x", 0, CURLH_HEADER, -1, NULL);
+ if(result != CURLHE_BAD_ARGUMENT)
+ return result;
+
+ result = curl_easy_header(curl, "x", 0, 0, -1, &hd1);
+ if(result != CURLHE_BAD_ARGUMENT)
+ return result;
+
+ result = curl_easy_header(curl, "date", 0, CURLH_HEADER, req_index, &hd1);
+ if(result != CURLHE_OK)
+ return result;
+ if(!hd1)
+ return CURLHE_NOHEADERS;
+
+ /* Should give the first header */
+ hd2 = curl_easy_nextheader(curl, CURLH_HEADER, -1, NULL);
+ if(!hd2)
+ return CURLHE_BADINDEX;
+
+ hd2 = curl_easy_nextheader(NULL, CURLH_HEADER, -1, hd1);
+ if(hd2) /* should not work */
+ return CURLHE_BADINDEX;
+
+ return CURLHE_OK;
+}
+
static CURLcode test_lib1940(const char *URL)
{
CURL *curl = NULL;
@@ -106,6 +145,8 @@ static CURLcode test_lib1940(const char *URL)
t1940_showem(curl, header_request, CURLH_1XX);
t1940_showem(curl, header_request, CURLH_TRAILER);
+ result = (CURLcode)t1940_negative(curl, header_request);
+
test_cleanup:
curl_easy_cleanup(curl);
curl_global_cleanup();