lib: new easy option string storage

Change the storage of easy handle option strings from an array sized for
all possible options to a hash set to reduce memory footprint.

Give the hash set initially room for 4 strings, with first allocation
happening when it goes beyond that. Measurements without test suite
and a forced fail on growing the set gives:

Size Result
2    1261 tests out of 1951 reported OK: 64%
4    1792 tests out of 1951 reported OK: 91%
8    1944 tests out of 1951 reported OK: 99%
16   1949 tests out of 1951 reported OK: 99%
32   single fail of 3211, unit test for u8_strset

Add u8_strset that keeps the tuples (uint8_t id, char *str)
and allows set/unset by `id`. Add that as data->set.strings.

Define MACROS
* CURL_EASY_STR(data, id) for access
* CURL_EASY_STR_SET(data, id, s) for setting, making a copy
* CURL_EASY_STR_SETN(data, id, s) for setting, no copy
* CURL_EASY_STR_CLEAR(data, id) for unsetting
* CURL_EASY_STR_CLEAR0(data, id) for unsetting and zero-ing value

Add `data->set.str_copypostfields` to handle former `STRING_COPYPOSTFIELDS`
string that was not always a string and could carry NUL bytes.

Add unit tests to test3211.

Closes #22628
This commit is contained in:
Stefan Eissing 2026-08-20 16:06:17 +02:00 committed by Daniel Stenberg
parent 961c95fea6
commit c8df3defd9
No known key found for this signature in database
GPG key ID: 5CC908FDB71E12C2
45 changed files with 1028 additions and 488 deletions

View file

@ -292,6 +292,7 @@ LIB_CFILES = \
transfer.c \ transfer.c \
uint-bset.c \ uint-bset.c \
uint-hash.c \ uint-hash.c \
uint-hashset.c \
uint-spbset.c \ uint-spbset.c \
uint-table.c \ uint-table.c \
url.c \ url.c \
@ -425,6 +426,7 @@ LIB_HFILES = \
transfer.h \ transfer.h \
uint-bset.h \ uint-bset.h \
uint-hash.h \ uint-hash.h \
uint-hashset.h \
uint-spbset.h \ uint-spbset.h \
uint-table.h \ uint-table.h \
url.h \ url.h \

View file

@ -81,8 +81,8 @@ static CURLcode cf_haproxy_date_out_set(struct Curl_cfilter *cf,
if(result) if(result)
return result; return result;
if(data->set.str[STRING_HAPROXY_CLIENT_IP]) { client_source_ip = CURL_EASY_STR(data, STRING_HAPROXY_CLIENT_IP);
client_source_ip = data->set.str[STRING_HAPROXY_CLIENT_IP]; if(client_source_ip) {
client_dest_ip = client_source_ip; client_dest_ip = client_source_ip;
is_ipv6 = !Curl_is_ipv4addr(client_source_ip); is_ipv6 = !Curl_is_ipv4addr(client_source_ip);
} }

View file

@ -656,9 +656,9 @@ static CURLcode bindlocal(struct Curl_easy *data, struct connectdata *conn,
"random" */ "random" */
/* how many port numbers to try to bind to, increasing one at a time */ /* how many port numbers to try to bind to, increasing one at a time */
int portnum = data->set.localportrange; int portnum = data->set.localportrange;
const char *dev = data->set.str[STRING_DEVICE]; const char *dev = CURL_EASY_STR(data, STRING_DEVICE);
const char *iface_input = data->set.str[STRING_INTERFACE]; const char *iface_input = CURL_EASY_STR(data, STRING_INTERFACE);
const char *host_input = data->set.str[STRING_BINDHOST]; const char *host_input = CURL_EASY_STR(data, STRING_BINDHOST);
const char *iface = iface_input ? iface_input : dev; const char *iface = iface_input ? iface_input : dev;
const char *host = host_input ? host_input : dev; const char *host = host_input ? host_input : dev;
int sockerr; int sockerr;

View file

@ -1666,13 +1666,13 @@ void Curl_flush_cookies(struct Curl_easy *data, bool cleanup)
might be cookie files that were not loaded so saving the file is the might be cookie files that were not loaded so saving the file is the
wrong thing. */ wrong thing. */
if(data->cookies) { if(data->cookies) {
if(data->set.str[STRING_COOKIEJAR] && data->cookies->running) { const char *cookiejar = CURL_EASY_STR(data, STRING_COOKIEJAR);
if(cookiejar && data->cookies->running) {
/* if we have a destination file for all the cookies to get dumped to */ /* if we have a destination file for all the cookies to get dumped to */
CURLcode result = cookie_output(data, data->cookies, CURLcode result = cookie_output(data, data->cookies, cookiejar);
data->set.str[STRING_COOKIEJAR]);
if(result) if(result)
infof(data, "WARNING: failed to save cookies in %s: %s", infof(data, "WARNING: failed to save cookies in %s: %s",
data->set.str[STRING_COOKIEJAR], curl_easy_strerror(result)); cookiejar, curl_easy_strerror(result));
} }
if(cleanup && (!data->share || (data->cookies != data->share->cookies))) { if(cleanup && (!data->share || (data->cookies != data->share->cookies))) {

View file

@ -890,7 +890,6 @@ CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ...)
static CURLcode dupset(struct Curl_easy *dst, struct Curl_easy *src) static CURLcode dupset(struct Curl_easy *dst, struct Curl_easy *src)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
enum dupstring i;
enum dupblob j; enum dupblob j;
/* Copy src->set into dst->set first, then deal with the strings /* Copy src->set into dst->set first, then deal with the strings
@ -899,17 +898,17 @@ static CURLcode dupset(struct Curl_easy *dst, struct Curl_easy *src)
#if !defined(CURL_DISABLE_MIME) || !defined(CURL_DISABLE_FORM_API) #if !defined(CURL_DISABLE_MIME) || !defined(CURL_DISABLE_FORM_API)
dst->set.mimepostp = NULL; dst->set.mimepostp = NULL;
#endif #endif
dst->set.str_copypostfields = NULL;
Curl_u8_strset_init(&dst->set.strings);
/* clear all dest string and blob pointers first, in case we error out /* clear all dest string and blob pointers first, in case we error out
mid-function */ mid-function */
memset(dst->set.str, 0, STRING_LAST * sizeof(char *));
memset(dst->set.blobs, 0, BLOB_LAST * sizeof(struct curl_blob *)); memset(dst->set.blobs, 0, BLOB_LAST * sizeof(struct curl_blob *));
/* duplicate all strings */ /* duplicate all strings */
for(i = (enum dupstring)0; i < STRING_LASTZEROTERMINATED; i++) { result = Curl_u8_strset_copy(&dst->set.strings, &src->set.strings);
result = Curl_setstropt(&dst->set.str[i], src->set.str[i]); if(result)
if(result) return result;
return result;
}
/* duplicate all blobs */ /* duplicate all blobs */
for(j = (enum dupblob)0; j < BLOB_LAST; j++) { for(j = (enum dupblob)0; j < BLOB_LAST; j++) {
@ -919,18 +918,18 @@ static CURLcode dupset(struct Curl_easy *dst, struct Curl_easy *src)
} }
/* duplicate memory areas pointed to */ /* duplicate memory areas pointed to */
i = STRING_COPYPOSTFIELDS; if(src->set.str_copypostfields) {
if(src->set.str[i]) {
if(src->set.postfieldsize == -1) if(src->set.postfieldsize == -1)
dst->set.str[i] = curlx_strdup(src->set.str[i]); dst->set.str_copypostfields = curlx_strdup(src->set.str_copypostfields);
else else
/* postfieldsize is curl_off_t, curlx_memdup() takes a size_t ... */ /* postfieldsize is curl_off_t, curlx_memdup() takes a size_t ... */
dst->set.str[i] = curlx_memdup(src->set.str[i], dst->set.str_copypostfields =
curlx_sotouz(src->set.postfieldsize)); curlx_memdup(src->set.str_copypostfields,
if(!dst->set.str[i]) curlx_sotouz(src->set.postfieldsize));
if(!dst->set.str_copypostfields)
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
/* point to the new copy */ /* point to the new copy */
dst->set.postfields = dst->set.str[i]; dst->set.postfields = dst->set.str_copypostfields;
} }
#if !defined(CURL_DISABLE_MIME) || !defined(CURL_DISABLE_FORM_API) #if !defined(CURL_DISABLE_MIME) || !defined(CURL_DISABLE_FORM_API)
@ -974,6 +973,7 @@ CURL *curl_easy_duphandle(CURL *curl)
if(CURL_EAPI_ENTER(&guard, curl, easy_duphandle, NULL)) { if(CURL_EAPI_ENTER(&guard, curl, easy_duphandle, NULL)) {
struct Curl_easy *data = curl; struct Curl_easy *data = curl;
const char *str;
outcurl = curlx_calloc(1, sizeof(struct Curl_easy)); outcurl = curlx_calloc(1, sizeof(struct Curl_easy));
if(!outcurl) if(!outcurl)
@ -1047,8 +1047,9 @@ CURL *curl_easy_duphandle(CURL *curl)
/* Reinitialize an SSL engine for the new handle /* Reinitialize an SSL engine for the new handle
* note: the engine name has already been copied by dupset */ * note: the engine name has already been copied by dupset */
if(outcurl->set.str[STRING_SSL_ENGINE]) { str = CURL_EASY_STR(outcurl, STRING_SSL_ENGINE);
if(Curl_ssl_set_engine(outcurl, outcurl->set.str[STRING_SSL_ENGINE])) if(str) {
if(Curl_ssl_set_engine(outcurl, str))
goto fail; goto fail;
} }
@ -1057,8 +1058,9 @@ CURL *curl_easy_duphandle(CURL *curl)
outcurl->asi = Curl_altsvc_init(); outcurl->asi = Curl_altsvc_init();
if(!outcurl->asi) if(!outcurl->asi)
goto fail; goto fail;
if(outcurl->set.str[STRING_ALTSVC]) str = CURL_EASY_STR(outcurl, STRING_ALTSVC);
(void)Curl_altsvc_load(outcurl->asi, outcurl->set.str[STRING_ALTSVC]); if(str)
(void)Curl_altsvc_load(outcurl->asi, str);
} }
#endif #endif
#ifndef CURL_DISABLE_HSTS #ifndef CURL_DISABLE_HSTS
@ -1066,9 +1068,9 @@ CURL *curl_easy_duphandle(CURL *curl)
outcurl->hsts = Curl_hsts_init(); outcurl->hsts = Curl_hsts_init();
if(!outcurl->hsts) if(!outcurl->hsts)
goto fail; goto fail;
if(outcurl->set.str[STRING_HSTS]) str = CURL_EASY_STR(outcurl, STRING_HSTS);
(void)Curl_hsts_loadfile(outcurl, if(str)
outcurl->hsts, outcurl->set.str[STRING_HSTS]); (void)Curl_hsts_loadfile(outcurl, outcurl->hsts, str);
(void)Curl_hsts_loadcb(outcurl, outcurl->hsts); (void)Curl_hsts_loadcb(outcurl, outcurl->hsts);
/* Copy entries learned at runtime. (E.g. Strict-Transport-Security /* Copy entries learned at runtime. (E.g. Strict-Transport-Security

View file

@ -1333,7 +1333,7 @@ static CURLcode ftp_state_use_port(struct Curl_easy *data,
curl_socklen_t sslen; curl_socklen_t sslen;
char hbuf[NI_MAXHOST]; char hbuf[NI_MAXHOST];
const char *host = NULL; const char *host = NULL;
const char *string_ftpport = data->set.str[STRING_FTPPORT]; const char *string_ftpport = CURL_EASY_STR(data, STRING_FTPPORT);
struct Curl_dns_entry *dns_entry = NULL; struct Curl_dns_entry *dns_entry = NULL;
const struct Curl_addrinfo *res = NULL; const struct Curl_addrinfo *res = NULL;
const struct Curl_addrinfo *ai = NULL; const struct Curl_addrinfo *ai = NULL;
@ -1477,8 +1477,8 @@ static CURLcode ftp_state_prepare_transfer(struct Curl_easy *data,
to prepare the server for the upcoming PASV */ to prepare the server for the upcoming PASV */
if(!ftpc->file) if(!ftpc->file)
result = Curl_pp_sendf(data, &ftpc->pp, "PRET %s", result = Curl_pp_sendf(data, &ftpc->pp, "PRET %s",
data->set.str[STRING_CUSTOMREQUEST] ? CURL_EASY_STR(data, STRING_CUSTOMREQUEST) ?
data->set.str[STRING_CUSTOMREQUEST] : CURL_EASY_STR(data, STRING_CUSTOMREQUEST) :
(data->state.list_only ? "NLST" : "LIST")); (data->state.list_only ? "NLST" : "LIST"));
else if(data->state.upload) else if(data->state.upload)
result = Curl_pp_sendf(data, &ftpc->pp, "PRET STOR %s", ftpc->file); result = Curl_pp_sendf(data, &ftpc->pp, "PRET STOR %s", ftpc->file);
@ -1572,8 +1572,8 @@ static CURLcode ftp_state_list(struct Curl_easy *data,
} }
cmd = curl_maprintf("%s%s%.*s", cmd = curl_maprintf("%s%s%.*s",
data->set.str[STRING_CUSTOMREQUEST] ? CURL_EASY_STR(data, STRING_CUSTOMREQUEST) ?
data->set.str[STRING_CUSTOMREQUEST] : CURL_EASY_STR(data, STRING_CUSTOMREQUEST) :
(data->state.list_only ? "NLST" : "LIST"), (data->state.list_only ? "NLST" : "LIST"),
lstArg ? " " : "", lstArg ? " " : "",
lstArglen, lstArg ? lstArg : ""); lstArglen, lstArg ? lstArg : "");
@ -2956,7 +2956,7 @@ static CURLcode ftp_state_user_resp(struct Curl_easy *data,
result = ftp_state_loggedin(data, ftpc); result = ftp_state_loggedin(data, ftpc);
} }
else if(ftpcode == 332) { else if(ftpcode == 332) {
const char *account = data->set.str[STRING_FTP_ACCOUNT]; const char *account = CURL_EASY_STR(data, STRING_FTP_ACCOUNT);
if(!account) { if(!account) {
failf(data, "ACCT requested but none available"); failf(data, "ACCT requested but none available");
result = CURLE_LOGIN_DENIED; result = CURLE_LOGIN_DENIED;
@ -2977,7 +2977,7 @@ static CURLcode ftp_state_user_resp(struct Curl_easy *data,
530 User ... access denied 530 User ... access denied
(the server denies to log the specified user) */ (the server denies to log the specified user) */
const char *alt = data->set.str[STRING_FTP_ALTERNATIVE_TO_USER]; const char *alt = CURL_EASY_STR(data, STRING_FTP_ALTERNATIVE_TO_USER);
if(alt && !ftpc->ftp_trying_alternative) { if(alt && !ftpc->ftp_trying_alternative) {
/* Ok, USER failed. Let's try the supplied command. */ /* Ok, USER failed. Let's try the supplied command. */
if(ftp_has_ctrl(alt)) { if(ftp_has_ctrl(alt)) {
@ -4436,16 +4436,16 @@ static CURLcode ftp_setup_connection(struct Curl_easy *data,
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
/* clone connection related data that is FTP specific */ /* clone connection related data that is FTP specific */
if(data->set.str[STRING_FTP_ACCOUNT]) { if(CURL_EASY_STR(data, STRING_FTP_ACCOUNT)) {
ftpc->account = curlx_strdup(data->set.str[STRING_FTP_ACCOUNT]); ftpc->account = curlx_strdup(CURL_EASY_STR(data, STRING_FTP_ACCOUNT));
if(!ftpc->account) { if(!ftpc->account) {
Curl_conn_meta_remove(conn, CURL_META_FTP_CONN); Curl_conn_meta_remove(conn, CURL_META_FTP_CONN);
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
} }
} }
if(data->set.str[STRING_FTP_ALTERNATIVE_TO_USER]) { if(CURL_EASY_STR(data, STRING_FTP_ALTERNATIVE_TO_USER)) {
ftpc->alternative_to_user = ftpc->alternative_to_user =
curlx_strdup(data->set.str[STRING_FTP_ALTERNATIVE_TO_USER]); curlx_strdup(CURL_EASY_STR(data, STRING_FTP_ALTERNATIVE_TO_USER));
if(!ftpc->alternative_to_user) { if(!ftpc->alternative_to_user) {
curlx_safefree(ftpc->account); curlx_safefree(ftpc->account);
Curl_conn_meta_remove(conn, CURL_META_FTP_CONN); Curl_conn_meta_remove(conn, CURL_META_FTP_CONN);

View file

@ -86,7 +86,7 @@ static CURLcode getinfo_char(struct Curl_easy *data, CURLINFO info,
} }
break; break;
case CURLINFO_EFFECTIVE_METHOD: { case CURLINFO_EFFECTIVE_METHOD: {
const char *m = data->set.str[STRING_CUSTOMREQUEST]; const char *m = CURL_EASY_STR(data, STRING_CUSTOMREQUEST);
if(!m) { if(!m) {
if(data->set.opt_no_body) if(data->set.opt_no_body)
m = "HEAD"; m = "HEAD";
@ -149,7 +149,7 @@ static CURLcode getinfo_char(struct Curl_easy *data, CURLINFO info,
break; break;
case CURLINFO_RTSP_SESSION_ID: case CURLINFO_RTSP_SESSION_ID:
#ifndef CURL_DISABLE_RTSP #ifndef CURL_DISABLE_RTSP
*param_charp = data->set.str[STRING_RTSP_SESSION_ID]; *param_charp = CURL_EASY_STR(data, STRING_RTSP_SESSION_ID);
#else #else
*param_charp = NULL; *param_charp = NULL;
#endif #endif

View file

@ -1153,7 +1153,7 @@ CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy,
static void http_switch_to_get(struct Curl_easy *data, int code) static void http_switch_to_get(struct Curl_easy *data, int code)
{ {
const char *req = data->set.str[STRING_CUSTOMREQUEST]; const char *req = CURL_EASY_STR(data, STRING_CUSTOMREQUEST);
if((req || data->state.httpreq != HTTPREQ_GET) && if((req || data->state.httpreq != HTTPREQ_GET) &&
(data->set.http_follow_mode == CURLFOLLOW_OBEYCODE)) { (data->set.http_follow_mode == CURLFOLLOW_OBEYCODE)) {
@ -1306,8 +1306,8 @@ CURLcode Curl_http_follow(struct Curl_easy *data, const char *newurl,
rewind_result = Curl_req_soft_reset(&data->req, data); rewind_result = Curl_req_soft_reset(&data->req, data);
infof(data, "Issue another request to this URL: '%s'", follow_url); infof(data, "Issue another request to this URL: '%s'", follow_url);
if((data->set.http_follow_mode == CURLFOLLOW_FIRSTONLY) && if((data->set.http_follow_mode == CURLFOLLOW_FIRSTONLY) &&
data->set.str[STRING_CUSTOMREQUEST] && !data->state.http_ignorecustom &&
!data->state.http_ignorecustom) { CURL_EASY_STR(data, STRING_CUSTOMREQUEST)) {
data->state.http_ignorecustom = TRUE; data->state.http_ignorecustom = TRUE;
infof(data, "Drop custom request method for next request"); infof(data, "Drop custom request method for next request");
} }
@ -1991,9 +1991,9 @@ void Curl_http_method(struct Curl_easy *data,
httpreq = HTTPREQ_PUT; httpreq = HTTPREQ_PUT;
/* Now set the 'request' pointer to the proper request string */ /* Now set the 'request' pointer to the proper request string */
if(data->set.str[STRING_CUSTOMREQUEST] && if(!data->state.http_ignorecustom &&
!data->state.http_ignorecustom) { CURL_EASY_STR(data, STRING_CUSTOMREQUEST)) {
request = data->set.str[STRING_CUSTOMREQUEST]; request = CURL_EASY_STR(data, STRING_CUSTOMREQUEST);
} }
else { else {
if(data->req.no_body) if(data->req.no_body)
@ -2124,8 +2124,8 @@ static CURLcode http_target(struct Curl_easy *data,
struct connectdata *conn = data->conn; struct connectdata *conn = data->conn;
#endif #endif
if(data->set.str[STRING_TARGET]) { if(CURL_EASY_STR(data, STRING_TARGET)) {
path = data->set.str[STRING_TARGET]; path = CURL_EASY_STR(data, STRING_TARGET);
query = NULL; query = NULL;
} }
@ -2194,8 +2194,8 @@ static CURLcode http_target(struct Curl_easy *data,
curl_url_cleanup(h); curl_url_cleanup(h);
/* target or URL */ /* target or URL */
result = curlx_dyn_add(r, data->set.str[STRING_TARGET] ? result = curlx_dyn_add(r, CURL_EASY_STR(data, STRING_TARGET) ?
data->set.str[STRING_TARGET] : url); CURL_EASY_STR(data, STRING_TARGET) : url);
curlx_free(url); curlx_free(url);
if(result) if(result)
return result; return result;
@ -2576,12 +2576,12 @@ static CURLcode http_cookies(struct Curl_easy *data,
struct dynbuf *r) struct dynbuf *r)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
char *addcookies = NULL; const char *addcookies = NULL;
bool linecap = FALSE; bool linecap = FALSE;
if(data->set.str[STRING_COOKIE] && if(CURL_EASY_STR(data, STRING_COOKIE) &&
!Curl_checkheaders(data, STRCONST("Cookie")) && !Curl_checkheaders(data, STRCONST("Cookie")) &&
Curl_auth_allowed_to_host(data)) Curl_auth_allowed_to_host(data))
addcookies = data->set.str[STRING_COOKIE]; addcookies = CURL_EASY_STR(data, STRING_COOKIE);
if(data->cookies || addcookies) { if(data->cookies || addcookies) {
struct Curl_llist list; struct Curl_llist list;
@ -2957,14 +2957,12 @@ static CURLcode http_add_hd(struct Curl_easy *data,
result = curlx_dyn_add(req, data->state.rangeline); result = curlx_dyn_add(req, data->state.rangeline);
break; break;
case H1_HD_USER_AGENT: case H1_HD_USER_AGENT: {
if(!Curl_checkheaders(data, STRCONST("User-Agent"))) { const char *ua = CURL_EASY_STR(data, STRING_USERAGENT);
if(data->set.str[STRING_USERAGENT] && if(ua && *ua && !Curl_checkheaders(data, STRCONST("User-Agent")))
*data->set.str[STRING_USERAGENT]) result = curlx_dyn_addf(req, "User-Agent: %s\r\n", ua);
result = curlx_dyn_addf(req, "User-Agent: %s\r\n",
data->set.str[STRING_USERAGENT]);
}
break; break;
}
case H1_HD_ACCEPT: case H1_HD_ACCEPT:
if(!Curl_checkheaders(data, STRCONST("Accept"))) if(!Curl_checkheaders(data, STRCONST("Accept")))
@ -2981,12 +2979,12 @@ static CURLcode http_add_hd(struct Curl_easy *data,
#endif #endif
break; break;
case H1_HD_ACCEPT_ENCODING: case H1_HD_ACCEPT_ENCODING: {
if(!Curl_checkheaders(data, STRCONST("Accept-Encoding")) && const char *enc = CURL_EASY_STR(data, STRING_ENCODING);
data->set.str[STRING_ENCODING]) if(enc && !Curl_checkheaders(data, STRCONST("Accept-Encoding")))
result = curlx_dyn_addf(req, "Accept-Encoding: %s\r\n", result = curlx_dyn_addf(req, "Accept-Encoding: %s\r\n", enc);
data->set.str[STRING_ENCODING]);
break; break;
}
case H1_HD_REFERER: case H1_HD_REFERER:
if(Curl_bufref_ptr(&data->state.referer) && if(Curl_bufref_ptr(&data->state.referer) &&
@ -3317,7 +3315,7 @@ static CURLcode http_header_c(struct Curl_easy *data,
} }
} while(1); } while(1);
} }
v = (!k->http_bodyless && data->set.str[STRING_ENCODING]) ? v = (!k->http_bodyless && CURL_EASY_STR(data, STRING_ENCODING)) ?
HD_VAL(hd, hdlen, "Content-Encoding:") : NULL; HD_VAL(hd, hdlen, "Content-Encoding:") : NULL;
if(v) { if(v) {
/* /*

View file

@ -2088,10 +2088,11 @@ static CURLcode h2_submit(struct h2_stream_ctx **pstream,
if(result) if(result)
goto out; goto out;
result = Curl_h1_req_parse_read(&stream->h1, buf, len, NULL, result = Curl_h1_req_parse_read(
!data->state.http_ignorecustom ? &stream->h1, buf, len, NULL,
data->set.str[STRING_CUSTOMREQUEST] : NULL, !data->state.http_ignorecustom ?
0, &nwritten); CURL_EASY_STR(data, STRING_CUSTOMREQUEST) : NULL,
0, &nwritten);
if(result) if(result)
goto out; goto out;
*pnwritten = nwritten; *pnwritten = nwritten;

View file

@ -816,7 +816,7 @@ static CURLcode parse_sigv4_params(struct Curl_easy *data,
struct Curl_str *region, struct Curl_str *region,
struct Curl_str *service) struct Curl_str *service)
{ {
const char *line = data->set.str[STRING_AWS_SIGV4]; const char *line = CURL_EASY_STR(data, STRING_AWS_SIGV4);
if(!line || !*line) if(!line || !*line)
line = "aws:amz"; line = "aws:amz";

View file

@ -376,7 +376,7 @@ static CURLcode parse_components(struct Curl_easy *data,
size_t *ncomp_out, size_t *ncomp_out,
char **hdrs_copy_out) char **hdrs_copy_out)
{ {
const char *hdrs = data->set.str[STRING_HTTPSIG_HEADERS]; const char *hdrs = CURL_EASY_STR(data, STRING_HTTPSIG_HEADERS);
size_t ncomp = 0; size_t ncomp = 0;
*hdrs_copy_out = NULL; *hdrs_copy_out = NULL;
@ -534,8 +534,8 @@ CURLcode Curl_output_httpsig(struct Curl_easy *data)
const char *query; const char *query;
Curl_HttpReq httpreq; Curl_HttpReq httpreq;
const char *method = NULL; const char *method = NULL;
const char *hexkey; const char *hexkey = CURL_EASY_STR(data, STRING_HTTPSIG_KEY);
const char *keyid; const char *keyid = CURL_EASY_STR(data, STRING_HTTPSIG_KEYID);
enum httpsig_alg alg; enum httpsig_alg alg;
time_t created; time_t created;
struct dynbuf sig_params; struct dynbuf sig_params;
@ -560,9 +560,6 @@ CURLcode Curl_output_httpsig(struct Curl_easy *data)
return CURLE_BAD_FUNCTION_ARGUMENT; return CURLE_BAD_FUNCTION_ARGUMENT;
} }
hexkey = data->set.str[STRING_HTTPSIG_KEY];
keyid = data->set.str[STRING_HTTPSIG_KEYID];
if(!hexkey || !*hexkey) { if(!hexkey || !*hexkey) {
failf(data, "httpsig: CURLOPT_HTTPSIG_KEY is required"); failf(data, "httpsig: CURLOPT_HTTPSIG_KEY is required");
return CURLE_BAD_FUNCTION_ARGUMENT; return CURLE_BAD_FUNCTION_ARGUMENT;

View file

@ -201,6 +201,7 @@ static CURLcode http_proxy_create_CONNECT(struct httpreq **preq,
proxy_http_ver ver) proxy_http_ver ver)
{ {
char *authority = NULL; char *authority = NULL;
const char *ua;
int httpversion = proxy_http_ver_major(ver); int httpversion = proxy_http_ver_major(ver);
CURLcode result; CURLcode result;
struct httpreq *req = NULL; struct httpreq *req = NULL;
@ -242,10 +243,10 @@ static CURLcode http_proxy_create_CONNECT(struct httpreq **preq,
goto out; goto out;
} }
ua = CURL_EASY_STR(data, STRING_USERAGENT);
if(!Curl_checkProxyheaders(data, cf->conn, STRCONST("User-Agent")) && if(!Curl_checkProxyheaders(data, cf->conn, STRCONST("User-Agent")) &&
data->set.str[STRING_USERAGENT] && *data->set.str[STRING_USERAGENT]) { ua && *ua) {
result = Curl_dynhds_cadd(&req->headers, "User-Agent", result = Curl_dynhds_cadd(&req->headers, "User-Agent", ua);
data->set.str[STRING_USERAGENT]);
if(result) if(result)
goto out; goto out;
} }
@ -276,7 +277,7 @@ static CURLcode http_proxy_create_CONNECTUDP(struct httpreq **preq,
struct Curl_peer *dest, struct Curl_peer *dest,
proxy_http_ver ver) proxy_http_ver ver)
{ {
const char *proxy_scheme = "http"; const char *proxy_scheme = "http", *ua;
const char *proxy_host = cf->conn->http_proxy.peer->hostname; const char *proxy_host = cf->conn->http_proxy.peer->hostname;
int httpversion = proxy_http_ver_major(ver); int httpversion = proxy_http_ver_major(ver);
char *authority = NULL; char *authority = NULL;
@ -381,11 +382,11 @@ static CURLcode http_proxy_create_CONNECTUDP(struct httpreq **preq,
goto out; goto out;
} }
ua = CURL_EASY_STR(data, STRING_USERAGENT);
if(ver == PROXY_HTTP_V1 && if(ver == PROXY_HTTP_V1 &&
!Curl_checkProxyheaders(data, cf->conn, STRCONST("User-Agent")) && !Curl_checkProxyheaders(data, cf->conn, STRCONST("User-Agent")) &&
data->set.str[STRING_USERAGENT] && *data->set.str[STRING_USERAGENT]) { ua && *ua) {
result = Curl_dynhds_cadd(&req->headers, "User-Agent", result = Curl_dynhds_cadd(&req->headers, "User-Agent", ua);
data->set.str[STRING_USERAGENT]);
if(result) if(result)
goto out; goto out;
} }

View file

@ -1923,7 +1923,7 @@ static CURLcode imap_parse_custom_request(struct Curl_easy *data,
struct IMAP *imap) struct IMAP *imap)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
const char *custom = data->set.str[STRING_CUSTOMREQUEST]; const char *custom = CURL_EASY_STR(data, STRING_CUSTOMREQUEST);
if(custom) { if(custom) {
/* URL decode the custom request */ /* URL decode the custom request */

View file

@ -250,7 +250,7 @@ static CURLcode pop3_parse_custom_request(struct Curl_easy *data)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct POP3 *pop3 = Curl_meta_get(data, CURL_META_POP3_EASY); struct POP3 *pop3 = Curl_meta_get(data, CURL_META_POP3_EASY);
const char *custom = data->set.str[STRING_CUSTOMREQUEST]; const char *custom = CURL_EASY_STR(data, STRING_CUSTOMREQUEST);
if(!pop3) if(!pop3)
return CURLE_FAILED_INIT; return CURLE_FAILED_INIT;

View file

@ -451,21 +451,21 @@ static CURLcode parse_proxy(struct Curl_easy *data,
if(proxyuser || proxypasswd) { if(proxyuser || proxypasswd) {
result = Curl_creds_create(proxyuser, proxypasswd, NULL, NULL, result = Curl_creds_create(proxyuser, proxypasswd, NULL, NULL,
data->set.str[STRING_PROXY_SERVICE_NAME], CURL_EASY_STR(data, STRING_PROXY_SERVICE_NAME),
CREDS_URL, &proxyinfo->creds); CREDS_URL, &proxyinfo->creds);
if(result) if(result)
goto error; goto error;
} }
else if(!for_pre_proxy && else if(!for_pre_proxy &&
(data->set.str[STRING_PROXYUSERNAME] || (CURL_EASY_STR(data, STRING_PROXYUSERNAME) ||
data->set.str[STRING_PROXYPASSWORD] || CURL_EASY_STR(data, STRING_PROXYPASSWORD) ||
data->set.str[STRING_PROXY_SERVICE_NAME])) { CURL_EASY_STR(data, STRING_PROXY_SERVICE_NAME))) {
/* No user/passwd in URL, if this is not a pre-proxy, the /* No user/passwd in URL, if this is not a pre-proxy, the
* CURLOPT_PROXY* settings apply. */ * CURLOPT_PROXY* settings apply. */
result = Curl_creds_create(data->set.str[STRING_PROXYUSERNAME], result = Curl_creds_create(CURL_EASY_STR(data, STRING_PROXYUSERNAME),
data->set.str[STRING_PROXYPASSWORD], CURL_EASY_STR(data, STRING_PROXYPASSWORD),
NULL, NULL, NULL, NULL,
data->set.str[STRING_PROXY_SERVICE_NAME], CURL_EASY_STR(data, STRING_PROXY_SERVICE_NAME),
CREDS_OPTION, &proxyinfo->creds); CREDS_OPTION, &proxyinfo->creds);
} }
else else
@ -498,7 +498,7 @@ static bool proxy_do_not_proxy(struct Curl_easy *data)
if(data->state.origin->scheme->flags & PROTOPT_NONETWORK) if(data->state.origin->scheme->flags & PROTOPT_NONETWORK)
return TRUE; return TRUE;
no_proxy = data->set.str[STRING_NOPROXY]; no_proxy = CURL_EASY_STR(data, STRING_NOPROXY);
if(!no_proxy) { if(!no_proxy) {
const char *p = "no_proxy"; const char *p = "no_proxy";
env_no_proxy = curl_getenv(p); env_no_proxy = curl_getenv(p);
@ -521,6 +521,7 @@ CURLcode Curl_proxy_init_conn(struct Curl_easy *data,
{ {
char *proxy = NULL; char *proxy = NULL;
char *pre_proxy = NULL; char *pre_proxy = NULL;
const char *str = NULL;
bool do_env_detect = TRUE; bool do_env_detect = TRUE;
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
@ -536,9 +537,10 @@ CURLcode Curl_proxy_init_conn(struct Curl_easy *data,
* Detect what (if any) proxy to use * Detect what (if any) proxy to use
*************************************************************/ *************************************************************/
/* the empty config strings disable proxy use and env detects */ /* the empty config strings disable proxy use and env detects */
if(data->set.str[STRING_PROXY]) { str = CURL_EASY_STR(data, STRING_PROXY);
if(*data->set.str[STRING_PROXY]) { if(str) {
proxy = curlx_strdup(data->set.str[STRING_PROXY]); if(*str) {
proxy = curlx_strdup(str);
/* if global proxy is set, this is it */ /* if global proxy is set, this is it */
if(!proxy) { if(!proxy) {
failf(data, "memory shortage"); failf(data, "memory shortage");
@ -550,9 +552,10 @@ CURLcode Curl_proxy_init_conn(struct Curl_easy *data,
do_env_detect = FALSE; do_env_detect = FALSE;
} }
if(data->set.str[STRING_PRE_PROXY]) { str = CURL_EASY_STR(data, STRING_PRE_PROXY);
if(*data->set.str[STRING_PRE_PROXY]) { if(str) {
pre_proxy = curlx_strdup(data->set.str[STRING_PRE_PROXY]); if(*str) {
pre_proxy = curlx_strdup(str);
/* if global socks proxy is set, this is it */ /* if global socks proxy is set, this is it */
if(!pre_proxy) { if(!pre_proxy) {
failf(data, "memory shortage"); failf(data, "memory shortage");

View file

@ -336,11 +336,11 @@ static CURLcode rtsp_setup_request(struct Curl_easy *data,
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct connectdata *conn = data->conn; struct connectdata *conn = data->conn;
b->session_id = data->set.str[STRING_RTSP_SESSION_ID]; b->session_id = CURL_EASY_STR(data, STRING_RTSP_SESSION_ID);
/* Stream URI. Default to server '*' if not specified */ /* Stream URI. Default to server '*' if not specified */
if(data->set.str[STRING_RTSP_STREAM_URI]) if(CURL_EASY_STR(data, STRING_RTSP_STREAM_URI))
b->stream_uri = data->set.str[STRING_RTSP_STREAM_URI]; b->stream_uri = CURL_EASY_STR(data, STRING_RTSP_STREAM_URI);
else else
b->stream_uri = "*"; b->stream_uri = "*";
@ -348,10 +348,10 @@ static CURLcode rtsp_setup_request(struct Curl_easy *data,
b->transport = Curl_checkheaders(data, STRCONST("Transport")); b->transport = Curl_checkheaders(data, STRCONST("Transport"));
if(rtspreq == RTSPREQ_SETUP && !b->transport) { if(rtspreq == RTSPREQ_SETUP && !b->transport) {
/* New Transport: setting? */ /* New Transport: setting? */
if(data->set.str[STRING_RTSP_TRANSPORT]) { if(CURL_EASY_STR(data, STRING_RTSP_TRANSPORT)) {
result = rtsp_header_alloc("Transport", result = rtsp_header_alloc(
data->set.str[STRING_RTSP_TRANSPORT], "Transport", CURL_EASY_STR(data, STRING_RTSP_TRANSPORT),
&b->transport); &b->transport);
if(result) if(result)
return result; return result;
b->transport_alloc = TRUE; b->transport_alloc = TRUE;
@ -371,9 +371,9 @@ static CURLcode rtsp_setup_request(struct Curl_easy *data,
/* Accept-Encoding header */ /* Accept-Encoding header */
if(!Curl_checkheaders(data, STRCONST("Accept-Encoding")) && if(!Curl_checkheaders(data, STRCONST("Accept-Encoding")) &&
data->set.str[STRING_ENCODING]) { CURL_EASY_STR(data, STRING_ENCODING)) {
result = rtsp_header_alloc("Accept-Encoding", result = rtsp_header_alloc("Accept-Encoding",
data->set.str[STRING_ENCODING], CURL_EASY_STR(data, STRING_ENCODING),
&b->accept_encoding); &b->accept_encoding);
if(result) if(result)
return result; return result;
@ -430,6 +430,7 @@ static CURLcode rtsp_do(struct Curl_easy *data, bool *done)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
const unsigned char rtspreq = data->set.rtspreq; const unsigned char rtspreq = data->set.rtspreq;
const char *str;
struct RTSP *rtsp = Curl_meta_get(data, CURL_META_RTSP_EASY); struct RTSP *rtsp = Curl_meta_get(data, CURL_META_RTSP_EASY);
struct dynbuf req_buffer; struct dynbuf req_buffer;
struct rtsp_blocks block; struct rtsp_blocks block;
@ -506,12 +507,11 @@ static CURLcode rtsp_do(struct Curl_easy *data, bool *done)
block.range ? block.range : "", block.range ? block.range : "",
block.referrer ? block.referrer : ""); block.referrer ? block.referrer : "");
if(!result && str = CURL_EASY_STR(data, STRING_USERAGENT);
!Curl_checkheaders(data, STRCONST("User-Agent")) && if(!result && str && *str &&
data->set.str[STRING_USERAGENT] && *data->set.str[STRING_USERAGENT]) !Curl_checkheaders(data, STRCONST("User-Agent")))
result = curlx_dyn_addf(&req_buffer, result = curlx_dyn_addf(&req_buffer,
"User-Agent: %s\r\n", "User-Agent: %s\r\n", str);
data->set.str[STRING_USERAGENT]);
if(!result) if(!result)
result = curlx_dyn_addf(&req_buffer, result = curlx_dyn_addf(&req_buffer,
@ -976,7 +976,7 @@ CURLcode Curl_rtsp_parseheader(struct Curl_easy *data, const char *header)
data->state.rtsp_CSeq_recv = rtsp->CSeq_recv = (uint32_t)CSeq; data->state.rtsp_CSeq_recv = rtsp->CSeq_recv = (uint32_t)CSeq;
} }
else if(checkprefix("Session:", header)) { else if(checkprefix("Session:", header)) {
const char *start, *end; const char *start, *end, *str;
size_t idlen; size_t idlen;
/* Find the first non-space letter */ /* Find the first non-space letter */
@ -999,24 +999,24 @@ CURLcode Curl_rtsp_parseheader(struct Curl_easy *data, const char *header)
end++; end++;
idlen = end - start; idlen = end - start;
if(data->set.str[STRING_RTSP_SESSION_ID]) { str = CURL_EASY_STR(data, STRING_RTSP_SESSION_ID);
if(str) {
/* If the Session ID is set, then compare */ /* If the Session ID is set, then compare */
if(strlen(data->set.str[STRING_RTSP_SESSION_ID]) != idlen || if(strlen(str) != idlen ||
strncmp(start, data->set.str[STRING_RTSP_SESSION_ID], idlen)) { strncmp(start, str, idlen)) {
failf(data, "Got RTSP Session ID Line [%s], but wanted ID [%s]", failf(data, "Got RTSP Session ID Line [%s], but wanted ID [%s]",
start, data->set.str[STRING_RTSP_SESSION_ID]); start, str);
return CURLE_RTSP_SESSION_ERROR; return CURLE_RTSP_SESSION_ERROR;
} }
} }
else { else {
/* If the Session ID is not set, and we find it in a response, then set /* If the Session ID is not set, and we find it in a response, then set
* it. * it.
*/ * Copy the id substring into a new buffer */
void *mem = curlx_memdup0(start, idlen);
/* Copy the id substring into a new buffer */ if(!mem ||
data->set.str[STRING_RTSP_SESSION_ID] = curlx_memdup0(start, idlen); CURL_EASY_STR_SETN(data, STRING_RTSP_SESSION_ID, mem))
if(!data->set.str[STRING_RTSP_SESSION_ID])
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
} }
} }

View file

@ -78,23 +78,14 @@ static CURLcode setopt_set_timeout_ms(timediff_t *ptimeout_ms, long ms)
return CURLE_OK; return CURLE_OK;
} }
CURLcode Curl_setstropt(char **charp, const char *s) CURLcode Curl_setstropt(struct Curl_easy *data,
enum dupstring id, const char *s)
{ {
/* Release the previous storage at `charp' and replace by a dynamic storage DEBUGASSERT((unsigned)id <= UINT8_MAX);
copy of `s'. Return CURLE_OK or CURLE_OUT_OF_MEMORY. */ if(s && (strlen(s) > CURL_MAX_INPUT_LENGTH))
return CURLE_BAD_FUNCTION_ARGUMENT;
curlx_safefree(*charp); return CURL_EASY_STR_SET(data, (uint8_t)id, s);
if(s) {
if(strlen(s) > CURL_MAX_INPUT_LENGTH)
return CURLE_BAD_FUNCTION_ARGUMENT;
*charp = curlx_strdup(s);
if(!*charp)
return CURLE_OUT_OF_MEMORY;
}
return CURLE_OK;
} }
CURLcode Curl_setblobopt(struct curl_blob **blobp, CURLcode Curl_setblobopt(struct curl_blob **blobp,
@ -160,34 +151,34 @@ static CURLcode setstropt_userpwd(const char *option, char **userp,
return CURLE_OK; return CURLE_OK;
} }
static CURLcode setstropt_interface(char *option, char **devp, static CURLcode setstropt_interface(struct Curl_easy *data, char *option)
char **ifacep, char **hostp)
{ {
char *dev = NULL; char *dev = NULL;
char *iface = NULL; char *iface = NULL;
char *host = NULL; char *host = NULL;
CURLcode result; CURLcode result;
DEBUGASSERT(devp);
DEBUGASSERT(ifacep);
DEBUGASSERT(hostp);
if(option) { if(option) {
/* Parse the interface details if set, otherwise clear them all */ /* Parse the interface details if set, otherwise clear them all */
result = Curl_parse_interface(option, &dev, &iface, &host); result = Curl_parse_interface(option, &dev, &iface, &host);
if(result) if(result)
return result; return result;
} }
curlx_free(*devp);
*devp = dev;
curlx_free(*ifacep); result = CURL_EASY_STR_SETN(data, STRING_DEVICE, dev);
*ifacep = iface; dev = NULL;
if(!result) {
curlx_free(*hostp); result = CURL_EASY_STR_SETN(data, STRING_INTERFACE, iface);
*hostp = host; iface = NULL;
}
return CURLE_OK; if(!result) {
result = CURL_EASY_STR_SETN(data, STRING_BINDHOST, host);
host = NULL;
}
curlx_free(dev);
curlx_free(iface);
curlx_free(host);
return result;
} }
#ifdef USE_SSL #ifdef USE_SSL
@ -952,7 +943,7 @@ static CURLcode setopt_long_ssl(struct Curl_easy *data, CURLoption option,
case CURLOPT_SSL_ENABLE_NPN: case CURLOPT_SSL_ENABLE_NPN:
break; break;
case CURLOPT_SSLENGINE_DEFAULT: case CURLOPT_SSLENGINE_DEFAULT:
curlx_safefree(s->str[STRING_SSL_ENGINE]); CURL_EASY_STR_CLEAR(data, STRING_SSL_ENGINE);
result = Curl_ssl_set_engine_default(data); result = Curl_ssl_set_engine_default(data);
break; break;
default: default:
@ -1211,9 +1202,8 @@ static CURLcode setopt_long_misc(struct Curl_easy *data, CURLoption option,
case CURLOPT_POSTFIELDSIZE: case CURLOPT_POSTFIELDSIZE:
if(arg < -1) if(arg < -1)
return CURLE_BAD_FUNCTION_ARGUMENT; return CURLE_BAD_FUNCTION_ARGUMENT;
if(s->postfieldsize < arg && if(s->postfieldsize < arg && s->str_copypostfields) {
s->postfields == s->str[STRING_COPYPOSTFIELDS]) { curlx_safefree(s->str_copypostfields);
curlx_safefree(s->str[STRING_COPYPOSTFIELDS]);
s->postfields = NULL; s->postfields = NULL;
} }
s->postfieldsize = arg; s->postfieldsize = arg;
@ -1458,7 +1448,7 @@ static CURLcode setopt_pointers(struct Curl_easy *data, CURLoption option,
* pass CURLU to set URL * pass CURLU to set URL
*/ */
Curl_bufref_free(&data->state.url); Curl_bufref_free(&data->state.url);
curlx_safefree(s->str[STRING_SET_URL]); CURL_EASY_STR_CLEAR(data, STRING_SET_URL);
s->uh = va_arg(param, CURLU *); s->uh = va_arg(param, CURLU *);
break; break;
#ifndef CURL_DISABLE_HTTP #ifndef CURL_DISABLE_HTTP
@ -1604,13 +1594,14 @@ static CURLcode cookiefile(struct Curl_easy *data, const char *ptr)
#ifndef CURL_DISABLE_PROXY #ifndef CURL_DISABLE_PROXY
static CURLcode setproxy(struct Curl_easy *data, const char *proxy) static CURLcode setproxy(struct Curl_easy *data, const char *proxy)
{ {
if((data->set.str[STRING_PROXY] && proxy) && const char *str = CURL_EASY_STR(data, STRING_PROXY);
if(str && proxy &&
/* there was one set, is this a new one? */ /* there was one set, is this a new one? */
!strcmp(data->set.str[STRING_PROXY], proxy)) !strcmp(str, proxy))
return CURLE_OK; /* same one as before */ return CURLE_OK; /* same one as before */
changeproxy(data); changeproxy(data);
return Curl_setstropt(&data->set.str[STRING_PROXY], proxy); return Curl_setstropt(data, STRING_PROXY, proxy);
} }
static CURLcode setopt_cptr_proxy(struct Curl_easy *data, CURLoption option, static CURLcode setopt_cptr_proxy(struct Curl_easy *data, CURLoption option,
@ -1629,15 +1620,21 @@ static CURLcode setopt_cptr_proxy(struct Curl_easy *data, CURLoption option,
/* URL decode the components */ /* URL decode the components */
if(!result) { if(!result) {
curlx_safefree(s->str[STRING_PROXYUSERNAME]); char *str = NULL;
curlx_safefree(s->str[STRING_PROXYPASSWORD]); CURL_EASY_STR_CLEAR(data, STRING_PROXYUSERNAME);
if(u) CURL_EASY_STR_CLEAR(data, STRING_PROXYPASSWORD);
result = Curl_urldecode(u, 0, &s->str[STRING_PROXYUSERNAME], NULL, if(u) {
REJECT_ZERO); result = Curl_urldecode(u, 0, &str, NULL, REJECT_ZERO);
if(!result)
result = Curl_u8_strset_setn(&s->strings, STRING_PROXYUSERNAME, str);
}
if(!result && p) {
str = NULL;
result = Curl_urldecode(p, 0, &str, NULL, REJECT_ZERO);
if(!result)
result = Curl_u8_strset_setn(&s->strings, STRING_PROXYPASSWORD, str);
}
} }
if(!result && p)
result = Curl_urldecode(p, 0, &s->str[STRING_PROXYPASSWORD], NULL,
REJECT_ZERO);
curlx_free(u); curlx_free(u);
curlx_strzero(p); curlx_strzero(p);
curlx_free(p); curlx_free(p);
@ -1647,55 +1644,55 @@ static CURLcode setopt_cptr_proxy(struct Curl_easy *data, CURLoption option,
/* /*
* authentication username to use in the operation * authentication username to use in the operation
*/ */
return Curl_setstropt(&s->str[STRING_PROXYUSERNAME], ptr); return Curl_setstropt(data, STRING_PROXYUSERNAME, ptr);
case CURLOPT_PROXYPASSWORD: case CURLOPT_PROXYPASSWORD:
/* /*
* authentication password to use in the operation * authentication password to use in the operation
*/ */
return Curl_setstropt(&s->str[STRING_PROXYPASSWORD], ptr); return Curl_setstropt(data, STRING_PROXYPASSWORD, ptr);
case CURLOPT_NOPROXY: case CURLOPT_NOPROXY:
/* /*
* proxy exception list * proxy exception list
*/ */
return Curl_setstropt(&s->str[STRING_NOPROXY], ptr); return Curl_setstropt(data, STRING_NOPROXY, ptr);
case CURLOPT_PROXY_SSLCERT: case CURLOPT_PROXY_SSLCERT:
/* /*
* String that holds filename of the SSL certificate to use for proxy * String that holds filename of the SSL certificate to use for proxy
*/ */
return Curl_setstropt(&s->str[STRING_CERT_PROXY], ptr); return Curl_setstropt(data, STRING_CERT_PROXY, ptr);
case CURLOPT_PROXY_SSLCERTTYPE: case CURLOPT_PROXY_SSLCERTTYPE:
/* /*
* String that holds file type of the SSL certificate to use for proxy * String that holds file type of the SSL certificate to use for proxy
*/ */
return Curl_setstropt(&s->str[STRING_CERT_TYPE_PROXY], ptr); return Curl_setstropt(data, STRING_CERT_TYPE_PROXY, ptr);
case CURLOPT_PROXY_SSLKEY: case CURLOPT_PROXY_SSLKEY:
/* /*
* String that holds filename of the SSL key to use for proxy * String that holds filename of the SSL key to use for proxy
*/ */
return Curl_setstropt(&s->str[STRING_KEY_PROXY], ptr); return Curl_setstropt(data, STRING_KEY_PROXY, ptr);
case CURLOPT_PROXY_KEYPASSWD: case CURLOPT_PROXY_KEYPASSWD:
/* /*
* String that holds the SSL private key password for proxy. * String that holds the SSL private key password for proxy.
*/ */
return Curl_setstropt(&s->str[STRING_KEY_PASSWD_PROXY], ptr); return Curl_setstropt(data, STRING_KEY_PASSWD_PROXY, ptr);
case CURLOPT_PROXY_SSLKEYTYPE: case CURLOPT_PROXY_SSLKEYTYPE:
/* /*
* String that holds file type of the SSL key to use for proxy * String that holds file type of the SSL key to use for proxy
*/ */
return Curl_setstropt(&s->str[STRING_KEY_TYPE_PROXY], ptr); return Curl_setstropt(data, STRING_KEY_TYPE_PROXY, ptr);
case CURLOPT_PROXY_SSL_CIPHER_LIST: case CURLOPT_PROXY_SSL_CIPHER_LIST:
if(Curl_ssl_supports(data, SSLSUPP_CIPHER_LIST)) { if(Curl_ssl_supports(data, SSLSUPP_CIPHER_LIST)) {
/* set a list of cipher we want to use in the SSL connection for proxy */ /* set a list of cipher we want to use in the SSL connection for proxy */
return Curl_setstropt(&s->str[STRING_SSL_CIPHER_LIST_PROXY], ptr); return Curl_setstropt(data, STRING_SSL_CIPHER_LIST_PROXY, ptr);
} }
else else
return CURLE_NOT_BUILT_IN; return CURLE_NOT_BUILT_IN;
case CURLOPT_PROXY_TLS13_CIPHERS: case CURLOPT_PROXY_TLS13_CIPHERS:
if(Curl_ssl_supports(data, SSLSUPP_TLS13_CIPHERSUITES)) if(Curl_ssl_supports(data, SSLSUPP_TLS13_CIPHERSUITES))
/* set preferred list of TLS 1.3 cipher suites for proxy */ /* set preferred list of TLS 1.3 cipher suites for proxy */
return Curl_setstropt(&s->str[STRING_SSL_CIPHER13_LIST_PROXY], ptr); return Curl_setstropt(data, STRING_SSL_CIPHER13_LIST_PROXY, ptr);
else else
return CURLE_NOT_BUILT_IN; return CURLE_NOT_BUILT_IN;
case CURLOPT_PROXY: case CURLOPT_PROXY:
@ -1717,13 +1714,13 @@ static CURLcode setopt_cptr_proxy(struct Curl_easy *data, CURLoption option,
* If the proxy is set to "" or NULL we explicitly say that we do not want * If the proxy is set to "" or NULL we explicitly say that we do not want
* to use the socks proxy. * to use the socks proxy.
*/ */
return Curl_setstropt(&s->str[STRING_PRE_PROXY], ptr); return Curl_setstropt(data, STRING_PRE_PROXY, ptr);
case CURLOPT_SOCKS5_GSSAPI_SERVICE: case CURLOPT_SOCKS5_GSSAPI_SERVICE:
case CURLOPT_PROXY_SERVICE_NAME: case CURLOPT_PROXY_SERVICE_NAME:
/* /*
* Set proxy authentication service name for Kerberos 5 and SPNEGO * Set proxy authentication service name for Kerberos 5 and SPNEGO
*/ */
return Curl_setstropt(&s->str[STRING_PROXY_SERVICE_NAME], ptr); return Curl_setstropt(data, STRING_PROXY_SERVICE_NAME, ptr);
case CURLOPT_PROXY_PINNEDPUBLICKEY: case CURLOPT_PROXY_PINNEDPUBLICKEY:
/* /*
* Set pinned public key for SSL connection. * Set pinned public key for SSL connection.
@ -1731,7 +1728,7 @@ static CURLcode setopt_cptr_proxy(struct Curl_easy *data, CURLoption option,
*/ */
#ifdef USE_SSL #ifdef USE_SSL
if(Curl_ssl_supports(data, SSLSUPP_PINNEDPUBKEY)) if(Curl_ssl_supports(data, SSLSUPP_PINNEDPUBKEY))
return Curl_setstropt(&s->str[STRING_SSL_PINNEDPUBLICKEY_PROXY], ptr); return Curl_setstropt(data, STRING_SSL_PINNEDPUBLICKEY_PROXY, ptr);
#endif #endif
return CURLE_NOT_BUILT_IN; return CURLE_NOT_BUILT_IN;
@ -1739,18 +1736,19 @@ static CURLcode setopt_cptr_proxy(struct Curl_easy *data, CURLoption option,
/* /*
* Set the client IP to send through HAProxy PROXY protocol * Set the client IP to send through HAProxy PROXY protocol
*/ */
result = Curl_setstropt(&s->str[STRING_HAPROXY_CLIENT_IP], ptr); result = Curl_setstropt(data, STRING_HAPROXY_CLIENT_IP, ptr);
/* enable the HAProxy protocol if an IP is provided */ /* enable the HAProxy protocol if an IP is provided */
s->haproxyprotocol = !!s->str[STRING_HAPROXY_CLIENT_IP]; s->haproxyprotocol = !!CURL_EASY_STR(data, STRING_HAPROXY_CLIENT_IP);
break; break;
case CURLOPT_PROXY_CAINFO: case CURLOPT_PROXY_CAINFO:
/* /*
* Set CA info SSL connection for proxy. Specify filename of the * Set CA info SSL connection for proxy. Specify filename of the
* CA certificate * CA certificate
*/ */
result = Curl_setstropt(&s->str[STRING_SSL_CAFILE_PROXY], ptr); result = Curl_setstropt(data, STRING_SSL_CAFILE_PROXY, ptr);
s->proxy_ssl.custom_cafile = !!s->str[STRING_SSL_CAFILE_PROXY]; s->proxy_ssl.custom_cafile =
!!CURL_EASY_STR(data, STRING_SSL_CAFILE_PROXY);
return result; return result;
case CURLOPT_PROXY_CRLFILE: case CURLOPT_PROXY_CRLFILE:
/* /*
@ -1758,14 +1756,14 @@ static CURLcode setopt_cptr_proxy(struct Curl_easy *data, CURLoption option,
* CRL to check certificates revocation * CRL to check certificates revocation
*/ */
if(Curl_ssl_supports(data, SSLSUPP_CRLFILE)) if(Curl_ssl_supports(data, SSLSUPP_CRLFILE))
return Curl_setstropt(&s->str[STRING_SSL_CRLFILE_PROXY], ptr); return Curl_setstropt(data, STRING_SSL_CRLFILE_PROXY, ptr);
return CURLE_NOT_BUILT_IN; return CURLE_NOT_BUILT_IN;
case CURLOPT_PROXY_ISSUERCERT: case CURLOPT_PROXY_ISSUERCERT:
/* /*
* Set Issuer certificate file to check certificates issuer * Set Issuer certificate file to check certificates issuer
*/ */
if(Curl_ssl_supports(data, SSLSUPP_ISSUERCERT)) if(Curl_ssl_supports(data, SSLSUPP_ISSUERCERT))
return Curl_setstropt(&s->str[STRING_SSL_ISSUERCERT_PROXY], ptr); return Curl_setstropt(data, STRING_SSL_ISSUERCERT_PROXY, ptr);
return CURLE_NOT_BUILT_IN; return CURLE_NOT_BUILT_IN;
case CURLOPT_PROXY_CAPATH: case CURLOPT_PROXY_CAPATH:
/* /*
@ -1775,8 +1773,9 @@ static CURLcode setopt_cptr_proxy(struct Curl_easy *data, CURLoption option,
#ifdef USE_SSL #ifdef USE_SSL
if(Curl_ssl_supports(data, SSLSUPP_CA_PATH)) { if(Curl_ssl_supports(data, SSLSUPP_CA_PATH)) {
/* This does not work on Windows. */ /* This does not work on Windows. */
result = Curl_setstropt(&s->str[STRING_SSL_CAPATH_PROXY], ptr); result = Curl_setstropt(data, STRING_SSL_CAPATH_PROXY, ptr);
s->proxy_ssl.custom_capath = !!s->str[STRING_SSL_CAPATH_PROXY]; s->proxy_ssl.custom_capath =
!!CURL_EASY_STR(data, STRING_SSL_CAPATH_PROXY);
return result; return result;
} }
#endif #endif
@ -1799,8 +1798,16 @@ static CURLcode setopt_copypostfields(const char *ptr, struct UserDefined *s)
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
if(s->postfieldsize < -1) if(s->postfieldsize < -1)
return CURLE_BAD_FUNCTION_ARGUMENT; return CURLE_BAD_FUNCTION_ARGUMENT;
if(!ptr || s->postfieldsize == -1) if(!ptr || s->postfieldsize == -1) {
result = Curl_setstropt(&s->str[STRING_COPYPOSTFIELDS], ptr); if(ptr && (strlen(ptr) > CURL_MAX_INPUT_LENGTH))
return CURLE_BAD_FUNCTION_ARGUMENT;
curlx_safefree(s->str_copypostfields);
if(ptr) {
s->str_copypostfields = curlx_strdup(ptr);
if(!s->str_copypostfields)
return CURLE_OUT_OF_MEMORY;
}
}
else { else {
size_t pflen = curlx_sotouz_range(s->postfieldsize, 0, SIZE_MAX); size_t pflen = curlx_sotouz_range(s->postfieldsize, 0, SIZE_MAX);
if(pflen == SIZE_MAX) if(pflen == SIZE_MAX)
@ -1813,13 +1820,13 @@ static CURLcode setopt_copypostfields(const char *ptr, struct UserDefined *s)
if(!p) if(!p)
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
else { else {
curlx_free(s->str[STRING_COPYPOSTFIELDS]); curlx_free(s->str_copypostfields);
s->str[STRING_COPYPOSTFIELDS] = p; s->str_copypostfields = p;
} }
} }
} }
s->postfields = s->str[STRING_COPYPOSTFIELDS]; s->postfields = s->str_copypostfields;
s->method = HTTPREQ_POST; s->method = HTTPREQ_POST;
return result; return result;
} }
@ -1847,12 +1854,12 @@ static CURLcode setopt_ech(struct Curl_easy *data, const char *ptr)
else if(plen > 4 && !strncmp(ptr, "ecl:", 4)) { else if(plen > 4 && !strncmp(ptr, "ecl:", 4)) {
if(!s->tls_ech) if(!s->tls_ech)
s->tls_ech = CURLECH_HARD; s->tls_ech = CURLECH_HARD;
result = Curl_setstropt(&s->str[STRING_ECH_CONFIG], ptr + 4); result = Curl_setstropt(data, STRING_ECH_CONFIG, ptr + 4);
} }
else if(plen > 3 && !strncmp(ptr, "pn:", 3)) { else if(plen > 3 && !strncmp(ptr, "pn:", 3)) {
if(!s->tls_ech) if(!s->tls_ech)
s->tls_ech = CURLECH_HARD; s->tls_ech = CURLECH_HARD;
result = Curl_setstropt(&s->str[STRING_ECH_PUBLIC], ptr + 3); result = Curl_setstropt(data, STRING_ECH_PUBLIC, ptr + 3);
} }
else else
result = CURLE_BAD_FUNCTION_ARGUMENT; result = CURLE_BAD_FUNCTION_ARGUMENT;
@ -1870,22 +1877,21 @@ static CURLcode setopt_cptr_ssl(struct Curl_easy *data, CURLoption option,
char *ptr) char *ptr)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct UserDefined *s = &data->set;
switch(option) { switch(option) {
case CURLOPT_KEYPASSWD: case CURLOPT_KEYPASSWD:
/* /*
* String that holds the SSL or SSH private key password. * String that holds the SSL or SSH private key password.
*/ */
result = Curl_setstropt(&s->str[STRING_KEY_PASSWD], ptr); result = Curl_setstropt(data, STRING_KEY_PASSWD, ptr);
break; break;
#ifdef USE_SSL #ifdef USE_SSL
case CURLOPT_CAINFO: case CURLOPT_CAINFO:
/* /*
* Set CA info for SSL connection. Specify filename of the CA certificate * Set CA info for SSL connection. Specify filename of the CA certificate
*/ */
result = Curl_setstropt(&s->str[STRING_SSL_CAFILE], ptr); result = Curl_setstropt(data, STRING_SSL_CAFILE, ptr);
s->ssl.custom_cafile = !!s->str[STRING_SSL_CAFILE]; data->set.ssl.custom_cafile = !!CURL_EASY_STR(data, STRING_SSL_CAFILE);
return result; return result;
case CURLOPT_CAPATH: case CURLOPT_CAPATH:
/* /*
@ -1894,8 +1900,8 @@ static CURLcode setopt_cptr_ssl(struct Curl_easy *data, CURLoption option,
*/ */
if(Curl_ssl_supports(data, SSLSUPP_CA_PATH)) { if(Curl_ssl_supports(data, SSLSUPP_CA_PATH)) {
/* This does not work on Windows. */ /* This does not work on Windows. */
result = Curl_setstropt(&s->str[STRING_SSL_CAPATH], ptr); result = Curl_setstropt(data, STRING_SSL_CAPATH, ptr);
s->ssl.custom_capath = !!s->str[STRING_SSL_CAPATH]; data->set.ssl.custom_capath = !!CURL_EASY_STR(data, STRING_SSL_CAPATH);
return result; return result;
} }
return CURLE_NOT_BUILT_IN; return CURLE_NOT_BUILT_IN;
@ -1905,18 +1911,18 @@ static CURLcode setopt_cptr_ssl(struct Curl_easy *data, CURLoption option,
* to check certificates revocation * to check certificates revocation
*/ */
if(Curl_ssl_supports(data, SSLSUPP_CRLFILE)) if(Curl_ssl_supports(data, SSLSUPP_CRLFILE))
return Curl_setstropt(&s->str[STRING_SSL_CRLFILE], ptr); return Curl_setstropt(data, STRING_SSL_CRLFILE, ptr);
return CURLE_NOT_BUILT_IN; return CURLE_NOT_BUILT_IN;
case CURLOPT_SSL_CIPHER_LIST: case CURLOPT_SSL_CIPHER_LIST:
if(Curl_ssl_supports(data, SSLSUPP_CIPHER_LIST)) if(Curl_ssl_supports(data, SSLSUPP_CIPHER_LIST))
/* set a list of cipher we want to use in the SSL connection */ /* set a list of cipher we want to use in the SSL connection */
return Curl_setstropt(&s->str[STRING_SSL_CIPHER_LIST], ptr); return Curl_setstropt(data, STRING_SSL_CIPHER_LIST, ptr);
else else
return CURLE_NOT_BUILT_IN; return CURLE_NOT_BUILT_IN;
case CURLOPT_TLS13_CIPHERS: case CURLOPT_TLS13_CIPHERS:
if(Curl_ssl_supports(data, SSLSUPP_TLS13_CIPHERSUITES)) if(Curl_ssl_supports(data, SSLSUPP_TLS13_CIPHERSUITES))
/* set preferred list of TLS 1.3 cipher suites */ /* set preferred list of TLS 1.3 cipher suites */
return Curl_setstropt(&s->str[STRING_SSL_CIPHER13_LIST], ptr); return Curl_setstropt(data, STRING_SSL_CIPHER13_LIST, ptr);
else else
return CURLE_NOT_BUILT_IN; return CURLE_NOT_BUILT_IN;
case CURLOPT_RANDOM_FILE: case CURLOPT_RANDOM_FILE:
@ -1928,7 +1934,7 @@ static CURLcode setopt_cptr_ssl(struct Curl_easy *data, CURLoption option,
* Set an SSL_CTX callback parameter pointer * Set an SSL_CTX callback parameter pointer
*/ */
if(Curl_ssl_supports(data, SSLSUPP_SSL_CTX)) { if(Curl_ssl_supports(data, SSLSUPP_SSL_CTX)) {
s->ssl.fsslctxp = ptr; data->set.ssl.fsslctxp = ptr;
break; break;
} }
else else
@ -1937,28 +1943,28 @@ static CURLcode setopt_cptr_ssl(struct Curl_easy *data, CURLoption option,
/* /*
* String that holds filename of the SSL certificate to use * String that holds filename of the SSL certificate to use
*/ */
return Curl_setstropt(&s->str[STRING_CERT], ptr); return Curl_setstropt(data, STRING_CERT, ptr);
case CURLOPT_SSLCERTTYPE: case CURLOPT_SSLCERTTYPE:
/* /*
* String that holds file type of the SSL certificate to use * String that holds file type of the SSL certificate to use
*/ */
return Curl_setstropt(&s->str[STRING_CERT_TYPE], ptr); return Curl_setstropt(data, STRING_CERT_TYPE, ptr);
case CURLOPT_SSLKEY: case CURLOPT_SSLKEY:
/* /*
* String that holds filename of the SSL key to use * String that holds filename of the SSL key to use
*/ */
return Curl_setstropt(&s->str[STRING_KEY], ptr); return Curl_setstropt(data, STRING_KEY, ptr);
case CURLOPT_SSLKEYTYPE: case CURLOPT_SSLKEYTYPE:
/* /*
* String that holds file type of the SSL key to use * String that holds file type of the SSL key to use
*/ */
return Curl_setstropt(&s->str[STRING_KEY_TYPE], ptr); return Curl_setstropt(data, STRING_KEY_TYPE, ptr);
case CURLOPT_SSLENGINE: case CURLOPT_SSLENGINE:
/* /*
* String that holds the SSL crypto engine. * String that holds the SSL crypto engine.
*/ */
if(ptr && ptr[0]) { if(ptr && ptr[0]) {
result = Curl_setstropt(&s->str[STRING_SSL_ENGINE], ptr); result = Curl_setstropt(data, STRING_SSL_ENGINE, ptr);
if(!result) { if(!result) {
result = Curl_ssl_set_engine(data, ptr); result = Curl_ssl_set_engine(data, ptr);
} }
@ -1970,7 +1976,7 @@ static CURLcode setopt_cptr_ssl(struct Curl_easy *data, CURLoption option,
* to check certificates issuer * to check certificates issuer
*/ */
if(Curl_ssl_supports(data, SSLSUPP_ISSUERCERT)) if(Curl_ssl_supports(data, SSLSUPP_ISSUERCERT))
return Curl_setstropt(&s->str[STRING_SSL_ISSUERCERT], ptr); return Curl_setstropt(data, STRING_SSL_ISSUERCERT, ptr);
return CURLE_NOT_BUILT_IN; return CURLE_NOT_BUILT_IN;
case CURLOPT_SSL_EC_CURVES: case CURLOPT_SSL_EC_CURVES:
/* /*
@ -1978,7 +1984,7 @@ static CURLcode setopt_cptr_ssl(struct Curl_easy *data, CURLoption option,
* Specify colon-delimited list of curve algorithm names. * Specify colon-delimited list of curve algorithm names.
*/ */
if(Curl_ssl_supports(data, SSLSUPP_SSL_EC_CURVES)) if(Curl_ssl_supports(data, SSLSUPP_SSL_EC_CURVES))
return Curl_setstropt(&s->str[STRING_SSL_EC_CURVES], ptr); return Curl_setstropt(data, STRING_SSL_EC_CURVES, ptr);
return CURLE_NOT_BUILT_IN; return CURLE_NOT_BUILT_IN;
case CURLOPT_SSL_SIGNATURE_ALGORITHMS: case CURLOPT_SSL_SIGNATURE_ALGORITHMS:
/* /*
@ -1986,7 +1992,7 @@ static CURLcode setopt_cptr_ssl(struct Curl_easy *data, CURLoption option,
* Specify colon-delimited list of signature scheme names. * Specify colon-delimited list of signature scheme names.
*/ */
if(Curl_ssl_supports(data, SSLSUPP_SIGNATURE_ALGORITHMS)) if(Curl_ssl_supports(data, SSLSUPP_SIGNATURE_ALGORITHMS))
return Curl_setstropt(&s->str[STRING_SSL_SIGNATURE_ALGORITHMS], ptr); return Curl_setstropt(data, STRING_SSL_SIGNATURE_ALGORITHMS, ptr);
return CURLE_NOT_BUILT_IN; return CURLE_NOT_BUILT_IN;
case CURLOPT_PINNEDPUBLICKEY: case CURLOPT_PINNEDPUBLICKEY:
/* /*
@ -1994,7 +2000,7 @@ static CURLcode setopt_cptr_ssl(struct Curl_easy *data, CURLoption option,
* Specify filename of the public key in DER format. * Specify filename of the public key in DER format.
*/ */
if(Curl_ssl_supports(data, SSLSUPP_PINNEDPUBKEY)) if(Curl_ssl_supports(data, SSLSUPP_PINNEDPUBKEY))
return Curl_setstropt(&s->str[STRING_SSL_PINNEDPUBLICKEY], ptr); return Curl_setstropt(data, STRING_SSL_PINNEDPUBLICKEY, ptr);
return CURLE_NOT_BUILT_IN; return CURLE_NOT_BUILT_IN;
case CURLOPT_ECH: case CURLOPT_ECH:
return setopt_ech(data, ptr); return setopt_ech(data, ptr);
@ -2023,7 +2029,7 @@ static CURLcode setopt_cptr_http_mqtt(struct Curl_easy *data,
*/ */
s->postfields = ptr; s->postfields = ptr;
/* Release old copied data. */ /* Release old copied data. */
curlx_safefree(s->str[STRING_COPYPOSTFIELDS]); curlx_safefree(s->str_copypostfields);
s->method = HTTPREQ_POST; s->method = HTTPREQ_POST;
break; break;
@ -2043,15 +2049,13 @@ static CURLcode setopt_cptr_http_mqtt(struct Curl_easy *data,
*/ */
if(ptr && !*ptr) { if(ptr && !*ptr) {
ptr = Curl_get_content_encodings(); ptr = Curl_get_content_encodings();
if(ptr) { if(ptr)
curlx_free(s->str[STRING_ENCODING]); result = CURL_EASY_STR_SETN(data, STRING_ENCODING, ptr);
s->str[STRING_ENCODING] = ptr;
}
else else
result = CURLE_OUT_OF_MEMORY; result = CURLE_OUT_OF_MEMORY;
return result; return result;
} }
return Curl_setstropt(&s->str[STRING_ENCODING], ptr); return Curl_setstropt(data, STRING_ENCODING, ptr);
#ifndef CURL_DISABLE_AWS #ifndef CURL_DISABLE_AWS
case CURLOPT_AWS_SIGV4: case CURLOPT_AWS_SIGV4:
@ -2059,23 +2063,23 @@ static CURLcode setopt_cptr_http_mqtt(struct Curl_easy *data,
* String that is merged to some authentication * String that is merged to some authentication
* parameters are used by the algorithm. * parameters are used by the algorithm.
*/ */
result = Curl_setstropt(&s->str[STRING_AWS_SIGV4], ptr); result = Curl_setstropt(data, STRING_AWS_SIGV4, ptr);
/* /*
* Basic has been set by default; it needs to be unset here. * Basic has been set by default; it needs to be unset here.
*/ */
if(s->str[STRING_AWS_SIGV4]) if(CURL_EASY_STR(data, STRING_AWS_SIGV4))
s->httpauth = CURLAUTH_AWS_SIGV4; s->httpauth = CURLAUTH_AWS_SIGV4;
break; break;
#endif #endif
#ifndef CURL_DISABLE_HTTPSIG #ifndef CURL_DISABLE_HTTPSIG
case CURLOPT_HTTPSIG_KEY: case CURLOPT_HTTPSIG_KEY:
result = Curl_setstropt(&s->str[STRING_HTTPSIG_KEY], ptr); result = Curl_setstropt(data, STRING_HTTPSIG_KEY, ptr);
break; break;
case CURLOPT_HTTPSIG_KEYID: case CURLOPT_HTTPSIG_KEYID:
result = Curl_setstropt(&s->str[STRING_HTTPSIG_KEYID], ptr); result = Curl_setstropt(data, STRING_HTTPSIG_KEYID, ptr);
break; break;
case CURLOPT_HTTPSIG_HEADERS: case CURLOPT_HTTPSIG_HEADERS:
result = Curl_setstropt(&s->str[STRING_HTTPSIG_HEADERS], ptr); result = Curl_setstropt(data, STRING_HTTPSIG_HEADERS, ptr);
break; break;
#endif #endif
case CURLOPT_REFERER: case CURLOPT_REFERER:
@ -2083,21 +2087,21 @@ static CURLcode setopt_cptr_http_mqtt(struct Curl_easy *data,
* String to set in the HTTP Referer: field. * String to set in the HTTP Referer: field.
*/ */
Curl_bufref_free(&data->state.referer); Curl_bufref_free(&data->state.referer);
result = Curl_setstropt(&s->str[STRING_SET_REFERER], ptr); result = Curl_setstropt(data, STRING_SET_REFERER, ptr);
break; break;
case CURLOPT_USERAGENT: case CURLOPT_USERAGENT:
/* /*
* String to use in the HTTP User-Agent field * String to use in the HTTP User-Agent field
*/ */
return Curl_setstropt(&s->str[STRING_USERAGENT], ptr); return Curl_setstropt(data, STRING_USERAGENT, ptr);
#ifndef CURL_DISABLE_COOKIES #ifndef CURL_DISABLE_COOKIES
case CURLOPT_COOKIE: case CURLOPT_COOKIE:
/* /*
* Cookie string to send to the remote server in the request. * Cookie string to send to the remote server in the request.
*/ */
return Curl_setstropt(&s->str[STRING_COOKIE], ptr); return Curl_setstropt(data, STRING_COOKIE, ptr);
case CURLOPT_COOKIEFILE: case CURLOPT_COOKIEFILE:
return cookiefile(data, ptr); return cookiefile(data, ptr);
@ -2106,7 +2110,7 @@ static CURLcode setopt_cptr_http_mqtt(struct Curl_easy *data,
/* /*
* Set cookie filename to dump all cookies to when we are done. * Set cookie filename to dump all cookies to when we are done.
*/ */
result = Curl_setstropt(&s->str[STRING_COOKIEJAR], ptr); result = Curl_setstropt(data, STRING_COOKIEJAR, ptr);
if(!result) { if(!result) {
/* /*
* Activate the cookie parser. This may or may not already * Activate the cookie parser. This may or may not already
@ -2143,12 +2147,12 @@ static CURLcode setopt_cptr_ssh(struct Curl_easy *data, CURLoption option,
/* /*
* Use this file instead of the $HOME/.ssh/id_dsa.pub file * Use this file instead of the $HOME/.ssh/id_dsa.pub file
*/ */
return Curl_setstropt(&s->str[STRING_SSH_PUBLIC_KEY], ptr); return Curl_setstropt(data, STRING_SSH_PUBLIC_KEY, ptr);
case CURLOPT_SSH_PRIVATE_KEYFILE: case CURLOPT_SSH_PRIVATE_KEYFILE:
/* /*
* Use this file instead of the $HOME/.ssh/id_dsa file * Use this file instead of the $HOME/.ssh/id_dsa file
*/ */
return Curl_setstropt(&s->str[STRING_SSH_PRIVATE_KEY], ptr); return Curl_setstropt(data, STRING_SSH_PRIVATE_KEY, ptr);
case CURLOPT_SSH_KEYDATA: case CURLOPT_SSH_KEYDATA:
/* /*
* Custom client data to pass to the SSH keyfunc callback * Custom client data to pass to the SSH keyfunc callback
@ -2160,18 +2164,18 @@ static CURLcode setopt_cptr_ssh(struct Curl_easy *data, CURLoption option,
* Option to allow for the MD5 of the host public key to be checked * Option to allow for the MD5 of the host public key to be checked
* for validation purposes. * for validation purposes.
*/ */
return Curl_setstropt(&s->str[STRING_SSH_HOST_PUBLIC_KEY_MD5], ptr); return Curl_setstropt(data, STRING_SSH_HOST_PUBLIC_KEY_MD5, ptr);
case CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256: case CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256:
/* /*
* Option to allow for the SHA256 of the host public key to be checked * Option to allow for the SHA256 of the host public key to be checked
* for validation purposes. * for validation purposes.
*/ */
return Curl_setstropt(&s->str[STRING_SSH_HOST_PUBLIC_KEY_SHA256], ptr); return Curl_setstropt(data, STRING_SSH_HOST_PUBLIC_KEY_SHA256, ptr);
case CURLOPT_SSH_KNOWNHOSTS: case CURLOPT_SSH_KNOWNHOSTS:
/* /*
* Store the filename to read known hosts from. * Store the filename to read known hosts from.
*/ */
return Curl_setstropt(&s->str[STRING_SSH_KNOWNHOSTS], ptr); return Curl_setstropt(data, STRING_SSH_KNOWNHOSTS, ptr);
#ifdef USE_LIBSSH2 #ifdef USE_LIBSSH2
case CURLOPT_SSH_HOSTKEYDATA: case CURLOPT_SSH_HOSTKEYDATA:
/* /*
@ -2198,15 +2202,15 @@ static CURLcode setopt_cptr_ftp(struct Curl_easy *data, CURLoption option,
/* /*
* Use FTP PORT, this also specifies which IP address to use * Use FTP PORT, this also specifies which IP address to use
*/ */
result = Curl_setstropt(&s->str[STRING_FTPPORT], ptr); result = Curl_setstropt(data, STRING_FTPPORT, ptr);
s->ftp_use_port = !!(s->str[STRING_FTPPORT]); s->ftp_use_port = !!CURL_EASY_STR(data, STRING_FTPPORT);
break; break;
case CURLOPT_FTP_ACCOUNT: case CURLOPT_FTP_ACCOUNT:
return Curl_setstropt(&s->str[STRING_FTP_ACCOUNT], ptr); return Curl_setstropt(data, STRING_FTP_ACCOUNT, ptr);
case CURLOPT_FTP_ALTERNATIVE_TO_USER: case CURLOPT_FTP_ALTERNATIVE_TO_USER:
return Curl_setstropt(&s->str[STRING_FTP_ALTERNATIVE_TO_USER], ptr); return Curl_setstropt(data, STRING_FTP_ALTERNATIVE_TO_USER, ptr);
case CURLOPT_KRBLEVEL: case CURLOPT_KRBLEVEL:
return CURLE_NOT_BUILT_IN; /* removed in 8.17.0 */ return CURLE_NOT_BUILT_IN; /* removed in 8.17.0 */
@ -2226,44 +2230,41 @@ static CURLcode setopt_cptr_ftp(struct Curl_easy *data, CURLoption option,
static CURLcode setopt_cptr_net(struct Curl_easy *data, CURLoption option, static CURLcode setopt_cptr_net(struct Curl_easy *data, CURLoption option,
char *ptr) char *ptr)
{ {
struct UserDefined *s = &data->set;
switch(option) { switch(option) {
case CURLOPT_INTERFACE: case CURLOPT_INTERFACE:
/* /*
* Set what interface or address/hostname to bind the socket to when * Set what interface or address/hostname to bind the socket to when
* performing an operation and thus what from-IP your connection will use. * performing an operation and thus what from-IP your connection will use.
*/ */
return setstropt_interface(ptr, return setstropt_interface(data, ptr);
&s->str[STRING_DEVICE],
&s->str[STRING_INTERFACE],
&s->str[STRING_BINDHOST]);
#ifdef USE_RESOLV_ARES #ifdef USE_RESOLV_ARES
case CURLOPT_DNS_SERVERS: case CURLOPT_DNS_SERVERS:
return Curl_setstropt(&s->str[STRING_DNS_SERVERS], ptr); return Curl_setstropt(data, STRING_DNS_SERVERS, ptr);
case CURLOPT_DNS_INTERFACE: case CURLOPT_DNS_INTERFACE:
return Curl_setstropt(&s->str[STRING_DNS_INTERFACE], ptr); return Curl_setstropt(data, STRING_DNS_INTERFACE, ptr);
case CURLOPT_DNS_LOCAL_IP4: case CURLOPT_DNS_LOCAL_IP4:
return Curl_setstropt(&s->str[STRING_DNS_LOCAL_IP4], ptr); return Curl_setstropt(data, STRING_DNS_LOCAL_IP4, ptr);
case CURLOPT_DNS_LOCAL_IP6: case CURLOPT_DNS_LOCAL_IP6:
return Curl_setstropt(&s->str[STRING_DNS_LOCAL_IP6], ptr); return Curl_setstropt(data, STRING_DNS_LOCAL_IP6, ptr);
#endif #endif
#ifdef USE_UNIX_SOCKETS #ifdef USE_UNIX_SOCKETS
case CURLOPT_UNIX_SOCKET_PATH: case CURLOPT_UNIX_SOCKET_PATH:
s->abstract_unix_socket = FALSE; data->set.abstract_unix_socket = FALSE;
return Curl_setstropt(&s->str[STRING_UNIX_SOCKET_PATH], ptr); return Curl_setstropt(data, STRING_UNIX_SOCKET_PATH, ptr);
case CURLOPT_ABSTRACT_UNIX_SOCKET: case CURLOPT_ABSTRACT_UNIX_SOCKET:
s->abstract_unix_socket = TRUE; data->set.abstract_unix_socket = TRUE;
return Curl_setstropt(&s->str[STRING_UNIX_SOCKET_PATH], ptr); return Curl_setstropt(data, STRING_UNIX_SOCKET_PATH, ptr);
#endif #endif
#ifndef CURL_DISABLE_DOH #ifndef CURL_DISABLE_DOH
case CURLOPT_DOH_URL: case CURLOPT_DOH_URL:
{ {
CURLcode result = Curl_setstropt(&s->str[STRING_DOH], ptr); CURLcode result = Curl_setstropt(data, STRING_DOH, ptr);
s->doh = !!(s->str[STRING_DOH]); data->set.doh = !!CURL_EASY_STR(data, STRING_DOH);
return result; return result;
} }
#endif #endif
@ -2280,19 +2281,19 @@ static CURLcode setopt_cptr_misc(struct Curl_easy *data, CURLoption option,
switch(option) { switch(option) {
case CURLOPT_REQUEST_TARGET: case CURLOPT_REQUEST_TARGET:
return Curl_setstropt(&s->str[STRING_TARGET], ptr); return Curl_setstropt(data, STRING_TARGET, ptr);
#ifndef CURL_DISABLE_NETRC #ifndef CURL_DISABLE_NETRC
case CURLOPT_NETRC_FILE: case CURLOPT_NETRC_FILE:
return Curl_setstropt(&s->str[STRING_NETRC_FILE], ptr); return Curl_setstropt(data, STRING_NETRC_FILE, ptr);
#endif #endif
case CURLOPT_CUSTOMREQUEST: case CURLOPT_CUSTOMREQUEST:
return Curl_setstropt(&s->str[STRING_CUSTOMREQUEST], ptr); return Curl_setstropt(data, STRING_CUSTOMREQUEST, ptr);
/* we do not set s->method = HTTPREQ_CUSTOM; here, we continue as if we /* we do not set s->method = HTTPREQ_CUSTOM; here, we continue as if we
were using the already set type and this changes the actual request were using the already set type and this changes the actual request
keyword */ keyword */
case CURLOPT_SERVICE_NAME: case CURLOPT_SERVICE_NAME:
return Curl_setstropt(&s->str[STRING_SERVICE_NAME], ptr); return Curl_setstropt(data, STRING_SERVICE_NAME, ptr);
case CURLOPT_HEADERDATA: case CURLOPT_HEADERDATA:
s->writeheader = ptr; s->writeheader = ptr;
@ -2334,27 +2335,40 @@ static CURLcode setopt_cptr_misc(struct Curl_easy *data, CURLoption option,
s->errorbuffer = ptr; s->errorbuffer = ptr;
break; break;
case CURLOPT_URL: case CURLOPT_URL:
result = Curl_setstropt(&s->str[STRING_SET_URL], ptr); result = Curl_setstropt(data, STRING_SET_URL, ptr);
Curl_bufref_set(&data->state.url, s->str[STRING_SET_URL], 0, NULL); Curl_bufref_set(&data->state.url,
CURL_EASY_STR(data, STRING_SET_URL), 0, NULL);
break; break;
case CURLOPT_USERPWD: case CURLOPT_USERPWD: {
return setstropt_userpwd(ptr, &s->str[STRING_USERNAME], char *u = NULL, *p = NULL;
&s->str[STRING_PASSWORD]); result = setstropt_userpwd(ptr, &u, &p);
if(!result) {
result = CURL_EASY_STR_SETN(data, STRING_USERNAME, u);
u = NULL;
}
if(!result) {
result = CURL_EASY_STR_SETN(data, STRING_PASSWORD, p);
p = NULL;
}
curlx_free(u);
curlx_free(p);
return result;
}
case CURLOPT_USERNAME: case CURLOPT_USERNAME:
return Curl_setstropt(&s->str[STRING_USERNAME], ptr); return Curl_setstropt(data, STRING_USERNAME, ptr);
case CURLOPT_PASSWORD: case CURLOPT_PASSWORD:
return Curl_setstropt(&s->str[STRING_PASSWORD], ptr); return Curl_setstropt(data, STRING_PASSWORD, ptr);
case CURLOPT_LOGIN_OPTIONS: case CURLOPT_LOGIN_OPTIONS:
return Curl_setstropt(&s->str[STRING_OPTIONS], ptr); return Curl_setstropt(data, STRING_OPTIONS, ptr);
case CURLOPT_XOAUTH2_BEARER: case CURLOPT_XOAUTH2_BEARER:
return Curl_setstropt(&s->str[STRING_BEARER], ptr); return Curl_setstropt(data, STRING_BEARER, ptr);
case CURLOPT_RANGE: case CURLOPT_RANGE:
return Curl_setstropt(&s->str[STRING_SET_RANGE], ptr); return Curl_setstropt(data, STRING_SET_RANGE, ptr);
case CURLOPT_PRIVATE: case CURLOPT_PRIVATE:
s->private_data = ptr; s->private_data = ptr;
break; break;
@ -2382,25 +2396,25 @@ static CURLcode setopt_cptr_misc(struct Curl_easy *data, CURLoption option,
break; break;
case CURLOPT_DEFAULT_PROTOCOL: case CURLOPT_DEFAULT_PROTOCOL:
/* Set the protocol to use when the URL does not include any protocol */ /* Set the protocol to use when the URL does not include any protocol */
return Curl_setstropt(&s->str[STRING_DEFAULT_PROTOCOL], ptr); return Curl_setstropt(data, STRING_DEFAULT_PROTOCOL, ptr);
#ifndef CURL_DISABLE_SMTP #ifndef CURL_DISABLE_SMTP
case CURLOPT_MAIL_FROM: case CURLOPT_MAIL_FROM:
/* Set the SMTP mail originator */ /* Set the SMTP mail originator */
return Curl_setstropt(&s->str[STRING_MAIL_FROM], ptr); return Curl_setstropt(data, STRING_MAIL_FROM, ptr);
case CURLOPT_MAIL_AUTH: case CURLOPT_MAIL_AUTH:
/* Set the SMTP auth originator */ /* Set the SMTP auth originator */
return Curl_setstropt(&s->str[STRING_MAIL_AUTH], ptr); return Curl_setstropt(data, STRING_MAIL_AUTH, ptr);
#endif #endif
case CURLOPT_SASL_AUTHZID: case CURLOPT_SASL_AUTHZID:
/* Authorization identity (identity to act as) */ /* Authorization identity (identity to act as) */
return Curl_setstropt(&s->str[STRING_SASL_AUTHZID], ptr); return Curl_setstropt(data, STRING_SASL_AUTHZID, ptr);
#ifndef CURL_DISABLE_RTSP #ifndef CURL_DISABLE_RTSP
case CURLOPT_RTSP_SESSION_ID: case CURLOPT_RTSP_SESSION_ID:
return Curl_setstropt(&s->str[STRING_RTSP_SESSION_ID], ptr); return Curl_setstropt(data, STRING_RTSP_SESSION_ID, ptr);
case CURLOPT_RTSP_STREAM_URI: case CURLOPT_RTSP_STREAM_URI:
return Curl_setstropt(&s->str[STRING_RTSP_STREAM_URI], ptr); return Curl_setstropt(data, STRING_RTSP_STREAM_URI, ptr);
case CURLOPT_RTSP_TRANSPORT: case CURLOPT_RTSP_TRANSPORT:
return Curl_setstropt(&s->str[STRING_RTSP_TRANSPORT], ptr); return Curl_setstropt(data, STRING_RTSP_TRANSPORT, ptr);
case CURLOPT_INTERLEAVEDATA: case CURLOPT_INTERLEAVEDATA:
s->rtp_out = ptr; s->rtp_out = ptr;
break; break;
@ -2427,7 +2441,7 @@ static CURLcode setopt_cptr_misc(struct Curl_easy *data, CURLoption option,
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
} }
if(ptr) { if(ptr) {
result = Curl_setstropt(&s->str[STRING_HSTS], ptr); result = Curl_setstropt(data, STRING_HSTS, ptr);
if(result) if(result)
return result; return result;
/* this needs to build a list of filenames to read from, so that it can /* this needs to build a list of filenames to read from, so that it can
@ -2459,7 +2473,7 @@ static CURLcode setopt_cptr_misc(struct Curl_easy *data, CURLoption option,
if(!data->asi) if(!data->asi)
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
} }
result = Curl_setstropt(&s->str[STRING_ALTSVC], ptr); result = Curl_setstropt(data, STRING_ALTSVC, ptr);
if(result) if(result)
break; break;
if(ptr) if(ptr)
@ -2719,10 +2733,9 @@ static CURLcode setopt_offt(struct Curl_easy *data, CURLoption option,
if(offt < -1) if(offt < -1)
return CURLE_BAD_FUNCTION_ARGUMENT; return CURLE_BAD_FUNCTION_ARGUMENT;
if(s->postfieldsize < offt && if(s->postfieldsize < offt && s->str_copypostfields) {
s->postfields == s->str[STRING_COPYPOSTFIELDS]) {
/* Previous CURLOPT_COPYPOSTFIELDS is no longer valid. */ /* Previous CURLOPT_COPYPOSTFIELDS is no longer valid. */
curlx_safefree(s->str[STRING_COPYPOSTFIELDS]); curlx_safefree(s->str_copypostfields);
s->postfields = NULL; s->postfields = NULL;
} }
s->postfieldsize = offt; s->postfieldsize = offt;

View file

@ -31,7 +31,8 @@ CURLcode Curl_setopt_SSLVERSION(struct Curl_easy *data, CURLoption option,
#define Curl_setopt_SSLVERSION(a, b, c) CURLE_NOT_BUILT_IN #define Curl_setopt_SSLVERSION(a, b, c) CURLE_NOT_BUILT_IN
#endif #endif
CURLcode Curl_setstropt(char **charp, const char *s) WARN_UNUSED_RESULT; CURLcode Curl_setstropt(struct Curl_easy *data,
enum dupstring id, const char *s) WARN_UNUSED_RESULT;
CURLcode Curl_setblobopt(struct curl_blob **blobp, CURLcode Curl_setblobopt(struct curl_blob **blobp,
const struct curl_blob *blob) WARN_UNUSED_RESULT; const struct curl_blob *blob) WARN_UNUSED_RESULT;
CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)

View file

@ -207,7 +207,7 @@ static CURLcode smtp_parse_custom_request(struct Curl_easy *data,
struct SMTP *smtp) struct SMTP *smtp)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
const char *custom = data->set.str[STRING_CUSTOMREQUEST]; const char *custom = CURL_EASY_STR(data, STRING_CUSTOMREQUEST);
/* URL decode the custom request */ /* URL decode the custom request */
if(custom) if(custom)
@ -912,6 +912,7 @@ static CURLcode smtp_perform_mail(struct Curl_easy *data,
char *from = NULL; char *from = NULL;
char *auth = NULL; char *auth = NULL;
char *size = NULL; char *size = NULL;
const char *str;
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
/* We notify the server we are sending UTF-8 data if a) it supports the /* We notify the server we are sending UTF-8 data if a) it supports the
@ -921,15 +922,15 @@ static CURLcode smtp_perform_mail(struct Curl_easy *data,
bool utf8 = FALSE; bool utf8 = FALSE;
/* Calculate the FROM parameter */ /* Calculate the FROM parameter */
if(data->set.str[STRING_MAIL_FROM]) { str = CURL_EASY_STR(data, STRING_MAIL_FROM);
if(str) {
char *address = NULL; char *address = NULL;
struct hostname host = { NULL, NULL, NULL, NULL }; struct hostname host = { NULL, NULL, NULL, NULL };
const char *suffix = ""; const char *suffix = "";
/* Parse the FROM mailbox into the local address and hostname parts, /* Parse the FROM mailbox into the local address and hostname parts,
converting the hostname to an IDN A-label if necessary */ converting the hostname to an IDN A-label if necessary */
result = smtp_parse_address(data, data->set.str[STRING_MAIL_FROM], result = smtp_parse_address(data, str, &address, &host, &suffix);
&address, &host, &suffix);
if(result) if(result)
goto out; goto out;
@ -962,16 +963,16 @@ static CURLcode smtp_perform_mail(struct Curl_easy *data,
} }
/* Calculate the optional AUTH parameter */ /* Calculate the optional AUTH parameter */
if(data->set.str[STRING_MAIL_AUTH] && smtpc->sasl.authused) { str = CURL_EASY_STR(data, STRING_MAIL_AUTH);
if(data->set.str[STRING_MAIL_AUTH][0] != '\0') { if(str && smtpc->sasl.authused) {
if(str[0] != '\0') {
char *address = NULL; char *address = NULL;
struct hostname host = { NULL, NULL, NULL, NULL }; struct hostname host = { NULL, NULL, NULL, NULL };
const char *suffix = ""; const char *suffix = "";
/* Parse the AUTH mailbox into the local address and hostname parts, /* Parse the AUTH mailbox into the local address and hostname parts,
converting the hostname to an IDN A-label if necessary */ converting the hostname to an IDN A-label if necessary */
result = smtp_parse_address(data, data->set.str[STRING_MAIL_AUTH], result = smtp_parse_address(data, str, &address, &host, &suffix);
&address, &host, &suffix);
if(result) if(result)
goto out; goto out;

View file

@ -451,7 +451,7 @@ CURLcode Curl_pretransfer(struct Curl_easy *data)
* By resetting it here, we ensure each new request starts fresh. */ * By resetting it here, we ensure each new request starts fresh. */
data->state.retrycount = 0; data->state.retrycount = 0;
if(!data->set.str[STRING_SET_URL] && !data->set.uh) { if(!CURL_EASY_STR(data, STRING_SET_URL) && !data->set.uh) {
/* we cannot do anything without URL */ /* we cannot do anything without URL */
failf(data, "No URL set"); failf(data, "No URL set");
return CURLE_URL_MALFORMAT; return CURLE_URL_MALFORMAT;
@ -460,19 +460,22 @@ CURLcode Curl_pretransfer(struct Curl_easy *data)
/* CURLOPT_CURLU overrides CURLOPT_URL and the contents of the CURLU handle /* CURLOPT_CURLU overrides CURLOPT_URL and the contents of the CURLU handle
is allowed to be changed by the user between transfers */ is allowed to be changed by the user between transfers */
if(data->set.uh) { if(data->set.uh) {
char *url = NULL;
CURLUcode uc; CURLUcode uc;
curlx_free(data->set.str[STRING_SET_URL]); uc = curl_url_get(data->set.uh, CURLUPART_URL, &url, 0);
uc = curl_url_get(data->set.uh,
CURLUPART_URL, &data->set.str[STRING_SET_URL], 0);
if(uc) { if(uc) {
/* clear the pointer to not point to freed memory anymore */ /* clear the pointer to not point to freed memory anymore */
Curl_bufref_set(&data->state.url, NULL, 0, NULL); Curl_bufref_set(&data->state.url, NULL, 0, NULL);
failf(data, "No URL set"); failf(data, "No URL set");
return CURLE_URL_MALFORMAT; return CURLE_URL_MALFORMAT;
} }
result = CURL_EASY_STR_SETN(data, STRING_SET_URL, url);
if(result)
return result;
} }
Curl_bufref_set(&data->state.url, data->set.str[STRING_SET_URL], 0, NULL); Curl_bufref_set(&data->state.url, CURL_EASY_STR(data, STRING_SET_URL),
0, NULL);
if(data->set.postfields && data->set.set_resume_from) { if(data->set.postfields && data->set.set_resume_from) {
/* we cannot */ /* we cannot */
@ -505,9 +508,9 @@ CURLcode Curl_pretransfer(struct Curl_easy *data)
Curl_data_priority_clear_state(data); Curl_data_priority_clear_state(data);
if(data->set.http_auto_referer) if(data->set.http_auto_referer)
Curl_bufref_free(&data->state.referer); Curl_bufref_free(&data->state.referer);
if(data->set.str[STRING_SET_REFERER]) if(CURL_EASY_STR(data, STRING_SET_REFERER))
Curl_bufref_set(&data->state.referer, data->set.str[STRING_SET_REFERER], Curl_bufref_set(&data->state.referer,
0, NULL); CURL_EASY_STR(data, STRING_SET_REFERER), 0, NULL);
else else
Curl_bufref_free(&data->state.referer); Curl_bufref_free(&data->state.referer);

305
lib/uint-hashset.c Normal file
View file

@ -0,0 +1,305 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#include "curl_setup.h"
#include "uint-hashset.h"
/* random patterns for API verification */
#ifdef DEBUGBUILD
#define CURL_U8_STRSET_MAGIC 0x7117e783
#endif
#define CURL_U8_STRSET_DEBUG 0
#define CURL_SWAP(a, b) (((a) ^= (b)), ((b) ^= (a)), ((a) ^= (b)))
static const uint8_t u8_smask[] = {
0x00U,
0x01U,
0x03U,
0x07U,
0x0FU,
0x1FU,
0x3FU,
0x7FU,
0xFFU,
};
#define CURL_U8_SET_SLOT_IDX(s, i) (uint8_t)((i) & u8_smask[(s)->slotbits])
#define CURL_U8_SLOT_CNT(i) ((uint16_t)u8_smask[(i)] + 1)
#define CURL_U8_SET_SLOT_CNT(s) CURL_U8_SLOT_CNT((s)->slotbits)
/* A hashset for tuples (id, string) using Robin Hood Hashing.
* <https://www.cs.cornell.edu/courses/JavaAndDS/files/hashing_RobinHood.pdf>
* The basic idea here to handle collisions by robbing "rich" entries and
* giving to the "poor":
* - We have an array: (id, string) are ideally placed at index "id % size".
* - If slot at index is already occupied, we have a collision.
* - A simple collision strategy would look at the next index, and the
* next until until finding an empty slot.
* - The drawback is that this may lead to many checks on lookups, as it
* will need to also look at subsequent slots until it finds the match.
* The amount of lookups is the "probe sequence length" (psl) and this
* may vary greatly between entries.
* - Robin Hood Hashing balances the 'psl's of all entries more evenly:
* - psl == 0 means an entry is in exactly the right slot
* - pasl == 1 means it is in the slot right after. psl == 2 is the slot
* after that, etc.
* - when inserting a new entry, track its psl. Finding a slot where
* the existing entry has a lower psl makes a swap. Put the new entry
* and its psl there, take the previous entry and its psl and find
* the next best slot for the previous entry. */
void Curl_u8_strset_init(struct u8_strset *set)
{
#if defined(__GNUC__) && __GNUC__ >= 13
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Warray-bounds"
#endif
memset(set, 0, sizeof(*set));
#if defined(__GNUC__) && __GNUC__ >= 13
#pragma GCC diagnostic pop
#endif
set->data = set->sdata;
set->ids = set->sids;
set->psl = set->spsl;
set->slotbits = CURL_U8_STRSET_START_BITS;
set->count = 0;
#ifdef DEBUGBUILD
set->init = CURL_U8_STRSET_MAGIC;
#endif
}
void Curl_u8_strset_clear(struct u8_strset *set)
{
uint16_t i;
DEBUGASSERT(set->init == CURL_U8_STRSET_MAGIC);
for(i = 0; i < CURL_U8_SET_SLOT_CNT(set); ++i)
curlx_safefree(set->data[i]);
if(set->data != set->sdata)
curlx_safefree(set->data);
Curl_u8_strset_init(set);
}
static void u8_strset_addn(struct u8_strset *set, uint8_t id, char *val)
{
uint8_t i = CURL_U8_SET_SLOT_IDX(set, id);
uint8_t psl = 0;
while(set->data[i]) {
if(psl > set->psl[i]) { /* SWAP */
char *tmpdata;
tmpdata = set->data[i];
set->data[i] = val;
val = tmpdata;
CURL_SWAP(set->psl[i], psl);
CURL_SWAP(set->ids[i], id);
}
i = CURL_U8_SET_SLOT_IDX(set, i + 1);
++psl;
}
set->ids[i] = id;
set->data[i] = val;
set->psl[i] = psl;
++set->count;
}
static bool u8_strset_grow(struct u8_strset *set)
{
uint8_t i, *prev_ids, nslotbits;
uint16_t prev_slots;
char **prev_data;
size_t nslots;
void *d;
if(set->slotbits >= 8)
return FALSE;
nslotbits = (uint8_t)(set->slotbits + 1);
#if CURL_U8_STRSET_DEBUG
curl_mfprintf(stderr, "u8_strset_grow from %d to %d\n",
set->slotbits, nslotbits);
#endif
nslots = CURL_U8_SLOT_CNT(nslotbits);
d = curlx_calloc(1, (nslots * sizeof(char *)) + (2 * nslots));
if(!d)
return FALSE;
prev_data = set->data;
prev_ids = set->ids;
prev_slots = set->slotbits;
#if defined(__GNUC__) && __GNUC__ >= 13
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wanalyzer-allocation-size"
#endif
set->data = (char **)d;
#if defined(__GNUC__) && __GNUC__ >= 13
#pragma GCC diagnostic pop
#endif
set->ids = (uint8_t *)d + (nslots * sizeof(char *));
set->psl = set->ids + nslots;
set->slotbits = nslotbits;
set->count = 0;
/* re-add previous entries */
for(i = 0; i < CURL_U8_SLOT_CNT(prev_slots); ++i) {
if(prev_data[i])
u8_strset_addn(set, prev_ids[i], prev_data[i]);
}
if(prev_data != set->sdata)
curlx_free(prev_data);
return TRUE;
}
static bool u8_strset_get_index(struct u8_strset *set,
uint8_t id, uint8_t *pindex)
{
uint8_t i = CURL_U8_SET_SLOT_IDX(set, id);
uint8_t psl = 0;
while(set->data[i] && (psl <= set->psl[i])) {
if(set->ids[i] == id) {
*pindex = i;
#if CURL_U8_STRSET_DEBUG
curl_mfprintf(stderr, "u8_strset_index %d=%s\n", id, set->data[i]);
#endif
return TRUE;
}
i = CURL_U8_SET_SLOT_IDX(set, i + 1);
++psl;
}
#if CURL_U8_STRSET_DEBUG
curl_mfprintf(stderr, "u8_strset_index %d not found\n", id);
#endif
*pindex = 0;
return FALSE;
}
uint16_t Curl_u8_strset_count(struct u8_strset *set)
{
return set->count;
}
const char *Curl_u8_strset_get(struct u8_strset *set, uint8_t id)
{
uint8_t i;
DEBUGASSERT(set->init == CURL_U8_STRSET_MAGIC);
if(u8_strset_get_index(set, id, &i))
return set->data[i];
return NULL;
}
CURLcode Curl_u8_strset_setn(struct u8_strset *set,
uint8_t id, char *str)
{
uint8_t i;
DEBUGASSERT(set->init == CURL_U8_STRSET_MAGIC);
#if CURL_U8_STRSET_DEBUG
curl_mfprintf(stderr, "u8_strset_setn %d=%s\n", id, str);
#endif
if(!str) {
Curl_u8_strset_unset(set, id);
return CURLE_OK;
}
if(u8_strset_get_index(set, id, &i)) {
/* `id` is in set, replace value */
curlx_free(set->data[i]);
set->data[i] = str;
return CURLE_OK;
}
/* `id` not in set yet, grow if full */
if((set->count >= CURL_U8_SET_SLOT_CNT(set)) && !u8_strset_grow(set)) {
curlx_free(str);
return CURLE_OUT_OF_MEMORY;
}
u8_strset_addn(set, id, str);
return CURLE_OK;
}
CURLcode Curl_u8_strset_set(struct u8_strset *set,
uint8_t id, const char *str)
{
char *val;
DEBUGASSERT(set->init == CURL_U8_STRSET_MAGIC);
if(!str) {
Curl_u8_strset_unset(set, id);
return CURLE_OK;
}
val = curlx_strdup(str);
if(!val)
return CURLE_OUT_OF_MEMORY;
return Curl_u8_strset_setn(set, id, val);
}
static void u8_strset_unset(struct u8_strset *set, uint8_t id, bool zero)
{
uint8_t i, j;
DEBUGASSERT(set->init == CURL_U8_STRSET_MAGIC);
if(u8_strset_get_index(set, id, &i)) {
/* `id` is in set */
if(zero)
curlx_strzero(set->data[i]);
curlx_safefree(set->data[i]);
set->ids[i] = set->psl[i] = 0;
--set->count;
j = CURL_U8_SET_SLOT_IDX(set, i + 1);
/* shift all entries with positive psl "down" */
while(set->data[j] && set->psl[j]) {
set->data[i] = set->data[j];
set->ids[i] = set->ids[j];
set->psl[i] = (uint8_t)(set->psl[j] - 1);
set->data[j] = NULL;
set->ids[j] = set->psl[j] = 0;
i = j;
j = CURL_U8_SET_SLOT_IDX(set, i + 1);
}
}
}
void Curl_u8_strset_unset(struct u8_strset *set, uint8_t id)
{
u8_strset_unset(set, id, FALSE);
}
void Curl_u8_strset_unset0(struct u8_strset *set, uint8_t id)
{
u8_strset_unset(set, id, TRUE);
}
CURLcode Curl_u8_strset_copy(struct u8_strset *dest, struct u8_strset *src)
{
CURLcode result = CURLE_OK;
uint16_t i;
DEBUGASSERT(src->init == CURL_U8_STRSET_MAGIC);
Curl_u8_strset_clear(dest);
for(i = 0; !result && (i < CURL_U8_SET_SLOT_CNT(src)); ++i) {
if(src->data[i])
result = Curl_u8_strset_set(dest, src->ids[i], src->data[i]);
}
return result;
}

80
lib/uint-hashset.h Normal file
View file

@ -0,0 +1,80 @@
#ifndef HEADER_CURL_UINT_HASHSET_H
#define HEADER_CURL_UINT_HASHSET_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#include "curl_setup.h"
/* How large should the initial set be?
* Measuring our test suite with set growth force fail, gives
* BITS RESULT
* 1 1261 tests out of 1951 reported OK: 64%
* 2 1792 tests out of 1951 reported OK: 91%
* 3 1944 tests out of 1951 reported OK: 99%
* 4 1949 tests out of 1951 reported OK: 99%
* 5 single fail of 3211, unit test for u8_strset
* meaning 91% of our tests to not set more than 4 strings and
* 99% do not set more than 8.
*/
#define CURL_U8_STRSET_START_BITS 2
#define CURL_U8_STRSET_START_DIM (1U << CURL_U8_STRSET_START_BITS)
/* A set that can hold up to 256 strings identified by an `id'.
* Setting a string for an existing id replaces the previous one.
* Getting the string for an id not in the set returns NULL.
* Setting an id to NULL unsets the id.
*/
struct u8_strset {
char **data; /* #slots array of null-terminated strings */
uint8_t *ids; /* #slots array of `id` values */
uint8_t *psl; /* #slots array of "probe sequence length" values */
char *sdata[CURL_U8_STRSET_START_DIM];
uint8_t sids[CURL_U8_STRSET_START_DIM];
uint8_t spsl[CURL_U8_STRSET_START_DIM];
uint16_t count;
uint8_t slotbits;
#ifdef DEBUGBUILD
int32_t init;
#endif
};
void Curl_u8_strset_init(struct u8_strset *set);
void Curl_u8_strset_clear(struct u8_strset *set);
uint16_t Curl_u8_strset_count(struct u8_strset *set);
const char *Curl_u8_strset_get(struct u8_strset *set, uint8_t id);
/* Set string for id, makes a copy. */
CURLcode Curl_u8_strset_set(struct u8_strset *set,
uint8_t id, const char *str);
/* Set string for id, takes ownership of `str` even on failure. */
CURLcode Curl_u8_strset_setn(struct u8_strset *set,
uint8_t id, char *str);
void Curl_u8_strset_unset(struct u8_strset *set, uint8_t id);
/* Remove the string if in the set and zero its memory */
void Curl_u8_strset_unset0(struct u8_strset *set, uint8_t id);
CURLcode Curl_u8_strset_copy(struct u8_strset *dest, struct u8_strset *src);
#endif /* HEADER_CURL_UINT_HASHSET_H */

View file

@ -148,21 +148,17 @@ static curl_prot_t get_protocol_family(const struct Curl_scheme *s)
void Curl_freeset(struct Curl_easy *data) void Curl_freeset(struct Curl_easy *data)
{ {
/* Free all dynamic strings stored in the data->set substructure. */ /* Free all dynamic strings stored in the data->set substructure. */
enum dupstring i;
enum dupblob j; enum dupblob j;
for(i = (enum dupstring)0; i < STRING_LAST; i++) { CURL_EASY_STR_CLEAR0(data, STRING_PASSWORD);
if(i == STRING_PASSWORD || CURL_EASY_STR_CLEAR0(data, STRING_KEY_PASSWD);
i == STRING_KEY_PASSWD || CURL_EASY_STR_CLEAR0(data, STRING_BEARER);
#ifndef CURL_DISABLE_PROXY #ifndef CURL_DISABLE_PROXY
i == STRING_PROXYPASSWORD || CURL_EASY_STR_CLEAR0(data, STRING_PROXYPASSWORD);
i == STRING_KEY_PASSWD_PROXY || CURL_EASY_STR_CLEAR0(data, STRING_KEY_PASSWD_PROXY);
#endif #endif
i == STRING_BEARER) { Curl_u8_strset_clear(&data->set.strings);
curlx_strzero(data->set.str[i]); curlx_safefree(data->set.str_copypostfields);
}
curlx_safefree(data->set.str[i]);
}
for(j = (enum dupblob)0; j < BLOB_LAST; j++) { for(j = (enum dupblob)0; j < BLOB_LAST; j++) {
curlx_safefree(data->set.blobs[j]); curlx_safefree(data->set.blobs[j]);
@ -257,11 +253,11 @@ CURLcode Curl_close(struct Curl_easy **datap)
curlx_dyn_free(&data->state.headerb); curlx_dyn_free(&data->state.headerb);
Curl_flush_cookies(data, TRUE); Curl_flush_cookies(data, TRUE);
#ifndef CURL_DISABLE_ALTSVC #ifndef CURL_DISABLE_ALTSVC
Curl_altsvc_save(data, data->asi, data->set.str[STRING_ALTSVC]); Curl_altsvc_save(data, data->asi, CURL_EASY_STR(data, STRING_ALTSVC));
Curl_altsvc_cleanup(&data->asi); Curl_altsvc_cleanup(&data->asi);
#endif #endif
#ifndef CURL_DISABLE_HSTS #ifndef CURL_DISABLE_HSTS
Curl_hsts_save(data, data->hsts, data->set.str[STRING_HSTS]); Curl_hsts_save(data, data->hsts, CURL_EASY_STR(data, STRING_HSTS));
if(!data->share || !data->share->hsts) if(!data->share || !data->share->hsts)
Curl_hsts_cleanup(&data->hsts); Curl_hsts_cleanup(&data->hsts);
curl_slist_free_all(data->state.hstslist); /* clean up list */ curl_slist_free_all(data->state.hstslist); /* clean up list */
@ -321,6 +317,8 @@ void Curl_init_userdefined(struct Curl_easy *data)
set->in_set = stdin; /* default input from stdin */ set->in_set = stdin; /* default input from stdin */
set->err = stderr; /* default stderr to stderr */ set->err = stderr; /* default stderr to stderr */
Curl_u8_strset_init(&data->set.strings);
#if defined(__clang__) && __clang_major__ >= 16 #if defined(__clang__) && __clang_major__ >= 16
#pragma clang diagnostic push #pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wcast-function-type-strict" #pragma clang diagnostic ignored "-Wcast-function-type-strict"
@ -475,6 +473,8 @@ CURLcode Curl_open(struct Curl_easy **curl)
Curl_hash_init(&data->meta_hash, 23, Curl_hash_init(&data->meta_hash, 23,
Curl_hash_str, curlx_str_key_compare, easy_meta_freeentry); Curl_hash_str, curlx_str_key_compare, easy_meta_freeentry);
DEBUGASSERT(STRING_LAST <= UINT8_MAX);
Curl_u8_strset_init(&data->set.strings);
curlx_dyn_init(&data->state.headerb, CURL_MAX_HTTP_HEADER); curlx_dyn_init(&data->state.headerb, CURL_MAX_HTTP_HEADER);
Curl_bufref_init(&data->state.url); Curl_bufref_init(&data->state.url);
Curl_bufref_init(&data->state.referer); Curl_bufref_init(&data->state.referer);
@ -1228,8 +1228,8 @@ static struct connectdata *allocate_conn(struct Curl_easy *data)
conn->transport_wanted = TRNSPRT_TCP; /* most of them are TCP streams */ conn->transport_wanted = TRNSPRT_TCP; /* most of them are TCP streams */
/* Store the local bind parameters that will be used for this connection */ /* Store the local bind parameters that will be used for this connection */
if(data->set.str[STRING_DEVICE]) { if(CURL_EASY_STR(data, STRING_DEVICE)) {
conn->localdev = curlx_strdup(data->set.str[STRING_DEVICE]); conn->localdev = curlx_strdup(CURL_EASY_STR(data, STRING_DEVICE));
if(!conn->localdev) if(!conn->localdev)
goto error; goto error;
} }
@ -1384,7 +1384,7 @@ static CURLcode url_set_data_creds_netrc(struct Curl_easy *data,
ret = Curl_netrc_scan(data, &data->state.netrc, ret = Curl_netrc_scan(data, &data->state.netrc,
data->state.origin->hostname, data->state.origin->hostname,
Curl_creds_user(ncreds_in), Curl_creds_user(ncreds_in),
data->set.str[STRING_NETRC_FILE], CURL_EASY_STR(data, STRING_NETRC_FILE),
&ncreds_out); &ncreds_out);
DEBUGASSERT(!ret || !ncreds_out); DEBUGASSERT(!ret || !ncreds_out);
if(ret == NETRC_OUT_OF_MEMORY) { if(ret == NETRC_OUT_OF_MEMORY) {
@ -1395,8 +1395,8 @@ static CURLcode url_set_data_creds_netrc(struct Curl_easy *data,
(data->set.use_netrc == CURL_NETRC_OPTIONAL))) { (data->set.use_netrc == CURL_NETRC_OPTIONAL))) {
infof(data, "Could not find host %s in the %s file; using defaults", infof(data, "Could not find host %s in the %s file; using defaults",
data->state.origin->hostname, data->state.origin->hostname,
(data->set.str[STRING_NETRC_FILE] ? (CURL_EASY_STR(data, STRING_NETRC_FILE) ?
data->set.str[STRING_NETRC_FILE] : ".netrc")); CURL_EASY_STR(data, STRING_NETRC_FILE) : ".netrc"));
} }
else if(ret) { else if(ret) {
const char *m = Curl_netrc_strerror(ret); const char *m = Curl_netrc_strerror(ret);
@ -1450,17 +1450,17 @@ static CURLcode url_set_data_creds(struct Curl_easy *data, CURLU *uh)
struct Curl_creds *newcreds = NULL; struct Curl_creds *newcreds = NULL;
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
if((data->set.str[STRING_USERNAME] || if((CURL_EASY_STR(data, STRING_USERNAME) ||
data->set.str[STRING_PASSWORD] || CURL_EASY_STR(data, STRING_PASSWORD) ||
data->set.str[STRING_BEARER] || CURL_EASY_STR(data, STRING_BEARER) ||
data->set.str[STRING_SASL_AUTHZID] || CURL_EASY_STR(data, STRING_SASL_AUTHZID) ||
data->set.str[STRING_SERVICE_NAME]) && CURL_EASY_STR(data, STRING_SERVICE_NAME)) &&
Curl_auth_allowed_to_origin(data, data->state.origin)) { Curl_auth_allowed_to_origin(data, data->state.origin)) {
result = Curl_creds_create(data->set.str[STRING_USERNAME], result = Curl_creds_create(CURL_EASY_STR(data, STRING_USERNAME),
data->set.str[STRING_PASSWORD], CURL_EASY_STR(data, STRING_PASSWORD),
data->set.str[STRING_BEARER], CURL_EASY_STR(data, STRING_BEARER),
data->set.str[STRING_SASL_AUTHZID], CURL_EASY_STR(data, STRING_SASL_AUTHZID),
data->set.str[STRING_SERVICE_NAME], CURL_EASY_STR(data, STRING_SERVICE_NAME),
CREDS_OPTION, &newcreds); CREDS_OPTION, &newcreds);
if(result) if(result)
goto out; goto out;
@ -1547,8 +1547,8 @@ static CURLcode url_set_conn_origin_etc(struct Curl_easy *data,
goto out; goto out;
/* set the connection options */ /* set the connection options */
if(data->set.str[STRING_OPTIONS]) { if(CURL_EASY_STR(data, STRING_OPTIONS)) {
conn->options = curlx_strdup(data->set.str[STRING_OPTIONS]); conn->options = curlx_strdup(CURL_EASY_STR(data, STRING_OPTIONS));
if(!conn->options) { if(!conn->options) {
result = CURLE_OUT_OF_MEMORY; result = CURLE_OUT_OF_MEMORY;
goto out; goto out;
@ -1579,14 +1579,14 @@ static CURLcode setup_range(struct Curl_easy *data)
{ {
struct UrlState *s = &data->state; struct UrlState *s = &data->state;
s->resume_from = data->set.set_resume_from; s->resume_from = data->set.set_resume_from;
if(s->resume_from || data->set.str[STRING_SET_RANGE]) { if(s->resume_from || CURL_EASY_STR(data, STRING_SET_RANGE)) {
if(s->rangestringalloc) if(s->rangestringalloc)
curlx_free(s->range); curlx_free(s->range);
if(s->resume_from) if(s->resume_from)
s->range = curl_maprintf("%" FMT_OFF_T "-", s->resume_from); s->range = curl_maprintf("%" FMT_OFF_T "-", s->resume_from);
else else
s->range = curlx_strdup(data->set.str[STRING_SET_RANGE]); s->range = curlx_strdup(CURL_EASY_STR(data, STRING_SET_RANGE));
if(!s->range) if(!s->range)
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
@ -2052,11 +2052,10 @@ static CURLcode url_create_needle(struct Curl_easy *data,
/************************************************************* /*************************************************************
* Set UDS first. It overrides "via_peer" and proxy settings. * Set UDS first. It overrides "via_peer" and proxy settings.
*************************************************************/ *************************************************************/
if(network_scheme && data->set.str[STRING_UNIX_SOCKET_PATH]) { if(network_scheme && CURL_EASY_STR(data, STRING_UNIX_SOCKET_PATH)) {
result = Curl_peer_uds_create(needle->origin->scheme, result = Curl_peer_uds_create(
data->set.str[STRING_UNIX_SOCKET_PATH], needle->origin->scheme, CURL_EASY_STR(data, STRING_UNIX_SOCKET_PATH),
(bool)data->set.abstract_unix_socket, (bool)data->set.abstract_unix_socket, &needle->via_peer);
&needle->via_peer);
if(result) if(result)
goto out; goto out;
} }
@ -2169,10 +2168,10 @@ static CURLcode url_set_data_origin_and_creds(struct Curl_easy *data)
/* Calculate the *real* URL this transfer uses, applying defaults /* Calculate the *real* URL this transfer uses, applying defaults
* where information is missing. */ * where information is missing. */
if(data->set.str[STRING_DEFAULT_PROTOCOL] && if(CURL_EASY_STR(data, STRING_DEFAULT_PROTOCOL) &&
!Curl_is_absolute_url(Curl_bufref_ptr(&data->state.url), NULL, 0, TRUE)) { !Curl_is_absolute_url(Curl_bufref_ptr(&data->state.url), NULL, 0, TRUE)) {
char *url = curl_maprintf("%s://%s", char *url = curl_maprintf("%s://%s",
data->set.str[STRING_DEFAULT_PROTOCOL], CURL_EASY_STR(data, STRING_DEFAULT_PROTOCOL),
Curl_bufref_ptr(&data->state.url)); Curl_bufref_ptr(&data->state.url));
if(!url) { if(!url) {
result = CURLE_OUT_OF_MEMORY; result = CURLE_OUT_OF_MEMORY;

View file

@ -69,6 +69,7 @@
#include "request.h" #include "request.h"
#include "ratelimit.h" #include "ratelimit.h"
#include "netrc.h" #include "netrc.h"
#include "uint-hashset.h"
#include "vdns/asyn.h" #include "vdns/asyn.h"
#include "vdns/hostip.h" #include "vdns/hostip.h"
#include "vtls/vtls_config.h" #include "vtls/vtls_config.h"
@ -804,14 +805,6 @@ enum dupstring {
STRING_ECH_PUBLIC, /* CURLOPT_ECH_PUBLIC */ STRING_ECH_PUBLIC, /* CURLOPT_ECH_PUBLIC */
STRING_SSL_SIGNATURE_ALGORITHMS, /* CURLOPT_SSL_SIGNATURE_ALGORITHMS */ STRING_SSL_SIGNATURE_ALGORITHMS, /* CURLOPT_SSL_SIGNATURE_ALGORITHMS */
/* -- end of null-terminated strings -- */
STRING_LASTZEROTERMINATED,
/* -- below this are pointers to binary data that cannot be strdup'ed. --- */
STRING_COPYPOSTFIELDS, /* if POST, set the fields' values here */
STRING_LAST /* not used, an end-of-list marker */ STRING_LAST /* not used, an end-of-list marker */
}; };
@ -839,6 +832,7 @@ struct UserDefined {
uint32_t httpauth; /* kind of HTTP authentication to use (bitmask) */ uint32_t httpauth; /* kind of HTTP authentication to use (bitmask) */
uint32_t proxyauth; /* kind of proxy authentication to use (bitmask) */ uint32_t proxyauth; /* kind of proxy authentication to use (bitmask) */
void *postfields; /* if POST, set the fields' values here */ void *postfields; /* if POST, set the fields' values here */
char *str_copypostfields; /* CURLOPT_COPYPOSTFIELDS value */
curl_seek_callback seek_func; /* function that seeks the input */ curl_seek_callback seek_func; /* function that seeks the input */
curl_off_t postfieldsize; /* if POST, this might have a size to use instead curl_off_t postfieldsize; /* if POST, this might have a size to use instead
of strlen(), and then the data *may* be binary of strlen(), and then the data *may* be binary
@ -933,7 +927,7 @@ struct UserDefined {
uint32_t ssh_auth_types; /* allowed SSH auth types */ uint32_t ssh_auth_types; /* allowed SSH auth types */
uint32_t new_directory_perms; /* when creating remote dirs */ uint32_t new_directory_perms; /* when creating remote dirs */
#endif #endif
char *str[STRING_LAST]; /* array of strings, pointing to allocated memory */ struct u8_strset strings;
struct curl_blob *blobs[BLOB_LAST]; struct curl_blob *blobs[BLOB_LAST];
uint32_t new_file_perms; /* when creating remote files */ uint32_t new_file_perms; /* when creating remote files */
#ifdef USE_IPV6 #ifdef USE_IPV6
@ -1230,6 +1224,17 @@ struct Curl_easy {
valid after a client has asked for it */ valid after a client has asked for it */
}; };
#define CURL_EASY_STR(d, id) \
Curl_u8_strset_get(&(d)->set.strings, (uint8_t)(id))
#define CURL_EASY_STR_SET(d, id, s) \
Curl_u8_strset_set(&(d)->set.strings, (uint8_t)(id), (s))
#define CURL_EASY_STR_SETN(d, id, s) \
Curl_u8_strset_setn(&(d)->set.strings, (uint8_t)(id), (s))
#define CURL_EASY_STR_CLEAR(d, id) \
Curl_u8_strset_unset(&(d)->set.strings, (uint8_t)(id))
#define CURL_EASY_STR_CLEAR0(d, id) \
Curl_u8_strset_unset0(&(d)->set.strings, (uint8_t)(id))
#define LIBCURL_NAME "libcurl" #define LIBCURL_NAME "libcurl"
#endif /* HEADER_CURL_URLDATA_H */ #endif /* HEADER_CURL_URLDATA_H */

View file

@ -660,7 +660,7 @@ static CURLcode async_ares_set_dns_servers(struct Curl_easy *data,
{ {
struct async_ares_ctx *ares = async ? &async->ares : NULL; struct async_ares_ctx *ares = async ? &async->ares : NULL;
CURLcode result = CURLE_NOT_BUILT_IN; CURLcode result = CURLE_NOT_BUILT_IN;
const char *servers = data->set.str[STRING_DNS_SERVERS]; const char *servers = CURL_EASY_STR(data, STRING_DNS_SERVERS);
int ares_result = ARES_SUCCESS; int ares_result = ARES_SUCCESS;
#ifdef DEBUGBUILD #ifdef DEBUGBUILD
@ -696,7 +696,7 @@ static CURLcode async_ares_set_dns_interface(struct Curl_easy *data,
struct Curl_resolv_async *async) struct Curl_resolv_async *async)
{ {
struct async_ares_ctx *ares = async ? &async->ares : NULL; struct async_ares_ctx *ares = async ? &async->ares : NULL;
const char *interf = data->set.str[STRING_DNS_INTERFACE]; const char *interf = CURL_EASY_STR(data, STRING_DNS_INTERFACE);
if(!interf) if(!interf)
interf = ""; interf = "";
@ -713,7 +713,7 @@ static CURLcode async_ares_set_dns_local_ip4(struct Curl_easy *data,
{ {
struct async_ares_ctx *ares = async ? &async->ares : NULL; struct async_ares_ctx *ares = async ? &async->ares : NULL;
struct in_addr a4; struct in_addr a4;
const char *local_ip4 = data->set.str[STRING_DNS_LOCAL_IP4]; const char *local_ip4 = CURL_EASY_STR(data, STRING_DNS_LOCAL_IP4);
if(!local_ip4 || (local_ip4[0] == 0)) { if(!local_ip4 || (local_ip4[0] == 0)) {
a4.s_addr = 0; /* disabled: do not bind to a specific address */ a4.s_addr = 0; /* disabled: do not bind to a specific address */
@ -738,7 +738,7 @@ static CURLcode async_ares_set_dns_local_ip6(struct Curl_easy *data,
#ifdef USE_IPV6 #ifdef USE_IPV6
struct async_ares_ctx *ares = async ? &async->ares : NULL; struct async_ares_ctx *ares = async ? &async->ares : NULL;
unsigned char a6[INET6_ADDRSTRLEN]; unsigned char a6[INET6_ADDRSTRLEN];
const char *local_ip6 = data->set.str[STRING_DNS_LOCAL_IP6]; const char *local_ip6 = CURL_EASY_STR(data, STRING_DNS_LOCAL_IP6);
if(!local_ip6 || (local_ip6[0] == 0)) { if(!local_ip6 || (local_ip6[0] == 0)) {
/* disabled: do not bind to a specific address */ /* disabled: do not bind to a specific address */

View file

@ -336,17 +336,20 @@ static CURLcode doh_probe_run(struct Curl_easy *data,
doh->set.ssl.custom_cafile = data->set.ssl.custom_cafile; doh->set.ssl.custom_cafile = data->set.ssl.custom_cafile;
doh->set.ssl.custom_capath = data->set.ssl.custom_capath; doh->set.ssl.custom_capath = data->set.ssl.custom_capath;
doh->set.ssl.custom_cablob = data->set.ssl.custom_cablob; doh->set.ssl.custom_cablob = data->set.ssl.custom_cablob;
if(data->set.str[STRING_SSL_CAFILE]) { if(CURL_EASY_STR(data, STRING_SSL_CAFILE)) {
ERROR_CHECK_SETOPT(CURLOPT_CAINFO, data->set.str[STRING_SSL_CAFILE]); ERROR_CHECK_SETOPT(CURLOPT_CAINFO,
CURL_EASY_STR(data, STRING_SSL_CAFILE));
} }
if(data->set.blobs[BLOB_CAINFO]) { if(data->set.blobs[BLOB_CAINFO]) {
ERROR_CHECK_SETOPT(CURLOPT_CAINFO_BLOB, data->set.blobs[BLOB_CAINFO]); ERROR_CHECK_SETOPT(CURLOPT_CAINFO_BLOB, data->set.blobs[BLOB_CAINFO]);
} }
if(data->set.str[STRING_SSL_CAPATH]) { if(CURL_EASY_STR(data, STRING_SSL_CAPATH)) {
ERROR_CHECK_SETOPT(CURLOPT_CAPATH, data->set.str[STRING_SSL_CAPATH]); ERROR_CHECK_SETOPT(CURLOPT_CAPATH,
CURL_EASY_STR(data, STRING_SSL_CAPATH));
} }
if(data->set.str[STRING_SSL_CRLFILE]) { if(CURL_EASY_STR(data, STRING_SSL_CRLFILE)) {
ERROR_CHECK_SETOPT(CURLOPT_CRLFILE, data->set.str[STRING_SSL_CRLFILE]); ERROR_CHECK_SETOPT(CURLOPT_CRLFILE,
CURL_EASY_STR(data, STRING_SSL_CRLFILE));
} }
if(data->set.ssl.certinfo) if(data->set.ssl.certinfo)
ERROR_CHECK_SETOPT(CURLOPT_CERTINFO, 1L); ERROR_CHECK_SETOPT(CURLOPT_CERTINFO, 1L);
@ -354,9 +357,9 @@ static CURLcode doh_probe_run(struct Curl_easy *data,
ERROR_CHECK_SETOPT(CURLOPT_SSL_CTX_FUNCTION, data->set.ssl.fsslctx); ERROR_CHECK_SETOPT(CURLOPT_SSL_CTX_FUNCTION, data->set.ssl.fsslctx);
if(data->set.ssl.fsslctxp) if(data->set.ssl.fsslctxp)
ERROR_CHECK_SETOPT(CURLOPT_SSL_CTX_DATA, data->set.ssl.fsslctxp); ERROR_CHECK_SETOPT(CURLOPT_SSL_CTX_DATA, data->set.ssl.fsslctxp);
if(data->set.str[STRING_SSL_EC_CURVES]) { if(CURL_EASY_STR(data, STRING_SSL_EC_CURVES)) {
ERROR_CHECK_SETOPT(CURLOPT_SSL_EC_CURVES, ERROR_CHECK_SETOPT(CURLOPT_SSL_EC_CURVES,
data->set.str[STRING_SSL_EC_CURVES]); CURL_EASY_STR(data, STRING_SSL_EC_CURVES));
} }
(void)curl_easy_setopt(doh, CURLOPT_SSL_OPTIONS, (void)curl_easy_setopt(doh, CURLOPT_SSL_OPTIONS,
@ -442,7 +445,8 @@ CURLcode Curl_doh(struct Curl_easy *data,
if(async->dns_queries & CURL_DNSQ_AAAA) { if(async->dns_queries & CURL_DNSQ_AAAA) {
/* create IPv6 DoH request */ /* create IPv6 DoH request */
result = doh_probe_run(data, CURL_DNS_TYPE_AAAA, result = doh_probe_run(data, CURL_DNS_TYPE_AAAA,
async->peer->hostname, data->set.str[STRING_DOH], async->peer->hostname,
CURL_EASY_STR(data, STRING_DOH),
data->multi, async->id, data->multi, async->id,
&dohp->probe_mid[DOH_SLOT_IPV6]); &dohp->probe_mid[DOH_SLOT_IPV6]);
if(result) if(result)
@ -454,7 +458,8 @@ CURLcode Curl_doh(struct Curl_easy *data,
/* create IPv4 DoH request */ /* create IPv4 DoH request */
if(async->dns_queries & CURL_DNSQ_A) { if(async->dns_queries & CURL_DNSQ_A) {
result = doh_probe_run(data, CURL_DNS_TYPE_A, result = doh_probe_run(data, CURL_DNS_TYPE_A,
async->peer->hostname, data->set.str[STRING_DOH], async->peer->hostname,
CURL_EASY_STR(data, STRING_DOH),
data->multi, async->id, data->multi, async->id,
&dohp->probe_mid[DOH_SLOT_IPV4]); &dohp->probe_mid[DOH_SLOT_IPV4]);
if(result) if(result)
@ -473,7 +478,7 @@ CURLcode Curl_doh(struct Curl_easy *data,
} }
result = doh_probe_run(data, CURL_DNS_TYPE_HTTPS, result = doh_probe_run(data, CURL_DNS_TYPE_HTTPS,
qname ? qname : async->peer->hostname, qname ? qname : async->peer->hostname,
data->set.str[STRING_DOH], data->multi, CURL_EASY_STR(data, STRING_DOH), data->multi,
async->id, async->id,
&dohp->probe_mid[DOH_SLOT_HTTPS_RR]); &dohp->probe_mid[DOH_SLOT_HTTPS_RR]);
curlx_free(qname); curlx_free(qname);

View file

@ -689,9 +689,9 @@ static CURLcode h3_stream_open(struct Curl_cfilter *cf,
} }
result = Curl_h1_req_parse_read(&stream->h1, buf, len, NULL, result = Curl_h1_req_parse_read(&stream->h1, buf, len, NULL,
!data->state.http_ignorecustom ? !data->state.http_ignorecustom ?
data->set.str[STRING_CUSTOMREQUEST] : NULL, CURL_EASY_STR(data, STRING_CUSTOMREQUEST) : NULL,
0, pnwritten); 0, pnwritten);
if(result) if(result)
goto out; goto out;
if(!stream->h1.done) { if(!stream->h1.done) {

View file

@ -1012,9 +1012,9 @@ static CURLcode h3_open_stream(struct Curl_cfilter *cf,
DEBUGASSERT(stream); DEBUGASSERT(stream);
result = Curl_h1_req_parse_read(&stream->h1, buf, blen, NULL, result = Curl_h1_req_parse_read(&stream->h1, buf, blen, NULL,
!data->state.http_ignorecustom ? !data->state.http_ignorecustom ?
data->set.str[STRING_CUSTOMREQUEST] : NULL, CURL_EASY_STR(data, STRING_CUSTOMREQUEST) : NULL,
0, pnwritten); 0, pnwritten);
if(result) if(result)
goto out; goto out;
if(!stream->h1.done) { if(!stream->h1.done) {

View file

@ -166,9 +166,9 @@ CURLcode Curl_vquic_tls_verify_peer(struct curl_tls_ctx *ctx,
(void)conn_config; (void)conn_config;
result = Curl_ossl_check_peer_cert(cf, data, &ctx->ossl, peer); result = Curl_ossl_check_peer_cert(cf, data, &ctx->ossl, peer);
#elif defined(USE_GNUTLS) #elif defined(USE_GNUTLS)
result = Curl_gtls_verifyserver(cf, data, ctx->gtls.session, result = Curl_gtls_verifyserver(
conn_config, &data->set.ssl, peer, cf, data, ctx->gtls.session, conn_config, &data->set.ssl, peer,
data->set.str[STRING_SSL_PINNEDPUBLICKEY]); CURL_EASY_STR(data, STRING_SSL_PINNEDPUBLICKEY));
if(result) if(result)
return result; return result;
#elif defined(USE_WOLFSSL) #elif defined(USE_WOLFSSL)

View file

@ -1022,7 +1022,7 @@ CURLcode Curl_cf_quic_insert_after(struct Curl_cfilter *cf_at,
CURLECH_ENABLED(data) && CURLECH_ENABLED(data) &&
Curl_ssl_supports(data, SSLSUPP_ECH) && Curl_ssl_supports(data, SSLSUPP_ECH) &&
(data->set.tls_ech != CURLECH_GREASE) && (data->set.tls_ech != CURLECH_GREASE) &&
!data->set.str[STRING_ECH_CONFIG]) { !CURL_EASY_STR(data, STRING_ECH_CONFIG)) {
result = Curl_conn_dns_add_https_resolve(data, cf_at->conn, result = Curl_conn_dns_add_https_resolve(data, cf_at->conn,
cf_at->sockindex, origin); cf_at->sockindex, origin);
} }

View file

@ -109,10 +109,10 @@ static CURLcode sftp_error_to_CURLE(int err)
} }
/* Multiple options: /* Multiple options:
* 1. data->set.str[STRING_SSH_HOST_PUBLIC_KEY_SHA256] is set with a SHA256 * 1. CURL_EASY_STR(data, STRING_SSH_HOST_PUBLIC_KEY_SHA256) is set
* hash. * with a SHA256 hash.
* 2. data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5] is set with an MD5 * 2. CURL_EASY_STR(data, STRING_SSH_HOST_PUBLIC_KEY_MD5) is set
* hash (90s style auth, not sure we should have it here) * with an MD5 hash (90s style auth, not sure we should have it here)
* 3. data->set.ssh_keyfunc callback is set. Then we do trust on first * 3. data->set.ssh_keyfunc callback is set. Then we do trust on first
* use. We even save on knownhosts if CURLKHSTAT_FINE_ADD_TO_FILE * use. We even save on knownhosts if CURLKHSTAT_FINE_ADD_TO_FILE
* is returned by it. * is returned by it.
@ -143,9 +143,9 @@ static int myssh_is_known(struct Curl_easy *data, struct ssh_conn *sshc)
if(rc != SSH_OK) if(rc != SSH_OK)
return rc; return rc;
if(data->set.str[STRING_SSH_HOST_PUBLIC_KEY_SHA256]) { if(CURL_EASY_STR(data, STRING_SSH_HOST_PUBLIC_KEY_SHA256)) {
const char *pubkey_sha256 = const char *pubkey_sha256 =
data->set.str[STRING_SSH_HOST_PUBLIC_KEY_SHA256]; CURL_EASY_STR(data, STRING_SSH_HOST_PUBLIC_KEY_SHA256);
char *fingerprint_b64 = NULL; char *fingerprint_b64 = NULL;
size_t fingerprint_b64_len; size_t fingerprint_b64_len;
size_t pub_pos = 0; size_t pub_pos = 0;
@ -197,8 +197,9 @@ static int myssh_is_known(struct Curl_easy *data, struct ssh_conn *sshc)
goto cleanup; goto cleanup;
} }
if(data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5]) { if(CURL_EASY_STR(data, STRING_SSH_HOST_PUBLIC_KEY_MD5)) {
const char *pubkey_md5 = data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5]; const char *pubkey_md5 =
CURL_EASY_STR(data, STRING_SSH_HOST_PUBLIC_KEY_MD5);
char md5buffer[33]; char md5buffer[33];
int i; int i;
@ -227,7 +228,7 @@ static int myssh_is_known(struct Curl_easy *data, struct ssh_conn *sshc)
goto cleanup; goto cleanup;
} }
if(data->set.str[STRING_SSH_KNOWNHOSTS]) { if(CURL_EASY_STR(data, STRING_SSH_KNOWNHOSTS)) {
/* Get the known_key from the known hosts file */ /* Get the known_key from the known hosts file */
vstate = ssh_session_get_known_hosts_entry(sshc->ssh_session, vstate = ssh_session_get_known_hosts_entry(sshc->ssh_session,
@ -2618,15 +2619,16 @@ static CURLcode myssh_connect(struct Curl_easy *data, bool *done)
} }
} }
if(data->set.str[STRING_SSH_KNOWNHOSTS]) { if(CURL_EASY_STR(data, STRING_SSH_KNOWNHOSTS)) {
infof(data, "Known hosts: %s", data->set.str[STRING_SSH_KNOWNHOSTS]); infof(data, "Known hosts: %s",
CURL_EASY_STR(data, STRING_SSH_KNOWNHOSTS));
rc = ssh_options_set(sshc->ssh_session, SSH_OPTIONS_KNOWNHOSTS, rc = ssh_options_set(sshc->ssh_session, SSH_OPTIONS_KNOWNHOSTS,
data->set.str[STRING_SSH_KNOWNHOSTS]); CURL_EASY_STR(data, STRING_SSH_KNOWNHOSTS));
if(rc == SSH_OK) if(rc == SSH_OK)
/* libssh has two separate options for this. Set both to the same file /* libssh has two separate options for this. Set both to the same file
to avoid surprises */ to avoid surprises */
rc = ssh_options_set(sshc->ssh_session, SSH_OPTIONS_GLOBAL_KNOWNHOSTS, rc = ssh_options_set(sshc->ssh_session, SSH_OPTIONS_GLOBAL_KNOWNHOSTS,
data->set.str[STRING_SSH_KNOWNHOSTS]); CURL_EASY_STR(data, STRING_SSH_KNOWNHOSTS));
if(rc != SSH_OK) { if(rc != SSH_OK) {
failf(data, "Could not set known hosts file path"); failf(data, "Could not set known hosts file path");
return CURLE_FAILED_INIT; return CURLE_FAILED_INIT;

View file

@ -316,7 +316,7 @@ static CURLcode ssh_knownhost(struct Curl_easy *data,
int rc = 0; int rc = 0;
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
if(!data->set.str[STRING_SSH_KNOWNHOSTS]) { if(!CURL_EASY_STR(data, STRING_SSH_KNOWNHOSTS)) {
infof(data, "SSH: no knownhosts file configured"); infof(data, "SSH: no knownhosts file configured");
return CURLE_OK; return CURLE_OK;
} }
@ -460,12 +460,12 @@ static CURLcode ssh_knownhost(struct Curl_easy *data,
/* now we write the entire in-memory list of known hosts to the /* now we write the entire in-memory list of known hosts to the
known_hosts file */ known_hosts file */
int wrc = int wrc =
libssh2_knownhost_writefile(sshc->kh, libssh2_knownhost_writefile(
data->set.str[STRING_SSH_KNOWNHOSTS], sshc->kh, CURL_EASY_STR(data, STRING_SSH_KNOWNHOSTS),
LIBSSH2_KNOWNHOST_FILE_OPENSSH); LIBSSH2_KNOWNHOST_FILE_OPENSSH);
if(wrc) { if(wrc) {
infof(data, "WARNING: writing %s failed", infof(data, "WARNING: writing %s failed",
data->set.str[STRING_SSH_KNOWNHOSTS]); CURL_EASY_STR(data, STRING_SSH_KNOWNHOSTS));
} }
} }
} }
@ -481,8 +481,10 @@ static CURLcode ssh_knownhost(struct Curl_easy *data,
static CURLcode ssh_check_fingerprint(struct Curl_easy *data, static CURLcode ssh_check_fingerprint(struct Curl_easy *data,
struct ssh_conn *sshc) struct ssh_conn *sshc)
{ {
const char *pubkey_md5 = data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5]; const char *pubkey_md5 =
const char *pubkey_sha256 = data->set.str[STRING_SSH_HOST_PUBLIC_KEY_SHA256]; CURL_EASY_STR(data, STRING_SSH_HOST_PUBLIC_KEY_MD5);
const char *pubkey_sha256 =
CURL_EASY_STR(data, STRING_SSH_HOST_PUBLIC_KEY_SHA256);
if(pubkey_sha256) { if(pubkey_sha256) {
const char *fingerprint = NULL; const char *fingerprint = NULL;
@ -646,8 +648,8 @@ static CURLcode ssh_force_knownhost_key_type(struct Curl_easy *data,
bool found = FALSE; bool found = FALSE;
if(sshc->kh && if(sshc->kh &&
!data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5] && !CURL_EASY_STR(data, STRING_SSH_HOST_PUBLIC_KEY_MD5) &&
!data->set.str[STRING_SSH_HOST_PUBLIC_KEY_SHA256]) { !CURL_EASY_STR(data, STRING_SSH_HOST_PUBLIC_KEY_SHA256)) {
struct libssh2_knownhost *store = NULL; struct libssh2_knownhost *store = NULL;
struct connectdata *conn = data->conn; struct connectdata *conn = data->conn;
/* lets try to find our host in the known hosts file */ /* lets try to find our host in the known hosts file */
@ -663,7 +665,8 @@ static CURLcode ssh_force_knownhost_key_type(struct Curl_easy *data,
const char *kh_name_end = strstr(store->name, "]:"); const char *kh_name_end = strstr(store->name, "]:");
if(!kh_name_end) { if(!kh_name_end) {
infof(data, "SSH: invalid host pattern %s in %s", infof(data, "SSH: invalid host pattern %s in %s",
store->name, data->set.str[STRING_SSH_KNOWNHOSTS]); store->name,
CURL_EASY_STR(data, STRING_SSH_KNOWNHOSTS));
continue; continue;
} }
p = kh_name_end + 2; /* start of port number */ p = kh_name_end + 2; /* start of port number */
@ -693,7 +696,8 @@ static CURLcode ssh_force_knownhost_key_type(struct Curl_easy *data,
int rc; int rc;
const char *hostkey_method = NULL; const char *hostkey_method = NULL;
infof(data, "SSH: found host '%s' in '%s'", infof(data, "SSH: found host '%s' in '%s'",
conn->origin->hostname, data->set.str[STRING_SSH_KNOWNHOSTS]); conn->origin->hostname,
CURL_EASY_STR(data, STRING_SSH_KNOWNHOSTS));
switch(store->typemask & LIBSSH2_KNOWNHOST_KEY_MASK) { switch(store->typemask & LIBSSH2_KNOWNHOST_KEY_MASK) {
case LIBSSH2_KNOWNHOST_KEY_ED25519: case LIBSSH2_KNOWNHOST_KEY_ED25519:
@ -738,7 +742,8 @@ static CURLcode ssh_force_knownhost_key_type(struct Curl_easy *data,
} }
else { else {
infof(data, "SSH: did not find host '%s' in '%s'", infof(data, "SSH: did not find host '%s' in '%s'",
conn->origin->hostname, data->set.str[STRING_SSH_KNOWNHOSTS]); conn->origin->hostname,
CURL_EASY_STR(data, STRING_SSH_KNOWNHOSTS));
} }
} }
@ -3475,7 +3480,7 @@ static CURLcode ssh_connect(struct Curl_easy *data, bool *done)
infof(data, "SSH: failed to enable compression for session"); infof(data, "SSH: failed to enable compression for session");
} }
if(data->set.str[STRING_SSH_KNOWNHOSTS]) { if(CURL_EASY_STR(data, STRING_SSH_KNOWNHOSTS)) {
int rc; int rc;
sshc->kh = libssh2_knownhost_init(sshc->ssh_session); sshc->kh = libssh2_knownhost_init(sshc->ssh_session);
if(!sshc->kh) { if(!sshc->kh) {
@ -3485,12 +3490,12 @@ static CURLcode ssh_connect(struct Curl_easy *data, bool *done)
} }
/* read all known hosts from there */ /* read all known hosts from there */
rc = libssh2_knownhost_readfile(sshc->kh, rc = libssh2_knownhost_readfile(
data->set.str[STRING_SSH_KNOWNHOSTS], sshc->kh, CURL_EASY_STR(data, STRING_SSH_KNOWNHOSTS),
LIBSSH2_KNOWNHOST_FILE_OPENSSH); LIBSSH2_KNOWNHOST_FILE_OPENSSH);
if(rc < 0) if(rc < 0)
infof(data, "SSH: failed to read known hosts from %s", infof(data, "SSH: failed to read known hosts from %s",
data->set.str[STRING_SSH_KNOWNHOSTS]); CURL_EASY_STR(data, STRING_SSH_KNOWNHOSTS));
} }
#ifdef CURL_LIBSSH2_DEBUG #ifdef CURL_LIBSSH2_DEBUG

View file

@ -368,8 +368,9 @@ CURLcode Curl_ssh_setup_pkey(struct Curl_easy *data, struct ssh_conn *sshc)
if(data->set.ssh_auth_types & CURLSSH_AUTH_PUBLICKEY) { if(data->set.ssh_auth_types & CURLSSH_AUTH_PUBLICKEY) {
sshc->pub_key = sshc->priv_key = NULL; sshc->pub_key = sshc->priv_key = NULL;
if(data->set.str[STRING_SSH_PRIVATE_KEY]) { if(CURL_EASY_STR(data, STRING_SSH_PRIVATE_KEY)) {
sshc->priv_key = curlx_strdup(data->set.str[STRING_SSH_PRIVATE_KEY]); sshc->priv_key = curlx_strdup(
CURL_EASY_STR(data, STRING_SSH_PRIVATE_KEY));
if(!sshc->priv_key) if(!sshc->priv_key)
goto fail; goto fail;
} }
@ -417,10 +418,11 @@ CURLcode Curl_ssh_setup_pkey(struct Curl_easy *data, struct ssh_conn *sshc)
* library extract the public key from the private key file. This is done * library extract the public key from the private key file. This is done
* by passing sshc->pub_key = NULL. * by passing sshc->pub_key = NULL.
*/ */
if(data->set.str[STRING_SSH_PUBLIC_KEY] && if(CURL_EASY_STR(data, STRING_SSH_PUBLIC_KEY) &&
/* treat empty string the same way as NULL */ /* treat empty string the same way as NULL */
data->set.str[STRING_SSH_PUBLIC_KEY][0]) { CURL_EASY_STR(data, STRING_SSH_PUBLIC_KEY)[0]) {
sshc->pub_key = curlx_strdup(data->set.str[STRING_SSH_PUBLIC_KEY]); sshc->pub_key = curlx_strdup(
CURL_EASY_STR(data, STRING_SSH_PUBLIC_KEY));
if(!sshc->pub_key) if(!sshc->pub_key)
goto fail; goto fail;
} }

View file

@ -1868,10 +1868,10 @@ static CURLcode gtls_verifyserver(struct Curl_cfilter *cf,
struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data); struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
#ifndef CURL_DISABLE_PROXY #ifndef CURL_DISABLE_PROXY
const char *pinned_key = Curl_ssl_cf_is_proxy(cf) ? const char *pinned_key = Curl_ssl_cf_is_proxy(cf) ?
data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] : CURL_EASY_STR(data, STRING_SSL_PINNEDPUBLICKEY_PROXY) :
data->set.str[STRING_SSL_PINNEDPUBLICKEY]; CURL_EASY_STR(data, STRING_SSL_PINNEDPUBLICKEY);
#else #else
const char *pinned_key = data->set.str[STRING_SSL_PINNEDPUBLICKEY]; const char *pinned_key = CURL_EASY_STR(data, STRING_SSL_PINNEDPUBLICKEY);
#endif #endif
CURLcode result; CURLcode result;

View file

@ -1075,10 +1075,11 @@ static CURLcode mbed_connect_step2(struct Curl_cfilter *cf,
#ifdef HAVE_PINNED_PUBKEY #ifdef HAVE_PINNED_PUBKEY
#ifndef CURL_DISABLE_PROXY #ifndef CURL_DISABLE_PROXY
const char * const pinnedpubkey = Curl_ssl_cf_is_proxy(cf) ? const char * const pinnedpubkey = Curl_ssl_cf_is_proxy(cf) ?
data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] : CURL_EASY_STR(data, STRING_SSL_PINNEDPUBLICKEY_PROXY) :
data->set.str[STRING_SSL_PINNEDPUBLICKEY]; CURL_EASY_STR(data, STRING_SSL_PINNEDPUBLICKEY);
#else #else
const char * const pinnedpubkey = data->set.str[STRING_SSL_PINNEDPUBLICKEY]; const char * const pinnedpubkey =
CURL_EASY_STR(data, STRING_SSL_PINNEDPUBLICKEY);
#endif #endif
#endif #endif

View file

@ -3477,7 +3477,7 @@ bool Curl_ossl_need_httpsrr(struct Curl_easy *data)
if(!CURLECH_ENABLED(data)) if(!CURLECH_ENABLED(data))
return FALSE; return FALSE;
if((data->set.tls_ech == CURLECH_GREASE) || if((data->set.tls_ech == CURLECH_GREASE) ||
data->set.str[STRING_ECH_CONFIG]) CURL_EASY_STR(data, STRING_ECH_CONFIG))
return FALSE; return FALSE;
return TRUE; return TRUE;
} }
@ -3487,9 +3487,7 @@ static CURLcode ossl_init_ech(struct ossl_ctx *octx,
struct Curl_easy *data, struct Curl_easy *data,
struct ssl_peer *peer) struct ssl_peer *peer)
{ {
unsigned char *ech_config = NULL; const char *outername = CURL_EASY_STR(data, STRING_ECH_PUBLIC);
size_t ech_config_len = 0;
char *outername = data->set.str[STRING_ECH_PUBLIC];
int trying_ech_now = 0; int trying_ech_now = 0;
if(!CURLECH_ENABLED(data)) if(!CURLECH_ENABLED(data))
@ -3503,10 +3501,12 @@ static CURLcode ossl_init_ech(struct ossl_ctx *octx,
SSL_set_options(octx->ssl, SSL_OP_ECH_GREASE); SSL_set_options(octx->ssl, SSL_OP_ECH_GREASE);
#endif #endif
} }
else if(data->set.tls_ech && data->set.str[STRING_ECH_CONFIG]) { else if(data->set.tls_ech && CURL_EASY_STR(data, STRING_ECH_CONFIG)) {
#ifdef HAVE_BORINGSSL_LIKE #ifdef HAVE_BORINGSSL_LIKE
/* have to do base64 decode here for BoringSSL */ /* have to do base64 decode here for BoringSSL */
const char *b64 = data->set.str[STRING_ECH_CONFIG]; const char *b64 = CURL_EASY_STR(data, STRING_ECH_CONFIG);
uint8_t *ech_config;
size_t ech_config_len = 0;
CURLcode result; CURLcode result;
if(!b64) { if(!b64) {
@ -3530,13 +3530,16 @@ static CURLcode ossl_init_ech(struct ossl_ctx *octx,
curlx_free(ech_config); curlx_free(ech_config);
trying_ech_now = 1; trying_ech_now = 1;
#else #else
ech_config = (unsigned char *)data->set.str[STRING_ECH_CONFIG]; const char *ech_config = CURL_EASY_STR(data, STRING_ECH_CONFIG);
size_t ech_config_len = 0;
if(!ech_config) { if(!ech_config) {
infof(data, "ECH: ECHConfig from command line empty"); infof(data, "ECH: ECHConfig from command line empty");
return CURLE_SSL_CONNECT_ERROR; return CURLE_SSL_CONNECT_ERROR;
} }
ech_config_len = strlen(data->set.str[STRING_ECH_CONFIG]); ech_config_len = strlen(ech_config);
if(SSL_set1_ech_config_list(octx->ssl, ech_config, ech_config_len) != 1) { if(SSL_set1_ech_config_list(octx->ssl,
(const uint8_t *)ech_config,
ech_config_len) != 1) {
infof(data, "ECH: SSL_ECH_set1_ech_config_list failed"); infof(data, "ECH: SSL_ECH_set1_ech_config_list failed");
if(data->set.tls_ech == CURLECH_HARD) if(data->set.tls_ech == CURLECH_HARD)
return CURLE_SSL_CONNECT_ERROR; return CURLE_SSL_CONNECT_ERROR;
@ -4599,10 +4602,10 @@ static CURLcode ossl_check_pinned_key(struct Curl_cfilter *cf,
(void)cf; (void)cf;
#ifndef CURL_DISABLE_PROXY #ifndef CURL_DISABLE_PROXY
ptr = Curl_ssl_cf_is_proxy(cf) ? ptr = Curl_ssl_cf_is_proxy(cf) ?
data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] : CURL_EASY_STR(data, STRING_SSL_PINNEDPUBLICKEY_PROXY) :
data->set.str[STRING_SSL_PINNEDPUBLICKEY]; CURL_EASY_STR(data, STRING_SSL_PINNEDPUBLICKEY);
#else #else
ptr = data->set.str[STRING_SSL_PINNEDPUBLICKEY]; ptr = CURL_EASY_STR(data, STRING_SSL_PINNEDPUBLICKEY);
#endif #endif
if(ptr) { if(ptr) {
result = ossl_pkp_pin_peer_pubkey(data, server_cert, ptr); result = ossl_pkp_pin_peer_pubkey(data, server_cert, ptr);

View file

@ -923,7 +923,7 @@ static bool cr_ech_need_httpsrr(struct Curl_easy *data)
if(!CURLECH_ENABLED(data)) if(!CURLECH_ENABLED(data))
return FALSE; return FALSE;
if((data->set.tls_ech == CURLECH_GREASE) || if((data->set.tls_ech == CURLECH_GREASE) ||
data->set.str[STRING_ECH_CONFIG]) CURL_EASY_STR(data, STRING_ECH_CONFIG))
return FALSE; return FALSE;
return TRUE; return TRUE;
} }
@ -948,7 +948,7 @@ init_config_builder_ech(struct Curl_easy *data,
goto cleanup; goto cleanup;
} }
if(data->set.str[STRING_ECH_PUBLIC]) { if(CURL_EASY_STR(data, STRING_ECH_PUBLIC)) {
failf(data, "rustls: ECH outername not supported"); failf(data, "rustls: ECH outername not supported");
result = CURLE_SSL_CONNECT_ERROR; result = CURLE_SSL_CONNECT_ERROR;
goto cleanup; goto cleanup;
@ -964,8 +964,8 @@ init_config_builder_ech(struct Curl_easy *data,
return CURLE_OK; return CURLE_OK;
} }
if(data->set.tls_ech && data->set.str[STRING_ECH_CONFIG]) { if(data->set.tls_ech && CURL_EASY_STR(data, STRING_ECH_CONFIG)) {
const char *b64 = data->set.str[STRING_ECH_CONFIG]; const char *b64 = CURL_EASY_STR(data, STRING_ECH_CONFIG);
size_t decode_result; size_t decode_result;
if(!b64) { if(!b64) {
infof(data, "rustls: ECHConfig from command line empty"); infof(data, "rustls: ECHConfig from command line empty");
@ -1005,7 +1005,7 @@ init_config_builder_ech(struct Curl_easy *data,
} }
cleanup: cleanup:
/* if we base64 decoded, we can free now */ /* if we base64 decoded, we can free now */
if(data->set.tls_ech && data->set.str[STRING_ECH_CONFIG]) { if(data->set.tls_ech && CURL_EASY_STR(data, STRING_ECH_CONFIG)) {
curlx_free(ech_config); curlx_free(ech_config);
} }
if(dns) { if(dns) {

View file

@ -1458,10 +1458,10 @@ static CURLcode schannel_connect_step2(struct Curl_cfilter *cf,
#ifndef CURL_DISABLE_PROXY #ifndef CURL_DISABLE_PROXY
pubkey_ptr = Curl_ssl_cf_is_proxy(cf) ? pubkey_ptr = Curl_ssl_cf_is_proxy(cf) ?
data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] : CURL_EASY_STR(data, STRING_SSL_PINNEDPUBLICKEY_PROXY) :
data->set.str[STRING_SSL_PINNEDPUBLICKEY]; CURL_EASY_STR(data, STRING_SSL_PINNEDPUBLICKEY);
#else #else
pubkey_ptr = data->set.str[STRING_SSL_PINNEDPUBLICKEY]; pubkey_ptr = CURL_EASY_STR(data, STRING_SSL_PINNEDPUBLICKEY);
#endif #endif
if(pubkey_ptr) { if(pubkey_ptr) {
result = schannel_pkp_pin_peer_pubkey(cf, data, pubkey_ptr); result = schannel_pkp_pin_peer_pubkey(cf, data, pubkey_ptr);

View file

@ -1431,7 +1431,7 @@ CURLcode Curl_cf_ssl_insert_after(struct Curl_cfilter *cf_at,
CURLECH_ENABLED(data) && CURLECH_ENABLED(data) &&
Curl_ssl_supports(data, SSLSUPP_ECH) && Curl_ssl_supports(data, SSLSUPP_ECH) &&
(data->set.tls_ech != CURLECH_GREASE) && (data->set.tls_ech != CURLECH_GREASE) &&
!data->set.str[STRING_ECH_CONFIG]) { !CURL_EASY_STR(data, STRING_ECH_CONFIG)) {
result = Curl_conn_dns_add_https_resolve(data, cf->conn, cf->sockindex, result = Curl_conn_dns_add_https_resolve(data, cf->conn, cf->sockindex,
origin); origin);
} }

View file

@ -236,12 +236,18 @@ static void ssl_easy_config_compl_options(struct Curl_peer *origin,
!!(options & CURLSSLOPT_AUTO_CLIENT_CERT); !!(options & CURLSSLOPT_AUTO_CLIENT_CERT);
} }
static char *ssl_easy_steal(struct Curl_easy *data, enum dupstring id)
{
/* For connection matching, we borrow string references from data
* THIS IS NOT REALLY NICE. */
return CURL_UNCONST(CURL_EASY_STR(data, id));
}
CURLcode Curl_ssl_easy_config_complete(struct Curl_easy *data, CURLcode Curl_ssl_easy_config_complete(struct Curl_easy *data,
struct Curl_peer *origin) struct Curl_peer *origin)
{ {
struct ssl_config_data *sslc = &data->set.ssl; struct ssl_config_data *sslc = &data->set.ssl;
#if defined(CURL_CA_PATH) || defined(CURL_CA_BUNDLE) #if defined(CURL_CA_PATH) || defined(CURL_CA_BUNDLE)
struct UserDefined *set = &data->set;
CURLcode result; CURLcode result;
#endif #endif
@ -253,42 +259,43 @@ CURLcode Curl_ssl_easy_config_complete(struct Curl_easy *data,
sslc->native_ca_store = TRUE; sslc->native_ca_store = TRUE;
#endif #endif
#ifdef CURL_CA_PATH #ifdef CURL_CA_PATH
if(!sslc->custom_capath && !set->str[STRING_SSL_CAPATH]) { if(!sslc->custom_capath && !CURL_EASY_STR(data, STRING_SSL_CAPATH)) {
result = Curl_setstropt(&set->str[STRING_SSL_CAPATH], CURL_CA_PATH); result = Curl_setstropt(data, STRING_SSL_CAPATH, CURL_CA_PATH);
if(result) if(result)
return result; return result;
} }
#endif #endif
#ifdef CURL_CA_BUNDLE #ifdef CURL_CA_BUNDLE
if(!sslc->custom_cafile && !set->str[STRING_SSL_CAFILE]) { if(!sslc->custom_cafile && !CURL_EASY_STR(data, STRING_SSL_CAFILE)) {
result = Curl_setstropt(&set->str[STRING_SSL_CAFILE], CURL_CA_BUNDLE); result = Curl_setstropt(data, STRING_SSL_CAFILE, CURL_CA_BUNDLE);
if(result) if(result)
return result; return result;
} }
#endif #endif
} }
sslc->primary.CAfile = data->set.str[STRING_SSL_CAFILE]; sslc->primary.CAfile = ssl_easy_steal(data, STRING_SSL_CAFILE);
sslc->primary.CRLfile = data->set.str[STRING_SSL_CRLFILE]; sslc->primary.CRLfile = ssl_easy_steal(data, STRING_SSL_CRLFILE);
sslc->primary.CApath = data->set.str[STRING_SSL_CAPATH]; sslc->primary.CApath = ssl_easy_steal(data, STRING_SSL_CAPATH);
sslc->primary.cipher_list = data->set.str[STRING_SSL_CIPHER_LIST]; sslc->primary.cipher_list = ssl_easy_steal(data, STRING_SSL_CIPHER_LIST);
sslc->primary.cipher_list13 = data->set.str[STRING_SSL_CIPHER13_LIST]; sslc->primary.cipher_list13 = ssl_easy_steal(data, STRING_SSL_CIPHER13_LIST);
sslc->primary.signature_algorithms = sslc->primary.signature_algorithms =
data->set.str[STRING_SSL_SIGNATURE_ALGORITHMS]; ssl_easy_steal(data, STRING_SSL_SIGNATURE_ALGORITHMS);
sslc->primary.ca_info_blob = data->set.blobs[BLOB_CAINFO]; sslc->primary.ca_info_blob = data->set.blobs[BLOB_CAINFO];
sslc->primary.curves = data->set.str[STRING_SSL_EC_CURVES]; sslc->primary.curves = ssl_easy_steal(data, STRING_SSL_EC_CURVES);
/* Maybe these should not be used for another origin. But for /* Maybe these should not be used for another origin. But for
* backwards compatibility, keep them in. */ * backwards compatibility, keep them in. */
sslc->primary.issuercert = data->set.str[STRING_SSL_ISSUERCERT]; sslc->primary.issuercert = ssl_easy_steal(data, STRING_SSL_ISSUERCERT);
sslc->primary.issuercert_blob = data->set.blobs[BLOB_SSL_ISSUERCERT]; sslc->primary.issuercert_blob = data->set.blobs[BLOB_SSL_ISSUERCERT];
if(Curl_peer_equal(data->state.initial_origin, origin)) { if(Curl_peer_equal(data->state.initial_origin, origin)) {
sslc->primary.pinned_key = data->set.str[STRING_SSL_PINNEDPUBLICKEY]; sslc->primary.pinned_key =
ssl_easy_steal(data, STRING_SSL_PINNEDPUBLICKEY);
sslc->primary.cert_blob = data->set.blobs[BLOB_CERT]; sslc->primary.cert_blob = data->set.blobs[BLOB_CERT];
sslc->primary.cert_type = data->set.str[STRING_CERT_TYPE]; sslc->primary.cert_type = ssl_easy_steal(data, STRING_CERT_TYPE);
sslc->primary.key = data->set.str[STRING_KEY]; sslc->primary.key = ssl_easy_steal(data, STRING_KEY);
sslc->primary.key_type = data->set.str[STRING_KEY_TYPE]; sslc->primary.key_type = ssl_easy_steal(data, STRING_KEY_TYPE);
sslc->primary.key_passwd = data->set.str[STRING_KEY_PASSWD]; sslc->primary.key_passwd = ssl_easy_steal(data, STRING_KEY_PASSWD);
sslc->primary.clientcert = data->set.str[STRING_CERT]; sslc->primary.clientcert = ssl_easy_steal(data, STRING_CERT);
sslc->primary.key_blob = data->set.blobs[BLOB_KEY]; sslc->primary.key_blob = data->set.blobs[BLOB_KEY];
} }
else { else {
@ -313,37 +320,40 @@ CURLcode Curl_ssl_easy_config_complete(struct Curl_easy *data,
sslc->native_ca_store = TRUE; sslc->native_ca_store = TRUE;
#endif #endif
#ifdef CURL_CA_PATH #ifdef CURL_CA_PATH
if(!sslc->custom_capath && !set->str[STRING_SSL_CAPATH_PROXY]) { if(!sslc->custom_capath &&
result = Curl_setstropt(&set->str[STRING_SSL_CAPATH_PROXY], !CURL_EASY_STR(data, STRING_SSL_CAPATH_PROXY)) {
CURL_CA_PATH); result = Curl_setstropt(data, STRING_SSL_CAPATH_PROXY, CURL_CA_PATH);
if(result) if(result)
return result; return result;
} }
#endif #endif
#ifdef CURL_CA_BUNDLE #ifdef CURL_CA_BUNDLE
if(!sslc->custom_cafile && !set->str[STRING_SSL_CAFILE_PROXY]) { if(!sslc->custom_cafile &&
result = Curl_setstropt(&set->str[STRING_SSL_CAFILE_PROXY], !CURL_EASY_STR(data, STRING_SSL_CAFILE_PROXY)) {
CURL_CA_BUNDLE); result = Curl_setstropt(data, STRING_SSL_CAFILE_PROXY, CURL_CA_BUNDLE);
if(result) if(result)
return result; return result;
} }
#endif #endif
} }
sslc->primary.CAfile = data->set.str[STRING_SSL_CAFILE_PROXY]; sslc->primary.CAfile = ssl_easy_steal(data, STRING_SSL_CAFILE_PROXY);
sslc->primary.CApath = data->set.str[STRING_SSL_CAPATH_PROXY]; sslc->primary.CApath = ssl_easy_steal(data, STRING_SSL_CAPATH_PROXY);
sslc->primary.cipher_list = data->set.str[STRING_SSL_CIPHER_LIST_PROXY]; sslc->primary.cipher_list =
sslc->primary.cipher_list13 = data->set.str[STRING_SSL_CIPHER13_LIST_PROXY]; ssl_easy_steal(data, STRING_SSL_CIPHER_LIST_PROXY);
sslc->primary.pinned_key = data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY]; sslc->primary.cipher_list13 =
ssl_easy_steal(data, STRING_SSL_CIPHER13_LIST_PROXY);
sslc->primary.pinned_key =
ssl_easy_steal(data, STRING_SSL_PINNEDPUBLICKEY_PROXY);
sslc->primary.cert_blob = data->set.blobs[BLOB_CERT_PROXY]; sslc->primary.cert_blob = data->set.blobs[BLOB_CERT_PROXY];
sslc->primary.ca_info_blob = data->set.blobs[BLOB_CAINFO_PROXY]; sslc->primary.ca_info_blob = data->set.blobs[BLOB_CAINFO_PROXY];
sslc->primary.issuercert = data->set.str[STRING_SSL_ISSUERCERT_PROXY]; sslc->primary.issuercert = ssl_easy_steal(data, STRING_SSL_ISSUERCERT_PROXY);
sslc->primary.issuercert_blob = data->set.blobs[BLOB_SSL_ISSUERCERT_PROXY]; sslc->primary.issuercert_blob = data->set.blobs[BLOB_SSL_ISSUERCERT_PROXY];
sslc->primary.CRLfile = data->set.str[STRING_SSL_CRLFILE_PROXY]; sslc->primary.CRLfile = ssl_easy_steal(data, STRING_SSL_CRLFILE_PROXY);
sslc->primary.cert_type = data->set.str[STRING_CERT_TYPE_PROXY]; sslc->primary.cert_type = ssl_easy_steal(data, STRING_CERT_TYPE_PROXY);
sslc->primary.key = data->set.str[STRING_KEY_PROXY]; sslc->primary.key = ssl_easy_steal(data, STRING_KEY_PROXY);
sslc->primary.key_type = data->set.str[STRING_KEY_TYPE_PROXY]; sslc->primary.key_type = ssl_easy_steal(data, STRING_KEY_TYPE_PROXY);
sslc->primary.key_passwd = data->set.str[STRING_KEY_PASSWD_PROXY]; sslc->primary.key_passwd = ssl_easy_steal(data, STRING_KEY_PASSWD_PROXY);
sslc->primary.clientcert = data->set.str[STRING_CERT_PROXY]; sslc->primary.clientcert = ssl_easy_steal(data, STRING_CERT_PROXY);
sslc->primary.key_blob = data->set.blobs[BLOB_KEY_PROXY]; sslc->primary.key_blob = data->set.blobs[BLOB_KEY_PROXY];
#endif /* CURL_DISABLE_PROXY */ #endif /* CURL_DISABLE_PROXY */

View file

@ -1260,7 +1260,7 @@ static CURLcode wssl_init_ech(struct wssl_ctx *wctx,
{ {
int trying_ech_now = 0; int trying_ech_now = 0;
if(data->set.str[STRING_ECH_PUBLIC]) { if(CURL_EASY_STR(data, STRING_ECH_PUBLIC)) {
infof(data, "ECH: outername not (yet) supported" infof(data, "ECH: outername not (yet) supported"
" with wolfSSL"); " with wolfSSL");
return CURLE_SSL_CONNECT_ERROR; return CURLE_SSL_CONNECT_ERROR;
@ -1269,8 +1269,8 @@ static CURLcode wssl_init_ech(struct wssl_ctx *wctx,
infof(data, "ECH: GREASE is done by default by" infof(data, "ECH: GREASE is done by default by"
" wolfSSL: no need to ask"); " wolfSSL: no need to ask");
} }
if(data->set.tls_ech && data->set.str[STRING_ECH_CONFIG]) { if(data->set.tls_ech && CURL_EASY_STR(data, STRING_ECH_CONFIG)) {
char *b64val = data->set.str[STRING_ECH_CONFIG]; const char *b64val = CURL_EASY_STR(data, STRING_ECH_CONFIG);
word32 b64len = 0; word32 b64len = 0;
b64len = (word32)strlen(b64val); b64len = (word32)strlen(b64val);
@ -1477,7 +1477,7 @@ bool Curl_wssl_need_httpsrr(struct Curl_easy *data)
if(!CURLECH_ENABLED(data)) if(!CURLECH_ENABLED(data))
return FALSE; return FALSE;
if((data->set.tls_ech == CURLECH_GREASE) || if((data->set.tls_ech == CURLECH_GREASE) ||
data->set.str[STRING_ECH_CONFIG]) CURL_EASY_STR(data, STRING_ECH_CONFIG))
return FALSE; return FALSE;
return TRUE; return TRUE;
#else #else
@ -1580,10 +1580,11 @@ CURLcode Curl_wssl_verify_pinned(struct Curl_cfilter *cf,
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
#ifndef CURL_DISABLE_PROXY #ifndef CURL_DISABLE_PROXY
const char * const pinnedpubkey = Curl_ssl_cf_is_proxy(cf) ? const char * const pinnedpubkey = Curl_ssl_cf_is_proxy(cf) ?
data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] : CURL_EASY_STR(data, STRING_SSL_PINNEDPUBLICKEY_PROXY) :
data->set.str[STRING_SSL_PINNEDPUBLICKEY]; CURL_EASY_STR(data, STRING_SSL_PINNEDPUBLICKEY);
#else #else
const char * const pinnedpubkey = data->set.str[STRING_SSL_PINNEDPUBLICKEY]; const char * const pinnedpubkey =
CURL_EASY_STR(data, STRING_SSL_PINNEDPUBLICKEY);
(void)cf; (void)cf;
#endif #endif

View file

@ -1205,7 +1205,7 @@ CURLcode curl_easy_setopt_ccsid(CURL *curl, CURLoption tag, ...)
} }
result = curl_easy_setopt(curl, CURLOPT_POSTFIELDS, s); result = curl_easy_setopt(curl, CURLOPT_POSTFIELDS, s);
data->set.str[STRING_COPYPOSTFIELDS] = s; /* Give to library. */ data->set.str_copypostfields = s; /* Give to library. */
break; break;
default: default:

View file

@ -13,7 +13,7 @@ uint_bset
unittest unittest
</features> </features>
<name> <name>
uint_bset unit tests uint_bset and uint_hashset unit tests
</name> </name>
</client> </client>
</testcase> </testcase>

View file

@ -127,7 +127,7 @@ static CURLcode test_unit1620(const char *arg)
Curl_freeset(empty); Curl_freeset(empty);
for(i = (enum dupstring)0; i < STRING_LAST; i++) { for(i = (enum dupstring)0; i < STRING_LAST; i++) {
fail_unless(!empty->set.str[i], "Curl_free() did not set to NULL"); fail_unless(!CURL_EASY_STR(empty, i), "Curl_free() did not set to NULL");
} }
result = Curl_close(&dupe); result = Curl_close(&dupe);

View file

@ -24,10 +24,11 @@
#include "unitcheck.h" #include "unitcheck.h"
#include "urldata.h" #include "urldata.h"
#include "uint-bset.h" #include "uint-bset.h"
#include "uint-hashset.h"
#include "curl_trc.h" #include "curl_trc.h"
static void check_set(const char *name, uint32_t capacity, static void t3211_check_bset(const char *name, uint32_t capacity,
const uint32_t *s, size_t slen) const uint32_t *s, size_t slen)
{ {
struct uint32_bset bset; struct uint32_bset bset;
size_t i, j; size_t i, j;
@ -122,6 +123,103 @@ static void check_set(const char *name, uint32_t capacity,
Curl_uint32_bset_destroy(&bset); Curl_uint32_bset_destroy(&bset);
} }
static bool t3211_strcmp(const char *s1, const char *s2)
{
if(s1 && s2)
return strcmp(s1, s2);
return s1 == s2;
}
static void t3211_check_strset1(void)
{
struct u8_strset set;
char buf[128];
CURLcode result;
uint8_t i, idx;
int j;
Curl_u8_strset_init(&set);
fail_unless(!Curl_u8_strset_count(&set), "initial strset not empty");
result = Curl_u8_strset_set(&set, 0, "123");
fail_unless(!result, "add1 failed");
fail_unless(Curl_u8_strset_get(&set, 0), "get failed");
fail_unless(!t3211_strcmp("123", Curl_u8_strset_get(&set, 0)), "wrong get1");
result = Curl_u8_strset_set(&set, 0, "456");
fail_unless(!result, "add2 failed");
fail_unless(!t3211_strcmp("456", Curl_u8_strset_get(&set, 0)), "wrong get2");
Curl_u8_strset_unset(&set, 0);
fail_unless(!Curl_u8_strset_get(&set, 0), "unset failed");
/* Initial size is 4, add 4 hash collisions */
for(i = 0; i < 4; ++i) {
idx = (uint8_t)((4 * i) + 3);
curl_msnprintf(buf, sizeof(buf), "str-%d", idx);
result = Curl_u8_strset_set(&set, idx, buf);
fail_unless(!result, "loop4-add failed");
fail_unless(!t3211_strcmp(buf, Curl_u8_strset_get(&set, idx)),
"wrong get loop4");
}
/* Remove collided entry 2, check again */
idx = (uint8_t)((4 * 2) + 3);
Curl_u8_strset_unset(&set, idx);
fail_unless(!Curl_u8_strset_get(&set, idx), "unset2 failed");
for(i = 0; i < 4; ++i) {
if(i == 2)
continue;
idx = (uint8_t)((4 * i) + 3);
curl_msnprintf(buf, sizeof(buf), "str-%d", idx);
fail_unless(!t3211_strcmp(buf, Curl_u8_strset_get(&set, idx)),
"wrong get loop6");
}
/* Add entry 2 again, check */
idx = (uint8_t)((4 * 2) + 3);
curl_msnprintf(buf, sizeof(buf), "str-%d", idx);
result = Curl_u8_strset_set(&set, idx, buf);
fail_unless(!result, "re-add 2 failed");
fail_unless(!t3211_strcmp(buf, Curl_u8_strset_get(&set, idx)),
"wrong re-add 2 get");
for(i = 0; i < 4; ++i) {
idx = (uint8_t)((4 * i) + 3);
curl_msnprintf(buf, sizeof(buf), "str-%d", idx);
fail_unless(!t3211_strcmp(buf, Curl_u8_strset_get(&set, idx)),
"wrong get loop6");
}
/* Add a 5th, set grows */
fail_unless(Curl_u8_strset_count(&set) == 4, "wrong count pre add 5");
idx = (uint8_t)((4 * 4) + 3);
curl_msnprintf(buf, sizeof(buf), "str-%d", idx);
result = Curl_u8_strset_set(&set, idx, buf);
fail_unless(!result, "add4 failed");
fail_unless(!t3211_strcmp(buf, Curl_u8_strset_get(&set, idx)),
"wrong get4");
for(i = 0; i < 5; ++i) {
idx = (uint8_t)((4 * i) + 3);
curl_msnprintf(buf, sizeof(buf), "str-%d", idx);
fail_unless(!t3211_strcmp(buf, Curl_u8_strset_get(&set, idx)),
"wrong get loop5");
}
fail_unless(Curl_u8_strset_count(&set) == 5, "wrong count aftger add 5");
Curl_u8_strset_clear(&set);
/* Make a full set */
for(j = 0; j <= UINT8_MAX; ++j) {
i = (uint8_t)j;
curl_msnprintf(buf, sizeof(buf), "str-%d", i);
result = Curl_u8_strset_set(&set, i, buf);
fail_unless(!result, "loop256-add failed");
fail_unless(!t3211_strcmp(buf, Curl_u8_strset_get(&set, i)),
"wrong get loop256");
}
Curl_u8_strset_clear(&set);
fail_unless(!Curl_u8_strset_count(&set), "cleared strset not empty");
}
static CURLcode test_unit3211(const char *arg) static CURLcode test_unit3211(const char *arg)
{ {
UNITTEST_BEGIN_SIMPLE UNITTEST_BEGIN_SIMPLE
@ -142,8 +240,10 @@ static CURLcode test_unit3211(const char *arg)
120, 121, 122, 123, 124, 125, 126, 127, 120, 121, 122, 123, 124, 125, 126, 127,
}; };
check_set("s1", 100, s1, CURL_ARRAYSIZE(s1)); t3211_check_bset("s1", 100, s1, CURL_ARRAYSIZE(s1));
check_set("s2", 1000, s2, CURL_ARRAYSIZE(s2)); t3211_check_bset("s2", 1000, s2, CURL_ARRAYSIZE(s2));
t3211_check_strset1();
UNITTEST_END_SIMPLE UNITTEST_END_SIMPLE
} }