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 \
uint-bset.c \
uint-hash.c \
uint-hashset.c \
uint-spbset.c \
uint-table.c \
url.c \
@ -425,6 +426,7 @@ LIB_HFILES = \
transfer.h \
uint-bset.h \
uint-hash.h \
uint-hashset.h \
uint-spbset.h \
uint-table.h \
url.h \

View file

@ -81,8 +81,8 @@ static CURLcode cf_haproxy_date_out_set(struct Curl_cfilter *cf,
if(result)
return result;
if(data->set.str[STRING_HAPROXY_CLIENT_IP]) {
client_source_ip = data->set.str[STRING_HAPROXY_CLIENT_IP];
client_source_ip = CURL_EASY_STR(data, STRING_HAPROXY_CLIENT_IP);
if(client_source_ip) {
client_dest_ip = 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" */
/* how many port numbers to try to bind to, increasing one at a time */
int portnum = data->set.localportrange;
const char *dev = data->set.str[STRING_DEVICE];
const char *iface_input = data->set.str[STRING_INTERFACE];
const char *host_input = data->set.str[STRING_BINDHOST];
const char *dev = CURL_EASY_STR(data, STRING_DEVICE);
const char *iface_input = CURL_EASY_STR(data, STRING_INTERFACE);
const char *host_input = CURL_EASY_STR(data, STRING_BINDHOST);
const char *iface = iface_input ? iface_input : dev;
const char *host = host_input ? host_input : dev;
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
wrong thing. */
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 */
CURLcode result = cookie_output(data, data->cookies,
data->set.str[STRING_COOKIEJAR]);
CURLcode result = cookie_output(data, data->cookies, cookiejar);
if(result)
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))) {

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)
{
CURLcode result = CURLE_OK;
enum dupstring i;
enum dupblob j;
/* 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)
dst->set.mimepostp = NULL;
#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
mid-function */
memset(dst->set.str, 0, STRING_LAST * sizeof(char *));
memset(dst->set.blobs, 0, BLOB_LAST * sizeof(struct curl_blob *));
/* duplicate all strings */
for(i = (enum dupstring)0; i < STRING_LASTZEROTERMINATED; i++) {
result = Curl_setstropt(&dst->set.str[i], src->set.str[i]);
if(result)
return result;
}
result = Curl_u8_strset_copy(&dst->set.strings, &src->set.strings);
if(result)
return result;
/* duplicate all blobs */
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 */
i = STRING_COPYPOSTFIELDS;
if(src->set.str[i]) {
if(src->set.str_copypostfields) {
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
/* postfieldsize is curl_off_t, curlx_memdup() takes a size_t ... */
dst->set.str[i] = curlx_memdup(src->set.str[i],
curlx_sotouz(src->set.postfieldsize));
if(!dst->set.str[i])
dst->set.str_copypostfields =
curlx_memdup(src->set.str_copypostfields,
curlx_sotouz(src->set.postfieldsize));
if(!dst->set.str_copypostfields)
return CURLE_OUT_OF_MEMORY;
/* 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)
@ -974,6 +973,7 @@ CURL *curl_easy_duphandle(CURL *curl)
if(CURL_EAPI_ENTER(&guard, curl, easy_duphandle, NULL)) {
struct Curl_easy *data = curl;
const char *str;
outcurl = curlx_calloc(1, sizeof(struct Curl_easy));
if(!outcurl)
@ -1047,8 +1047,9 @@ CURL *curl_easy_duphandle(CURL *curl)
/* Reinitialize an SSL engine for the new handle
* note: the engine name has already been copied by dupset */
if(outcurl->set.str[STRING_SSL_ENGINE]) {
if(Curl_ssl_set_engine(outcurl, outcurl->set.str[STRING_SSL_ENGINE]))
str = CURL_EASY_STR(outcurl, STRING_SSL_ENGINE);
if(str) {
if(Curl_ssl_set_engine(outcurl, str))
goto fail;
}
@ -1057,8 +1058,9 @@ CURL *curl_easy_duphandle(CURL *curl)
outcurl->asi = Curl_altsvc_init();
if(!outcurl->asi)
goto fail;
if(outcurl->set.str[STRING_ALTSVC])
(void)Curl_altsvc_load(outcurl->asi, outcurl->set.str[STRING_ALTSVC]);
str = CURL_EASY_STR(outcurl, STRING_ALTSVC);
if(str)
(void)Curl_altsvc_load(outcurl->asi, str);
}
#endif
#ifndef CURL_DISABLE_HSTS
@ -1066,9 +1068,9 @@ CURL *curl_easy_duphandle(CURL *curl)
outcurl->hsts = Curl_hsts_init();
if(!outcurl->hsts)
goto fail;
if(outcurl->set.str[STRING_HSTS])
(void)Curl_hsts_loadfile(outcurl,
outcurl->hsts, outcurl->set.str[STRING_HSTS]);
str = CURL_EASY_STR(outcurl, STRING_HSTS);
if(str)
(void)Curl_hsts_loadfile(outcurl, outcurl->hsts, str);
(void)Curl_hsts_loadcb(outcurl, outcurl->hsts);
/* 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;
char hbuf[NI_MAXHOST];
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;
const struct Curl_addrinfo *res = 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 */
if(!ftpc->file)
result = Curl_pp_sendf(data, &ftpc->pp, "PRET %s",
data->set.str[STRING_CUSTOMREQUEST] ?
data->set.str[STRING_CUSTOMREQUEST] :
CURL_EASY_STR(data, STRING_CUSTOMREQUEST) ?
CURL_EASY_STR(data, STRING_CUSTOMREQUEST) :
(data->state.list_only ? "NLST" : "LIST"));
else if(data->state.upload)
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",
data->set.str[STRING_CUSTOMREQUEST] ?
data->set.str[STRING_CUSTOMREQUEST] :
CURL_EASY_STR(data, STRING_CUSTOMREQUEST) ?
CURL_EASY_STR(data, STRING_CUSTOMREQUEST) :
(data->state.list_only ? "NLST" : "LIST"),
lstArg ? " " : "",
lstArglen, lstArg ? lstArg : "");
@ -2956,7 +2956,7 @@ static CURLcode ftp_state_user_resp(struct Curl_easy *data,
result = ftp_state_loggedin(data, ftpc);
}
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) {
failf(data, "ACCT requested but none available");
result = CURLE_LOGIN_DENIED;
@ -2977,7 +2977,7 @@ static CURLcode ftp_state_user_resp(struct Curl_easy *data,
530 User ... access denied
(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) {
/* Ok, USER failed. Let's try the supplied command. */
if(ftp_has_ctrl(alt)) {
@ -4436,16 +4436,16 @@ static CURLcode ftp_setup_connection(struct Curl_easy *data,
return CURLE_OUT_OF_MEMORY;
/* clone connection related data that is FTP specific */
if(data->set.str[STRING_FTP_ACCOUNT]) {
ftpc->account = curlx_strdup(data->set.str[STRING_FTP_ACCOUNT]);
if(CURL_EASY_STR(data, STRING_FTP_ACCOUNT)) {
ftpc->account = curlx_strdup(CURL_EASY_STR(data, STRING_FTP_ACCOUNT));
if(!ftpc->account) {
Curl_conn_meta_remove(conn, CURL_META_FTP_CONN);
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 =
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) {
curlx_safefree(ftpc->account);
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;
case CURLINFO_EFFECTIVE_METHOD: {
const char *m = data->set.str[STRING_CUSTOMREQUEST];
const char *m = CURL_EASY_STR(data, STRING_CUSTOMREQUEST);
if(!m) {
if(data->set.opt_no_body)
m = "HEAD";
@ -149,7 +149,7 @@ static CURLcode getinfo_char(struct Curl_easy *data, CURLINFO info,
break;
case CURLINFO_RTSP_SESSION_ID:
#ifndef CURL_DISABLE_RTSP
*param_charp = data->set.str[STRING_RTSP_SESSION_ID];
*param_charp = CURL_EASY_STR(data, STRING_RTSP_SESSION_ID);
#else
*param_charp = NULL;
#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)
{
const char *req = data->set.str[STRING_CUSTOMREQUEST];
const char *req = CURL_EASY_STR(data, STRING_CUSTOMREQUEST);
if((req || data->state.httpreq != HTTPREQ_GET) &&
(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);
infof(data, "Issue another request to this URL: '%s'", follow_url);
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;
infof(data, "Drop custom request method for next request");
}
@ -1991,9 +1991,9 @@ void Curl_http_method(struct Curl_easy *data,
httpreq = HTTPREQ_PUT;
/* Now set the 'request' pointer to the proper request string */
if(data->set.str[STRING_CUSTOMREQUEST] &&
!data->state.http_ignorecustom) {
request = data->set.str[STRING_CUSTOMREQUEST];
if(!data->state.http_ignorecustom &&
CURL_EASY_STR(data, STRING_CUSTOMREQUEST)) {
request = CURL_EASY_STR(data, STRING_CUSTOMREQUEST);
}
else {
if(data->req.no_body)
@ -2124,8 +2124,8 @@ static CURLcode http_target(struct Curl_easy *data,
struct connectdata *conn = data->conn;
#endif
if(data->set.str[STRING_TARGET]) {
path = data->set.str[STRING_TARGET];
if(CURL_EASY_STR(data, STRING_TARGET)) {
path = CURL_EASY_STR(data, STRING_TARGET);
query = NULL;
}
@ -2194,8 +2194,8 @@ static CURLcode http_target(struct Curl_easy *data,
curl_url_cleanup(h);
/* target or URL */
result = curlx_dyn_add(r, data->set.str[STRING_TARGET] ?
data->set.str[STRING_TARGET] : url);
result = curlx_dyn_add(r, CURL_EASY_STR(data, STRING_TARGET) ?
CURL_EASY_STR(data, STRING_TARGET) : url);
curlx_free(url);
if(result)
return result;
@ -2576,12 +2576,12 @@ static CURLcode http_cookies(struct Curl_easy *data,
struct dynbuf *r)
{
CURLcode result = CURLE_OK;
char *addcookies = NULL;
const char *addcookies = NULL;
bool linecap = FALSE;
if(data->set.str[STRING_COOKIE] &&
if(CURL_EASY_STR(data, STRING_COOKIE) &&
!Curl_checkheaders(data, STRCONST("Cookie")) &&
Curl_auth_allowed_to_host(data))
addcookies = data->set.str[STRING_COOKIE];
addcookies = CURL_EASY_STR(data, STRING_COOKIE);
if(data->cookies || addcookies) {
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);
break;
case H1_HD_USER_AGENT:
if(!Curl_checkheaders(data, STRCONST("User-Agent"))) {
if(data->set.str[STRING_USERAGENT] &&
*data->set.str[STRING_USERAGENT])
result = curlx_dyn_addf(req, "User-Agent: %s\r\n",
data->set.str[STRING_USERAGENT]);
}
case H1_HD_USER_AGENT: {
const char *ua = CURL_EASY_STR(data, STRING_USERAGENT);
if(ua && *ua && !Curl_checkheaders(data, STRCONST("User-Agent")))
result = curlx_dyn_addf(req, "User-Agent: %s\r\n", ua);
break;
}
case H1_HD_ACCEPT:
if(!Curl_checkheaders(data, STRCONST("Accept")))
@ -2981,12 +2979,12 @@ static CURLcode http_add_hd(struct Curl_easy *data,
#endif
break;
case H1_HD_ACCEPT_ENCODING:
if(!Curl_checkheaders(data, STRCONST("Accept-Encoding")) &&
data->set.str[STRING_ENCODING])
result = curlx_dyn_addf(req, "Accept-Encoding: %s\r\n",
data->set.str[STRING_ENCODING]);
case H1_HD_ACCEPT_ENCODING: {
const char *enc = CURL_EASY_STR(data, STRING_ENCODING);
if(enc && !Curl_checkheaders(data, STRCONST("Accept-Encoding")))
result = curlx_dyn_addf(req, "Accept-Encoding: %s\r\n", enc);
break;
}
case H1_HD_REFERER:
if(Curl_bufref_ptr(&data->state.referer) &&
@ -3317,7 +3315,7 @@ static CURLcode http_header_c(struct Curl_easy *data,
}
} 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;
if(v) {
/*

View file

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

View file

@ -816,7 +816,7 @@ static CURLcode parse_sigv4_params(struct Curl_easy *data,
struct Curl_str *region,
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)
line = "aws:amz";

View file

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

View file

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

View file

@ -1923,7 +1923,7 @@ static CURLcode imap_parse_custom_request(struct Curl_easy *data,
struct IMAP *imap)
{
CURLcode result = CURLE_OK;
const char *custom = data->set.str[STRING_CUSTOMREQUEST];
const char *custom = CURL_EASY_STR(data, STRING_CUSTOMREQUEST);
if(custom) {
/* 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;
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)
return CURLE_FAILED_INIT;

View file

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

View file

@ -336,11 +336,11 @@ static CURLcode rtsp_setup_request(struct Curl_easy *data,
CURLcode result = CURLE_OK;
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 */
if(data->set.str[STRING_RTSP_STREAM_URI])
b->stream_uri = data->set.str[STRING_RTSP_STREAM_URI];
if(CURL_EASY_STR(data, STRING_RTSP_STREAM_URI))
b->stream_uri = CURL_EASY_STR(data, STRING_RTSP_STREAM_URI);
else
b->stream_uri = "*";
@ -348,10 +348,10 @@ static CURLcode rtsp_setup_request(struct Curl_easy *data,
b->transport = Curl_checkheaders(data, STRCONST("Transport"));
if(rtspreq == RTSPREQ_SETUP && !b->transport) {
/* New Transport: setting? */
if(data->set.str[STRING_RTSP_TRANSPORT]) {
result = rtsp_header_alloc("Transport",
data->set.str[STRING_RTSP_TRANSPORT],
&b->transport);
if(CURL_EASY_STR(data, STRING_RTSP_TRANSPORT)) {
result = rtsp_header_alloc(
"Transport", CURL_EASY_STR(data, STRING_RTSP_TRANSPORT),
&b->transport);
if(result)
return result;
b->transport_alloc = TRUE;
@ -371,9 +371,9 @@ static CURLcode rtsp_setup_request(struct Curl_easy *data,
/* Accept-Encoding header */
if(!Curl_checkheaders(data, STRCONST("Accept-Encoding")) &&
data->set.str[STRING_ENCODING]) {
CURL_EASY_STR(data, STRING_ENCODING)) {
result = rtsp_header_alloc("Accept-Encoding",
data->set.str[STRING_ENCODING],
CURL_EASY_STR(data, STRING_ENCODING),
&b->accept_encoding);
if(result)
return result;
@ -430,6 +430,7 @@ static CURLcode rtsp_do(struct Curl_easy *data, bool *done)
{
CURLcode result = CURLE_OK;
const unsigned char rtspreq = data->set.rtspreq;
const char *str;
struct RTSP *rtsp = Curl_meta_get(data, CURL_META_RTSP_EASY);
struct dynbuf req_buffer;
struct rtsp_blocks block;
@ -506,12 +507,11 @@ static CURLcode rtsp_do(struct Curl_easy *data, bool *done)
block.range ? block.range : "",
block.referrer ? block.referrer : "");
if(!result &&
!Curl_checkheaders(data, STRCONST("User-Agent")) &&
data->set.str[STRING_USERAGENT] && *data->set.str[STRING_USERAGENT])
str = CURL_EASY_STR(data, STRING_USERAGENT);
if(!result && str && *str &&
!Curl_checkheaders(data, STRCONST("User-Agent")))
result = curlx_dyn_addf(&req_buffer,
"User-Agent: %s\r\n",
data->set.str[STRING_USERAGENT]);
"User-Agent: %s\r\n", str);
if(!result)
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;
}
else if(checkprefix("Session:", header)) {
const char *start, *end;
const char *start, *end, *str;
size_t idlen;
/* Find the first non-space letter */
@ -999,24 +999,24 @@ CURLcode Curl_rtsp_parseheader(struct Curl_easy *data, const char *header)
end++;
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(strlen(data->set.str[STRING_RTSP_SESSION_ID]) != idlen ||
strncmp(start, data->set.str[STRING_RTSP_SESSION_ID], idlen)) {
if(strlen(str) != idlen ||
strncmp(start, str, idlen)) {
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;
}
}
else {
/* If the Session ID is not set, and we find it in a response, then set
* it.
*/
/* Copy the id substring into a new buffer */
data->set.str[STRING_RTSP_SESSION_ID] = curlx_memdup0(start, idlen);
if(!data->set.str[STRING_RTSP_SESSION_ID])
* Copy the id substring into a new buffer */
void *mem = curlx_memdup0(start, idlen);
if(!mem ||
CURL_EASY_STR_SETN(data, STRING_RTSP_SESSION_ID, mem))
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;
}
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
copy of `s'. Return CURLE_OK or CURLE_OUT_OF_MEMORY. */
DEBUGASSERT((unsigned)id <= UINT8_MAX);
if(s && (strlen(s) > CURL_MAX_INPUT_LENGTH))
return CURLE_BAD_FUNCTION_ARGUMENT;
curlx_safefree(*charp);
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;
return CURL_EASY_STR_SET(data, (uint8_t)id, s);
}
CURLcode Curl_setblobopt(struct curl_blob **blobp,
@ -160,34 +151,34 @@ static CURLcode setstropt_userpwd(const char *option, char **userp,
return CURLE_OK;
}
static CURLcode setstropt_interface(char *option, char **devp,
char **ifacep, char **hostp)
static CURLcode setstropt_interface(struct Curl_easy *data, char *option)
{
char *dev = NULL;
char *iface = NULL;
char *host = NULL;
CURLcode result;
DEBUGASSERT(devp);
DEBUGASSERT(ifacep);
DEBUGASSERT(hostp);
if(option) {
/* Parse the interface details if set, otherwise clear them all */
result = Curl_parse_interface(option, &dev, &iface, &host);
if(result)
return result;
}
curlx_free(*devp);
*devp = dev;
curlx_free(*ifacep);
*ifacep = iface;
curlx_free(*hostp);
*hostp = host;
return CURLE_OK;
result = CURL_EASY_STR_SETN(data, STRING_DEVICE, dev);
dev = NULL;
if(!result) {
result = CURL_EASY_STR_SETN(data, STRING_INTERFACE, iface);
iface = NULL;
}
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
@ -952,7 +943,7 @@ static CURLcode setopt_long_ssl(struct Curl_easy *data, CURLoption option,
case CURLOPT_SSL_ENABLE_NPN:
break;
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);
break;
default:
@ -1211,9 +1202,8 @@ static CURLcode setopt_long_misc(struct Curl_easy *data, CURLoption option,
case CURLOPT_POSTFIELDSIZE:
if(arg < -1)
return CURLE_BAD_FUNCTION_ARGUMENT;
if(s->postfieldsize < arg &&
s->postfields == s->str[STRING_COPYPOSTFIELDS]) {
curlx_safefree(s->str[STRING_COPYPOSTFIELDS]);
if(s->postfieldsize < arg && s->str_copypostfields) {
curlx_safefree(s->str_copypostfields);
s->postfields = NULL;
}
s->postfieldsize = arg;
@ -1458,7 +1448,7 @@ static CURLcode setopt_pointers(struct Curl_easy *data, CURLoption option,
* pass CURLU to set 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 *);
break;
#ifndef CURL_DISABLE_HTTP
@ -1604,13 +1594,14 @@ static CURLcode cookiefile(struct Curl_easy *data, const char *ptr)
#ifndef CURL_DISABLE_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? */
!strcmp(data->set.str[STRING_PROXY], proxy))
!strcmp(str, proxy))
return CURLE_OK; /* same one as before */
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,
@ -1629,15 +1620,21 @@ static CURLcode setopt_cptr_proxy(struct Curl_easy *data, CURLoption option,
/* URL decode the components */
if(!result) {
curlx_safefree(s->str[STRING_PROXYUSERNAME]);
curlx_safefree(s->str[STRING_PROXYPASSWORD]);
if(u)
result = Curl_urldecode(u, 0, &s->str[STRING_PROXYUSERNAME], NULL,
REJECT_ZERO);
char *str = NULL;
CURL_EASY_STR_CLEAR(data, STRING_PROXYUSERNAME);
CURL_EASY_STR_CLEAR(data, STRING_PROXYPASSWORD);
if(u) {
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_strzero(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
*/
return Curl_setstropt(&s->str[STRING_PROXYUSERNAME], ptr);
return Curl_setstropt(data, STRING_PROXYUSERNAME, ptr);
case CURLOPT_PROXYPASSWORD:
/*
* 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:
/*
* proxy exception list
*/
return Curl_setstropt(&s->str[STRING_NOPROXY], ptr);
return Curl_setstropt(data, STRING_NOPROXY, ptr);
case CURLOPT_PROXY_SSLCERT:
/*
* 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:
/*
* 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:
/*
* 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:
/*
* 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:
/*
* 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:
if(Curl_ssl_supports(data, SSLSUPP_CIPHER_LIST)) {
/* 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
return CURLE_NOT_BUILT_IN;
case CURLOPT_PROXY_TLS13_CIPHERS:
if(Curl_ssl_supports(data, SSLSUPP_TLS13_CIPHERSUITES))
/* 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
return CURLE_NOT_BUILT_IN;
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
* 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_PROXY_SERVICE_NAME:
/*
* 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:
/*
* 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
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
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
*/
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 */
s->haproxyprotocol = !!s->str[STRING_HAPROXY_CLIENT_IP];
s->haproxyprotocol = !!CURL_EASY_STR(data, STRING_HAPROXY_CLIENT_IP);
break;
case CURLOPT_PROXY_CAINFO:
/*
* Set CA info SSL connection for proxy. Specify filename of the
* CA certificate
*/
result = Curl_setstropt(&s->str[STRING_SSL_CAFILE_PROXY], ptr);
s->proxy_ssl.custom_cafile = !!s->str[STRING_SSL_CAFILE_PROXY];
result = Curl_setstropt(data, STRING_SSL_CAFILE_PROXY, ptr);
s->proxy_ssl.custom_cafile =
!!CURL_EASY_STR(data, STRING_SSL_CAFILE_PROXY);
return result;
case CURLOPT_PROXY_CRLFILE:
/*
@ -1758,14 +1756,14 @@ static CURLcode setopt_cptr_proxy(struct Curl_easy *data, CURLoption option,
* CRL to check certificates revocation
*/
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;
case CURLOPT_PROXY_ISSUERCERT:
/*
* Set Issuer certificate file to check certificates issuer
*/
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;
case CURLOPT_PROXY_CAPATH:
/*
@ -1775,8 +1773,9 @@ static CURLcode setopt_cptr_proxy(struct Curl_easy *data, CURLoption option,
#ifdef USE_SSL
if(Curl_ssl_supports(data, SSLSUPP_CA_PATH)) {
/* This does not work on Windows. */
result = Curl_setstropt(&s->str[STRING_SSL_CAPATH_PROXY], ptr);
s->proxy_ssl.custom_capath = !!s->str[STRING_SSL_CAPATH_PROXY];
result = Curl_setstropt(data, STRING_SSL_CAPATH_PROXY, ptr);
s->proxy_ssl.custom_capath =
!!CURL_EASY_STR(data, STRING_SSL_CAPATH_PROXY);
return result;
}
#endif
@ -1799,8 +1798,16 @@ static CURLcode setopt_copypostfields(const char *ptr, struct UserDefined *s)
CURLcode result = CURLE_OK;
if(s->postfieldsize < -1)
return CURLE_BAD_FUNCTION_ARGUMENT;
if(!ptr || s->postfieldsize == -1)
result = Curl_setstropt(&s->str[STRING_COPYPOSTFIELDS], ptr);
if(!ptr || s->postfieldsize == -1) {
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 {
size_t pflen = curlx_sotouz_range(s->postfieldsize, 0, SIZE_MAX);
if(pflen == SIZE_MAX)
@ -1813,13 +1820,13 @@ static CURLcode setopt_copypostfields(const char *ptr, struct UserDefined *s)
if(!p)
return CURLE_OUT_OF_MEMORY;
else {
curlx_free(s->str[STRING_COPYPOSTFIELDS]);
s->str[STRING_COPYPOSTFIELDS] = p;
curlx_free(s->str_copypostfields);
s->str_copypostfields = p;
}
}
}
s->postfields = s->str[STRING_COPYPOSTFIELDS];
s->postfields = s->str_copypostfields;
s->method = HTTPREQ_POST;
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)) {
if(!s->tls_ech)
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)) {
if(!s->tls_ech)
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
result = CURLE_BAD_FUNCTION_ARGUMENT;
@ -1870,22 +1877,21 @@ static CURLcode setopt_cptr_ssl(struct Curl_easy *data, CURLoption option,
char *ptr)
{
CURLcode result = CURLE_OK;
struct UserDefined *s = &data->set;
switch(option) {
case CURLOPT_KEYPASSWD:
/*
* 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;
#ifdef USE_SSL
case CURLOPT_CAINFO:
/*
* Set CA info for SSL connection. Specify filename of the CA certificate
*/
result = Curl_setstropt(&s->str[STRING_SSL_CAFILE], ptr);
s->ssl.custom_cafile = !!s->str[STRING_SSL_CAFILE];
result = Curl_setstropt(data, STRING_SSL_CAFILE, ptr);
data->set.ssl.custom_cafile = !!CURL_EASY_STR(data, STRING_SSL_CAFILE);
return result;
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)) {
/* This does not work on Windows. */
result = Curl_setstropt(&s->str[STRING_SSL_CAPATH], ptr);
s->ssl.custom_capath = !!s->str[STRING_SSL_CAPATH];
result = Curl_setstropt(data, STRING_SSL_CAPATH, ptr);
data->set.ssl.custom_capath = !!CURL_EASY_STR(data, STRING_SSL_CAPATH);
return result;
}
return CURLE_NOT_BUILT_IN;
@ -1905,18 +1911,18 @@ static CURLcode setopt_cptr_ssl(struct Curl_easy *data, CURLoption option,
* to check certificates revocation
*/
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;
case CURLOPT_SSL_CIPHER_LIST:
if(Curl_ssl_supports(data, SSLSUPP_CIPHER_LIST))
/* 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
return CURLE_NOT_BUILT_IN;
case CURLOPT_TLS13_CIPHERS:
if(Curl_ssl_supports(data, SSLSUPP_TLS13_CIPHERSUITES))
/* 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
return CURLE_NOT_BUILT_IN;
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
*/
if(Curl_ssl_supports(data, SSLSUPP_SSL_CTX)) {
s->ssl.fsslctxp = ptr;
data->set.ssl.fsslctxp = ptr;
break;
}
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
*/
return Curl_setstropt(&s->str[STRING_CERT], ptr);
return Curl_setstropt(data, STRING_CERT, ptr);
case CURLOPT_SSLCERTTYPE:
/*
* 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:
/*
* 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:
/*
* 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:
/*
* String that holds the SSL crypto engine.
*/
if(ptr && ptr[0]) {
result = Curl_setstropt(&s->str[STRING_SSL_ENGINE], ptr);
result = Curl_setstropt(data, STRING_SSL_ENGINE, ptr);
if(!result) {
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
*/
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;
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.
*/
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;
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.
*/
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;
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.
*/
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;
case CURLOPT_ECH:
return setopt_ech(data, ptr);
@ -2023,7 +2029,7 @@ static CURLcode setopt_cptr_http_mqtt(struct Curl_easy *data,
*/
s->postfields = ptr;
/* Release old copied data. */
curlx_safefree(s->str[STRING_COPYPOSTFIELDS]);
curlx_safefree(s->str_copypostfields);
s->method = HTTPREQ_POST;
break;
@ -2043,15 +2049,13 @@ static CURLcode setopt_cptr_http_mqtt(struct Curl_easy *data,
*/
if(ptr && !*ptr) {
ptr = Curl_get_content_encodings();
if(ptr) {
curlx_free(s->str[STRING_ENCODING]);
s->str[STRING_ENCODING] = ptr;
}
if(ptr)
result = CURL_EASY_STR_SETN(data, STRING_ENCODING, ptr);
else
result = CURLE_OUT_OF_MEMORY;
return result;
}
return Curl_setstropt(&s->str[STRING_ENCODING], ptr);
return Curl_setstropt(data, STRING_ENCODING, ptr);
#ifndef CURL_DISABLE_AWS
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
* 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.
*/
if(s->str[STRING_AWS_SIGV4])
if(CURL_EASY_STR(data, STRING_AWS_SIGV4))
s->httpauth = CURLAUTH_AWS_SIGV4;
break;
#endif
#ifndef CURL_DISABLE_HTTPSIG
case CURLOPT_HTTPSIG_KEY:
result = Curl_setstropt(&s->str[STRING_HTTPSIG_KEY], ptr);
result = Curl_setstropt(data, STRING_HTTPSIG_KEY, ptr);
break;
case CURLOPT_HTTPSIG_KEYID:
result = Curl_setstropt(&s->str[STRING_HTTPSIG_KEYID], ptr);
result = Curl_setstropt(data, STRING_HTTPSIG_KEYID, ptr);
break;
case CURLOPT_HTTPSIG_HEADERS:
result = Curl_setstropt(&s->str[STRING_HTTPSIG_HEADERS], ptr);
result = Curl_setstropt(data, STRING_HTTPSIG_HEADERS, ptr);
break;
#endif
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.
*/
Curl_bufref_free(&data->state.referer);
result = Curl_setstropt(&s->str[STRING_SET_REFERER], ptr);
result = Curl_setstropt(data, STRING_SET_REFERER, ptr);
break;
case CURLOPT_USERAGENT:
/*
* 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
case CURLOPT_COOKIE:
/*
* 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:
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.
*/
result = Curl_setstropt(&s->str[STRING_COOKIEJAR], ptr);
result = Curl_setstropt(data, STRING_COOKIEJAR, ptr);
if(!result) {
/*
* 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
*/
return Curl_setstropt(&s->str[STRING_SSH_PUBLIC_KEY], ptr);
return Curl_setstropt(data, STRING_SSH_PUBLIC_KEY, ptr);
case CURLOPT_SSH_PRIVATE_KEYFILE:
/*
* 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:
/*
* 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
* 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:
/*
* Option to allow for the SHA256 of the host public key to be checked
* 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:
/*
* 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
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
*/
result = Curl_setstropt(&s->str[STRING_FTPPORT], ptr);
s->ftp_use_port = !!(s->str[STRING_FTPPORT]);
result = Curl_setstropt(data, STRING_FTPPORT, ptr);
s->ftp_use_port = !!CURL_EASY_STR(data, STRING_FTPPORT);
break;
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:
return Curl_setstropt(&s->str[STRING_FTP_ALTERNATIVE_TO_USER], ptr);
return Curl_setstropt(data, STRING_FTP_ALTERNATIVE_TO_USER, ptr);
case CURLOPT_KRBLEVEL:
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,
char *ptr)
{
struct UserDefined *s = &data->set;
switch(option) {
case CURLOPT_INTERFACE:
/*
* Set what interface or address/hostname to bind the socket to when
* performing an operation and thus what from-IP your connection will use.
*/
return setstropt_interface(ptr,
&s->str[STRING_DEVICE],
&s->str[STRING_INTERFACE],
&s->str[STRING_BINDHOST]);
return setstropt_interface(data, ptr);
#ifdef USE_RESOLV_ARES
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:
return Curl_setstropt(&s->str[STRING_DNS_INTERFACE], ptr);
return Curl_setstropt(data, STRING_DNS_INTERFACE, ptr);
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:
return Curl_setstropt(&s->str[STRING_DNS_LOCAL_IP6], ptr);
return Curl_setstropt(data, STRING_DNS_LOCAL_IP6, ptr);
#endif
#ifdef USE_UNIX_SOCKETS
case CURLOPT_UNIX_SOCKET_PATH:
s->abstract_unix_socket = FALSE;
return Curl_setstropt(&s->str[STRING_UNIX_SOCKET_PATH], ptr);
data->set.abstract_unix_socket = FALSE;
return Curl_setstropt(data, STRING_UNIX_SOCKET_PATH, ptr);
case CURLOPT_ABSTRACT_UNIX_SOCKET:
s->abstract_unix_socket = TRUE;
return Curl_setstropt(&s->str[STRING_UNIX_SOCKET_PATH], ptr);
data->set.abstract_unix_socket = TRUE;
return Curl_setstropt(data, STRING_UNIX_SOCKET_PATH, ptr);
#endif
#ifndef CURL_DISABLE_DOH
case CURLOPT_DOH_URL:
{
CURLcode result = Curl_setstropt(&s->str[STRING_DOH], ptr);
s->doh = !!(s->str[STRING_DOH]);
CURLcode result = Curl_setstropt(data, STRING_DOH, ptr);
data->set.doh = !!CURL_EASY_STR(data, STRING_DOH);
return result;
}
#endif
@ -2280,19 +2281,19 @@ static CURLcode setopt_cptr_misc(struct Curl_easy *data, CURLoption option,
switch(option) {
case CURLOPT_REQUEST_TARGET:
return Curl_setstropt(&s->str[STRING_TARGET], ptr);
return Curl_setstropt(data, STRING_TARGET, ptr);
#ifndef CURL_DISABLE_NETRC
case CURLOPT_NETRC_FILE:
return Curl_setstropt(&s->str[STRING_NETRC_FILE], ptr);
return Curl_setstropt(data, STRING_NETRC_FILE, ptr);
#endif
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
were using the already set type and this changes the actual request
keyword */
case CURLOPT_SERVICE_NAME:
return Curl_setstropt(&s->str[STRING_SERVICE_NAME], ptr);
return Curl_setstropt(data, STRING_SERVICE_NAME, ptr);
case CURLOPT_HEADERDATA:
s->writeheader = ptr;
@ -2334,27 +2335,40 @@ static CURLcode setopt_cptr_misc(struct Curl_easy *data, CURLoption option,
s->errorbuffer = ptr;
break;
case CURLOPT_URL:
result = Curl_setstropt(&s->str[STRING_SET_URL], ptr);
Curl_bufref_set(&data->state.url, s->str[STRING_SET_URL], 0, NULL);
result = Curl_setstropt(data, STRING_SET_URL, ptr);
Curl_bufref_set(&data->state.url,
CURL_EASY_STR(data, STRING_SET_URL), 0, NULL);
break;
case CURLOPT_USERPWD:
return setstropt_userpwd(ptr, &s->str[STRING_USERNAME],
&s->str[STRING_PASSWORD]);
case CURLOPT_USERPWD: {
char *u = NULL, *p = NULL;
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:
return Curl_setstropt(&s->str[STRING_USERNAME], ptr);
return Curl_setstropt(data, STRING_USERNAME, ptr);
case CURLOPT_PASSWORD:
return Curl_setstropt(&s->str[STRING_PASSWORD], ptr);
return Curl_setstropt(data, STRING_PASSWORD, ptr);
case CURLOPT_LOGIN_OPTIONS:
return Curl_setstropt(&s->str[STRING_OPTIONS], ptr);
return Curl_setstropt(data, STRING_OPTIONS, ptr);
case CURLOPT_XOAUTH2_BEARER:
return Curl_setstropt(&s->str[STRING_BEARER], ptr);
return Curl_setstropt(data, STRING_BEARER, ptr);
case CURLOPT_RANGE:
return Curl_setstropt(&s->str[STRING_SET_RANGE], ptr);
return Curl_setstropt(data, STRING_SET_RANGE, ptr);
case CURLOPT_PRIVATE:
s->private_data = ptr;
break;
@ -2382,25 +2396,25 @@ static CURLcode setopt_cptr_misc(struct Curl_easy *data, CURLoption option,
break;
case CURLOPT_DEFAULT_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
case CURLOPT_MAIL_FROM:
/* 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:
/* Set the SMTP auth originator */
return Curl_setstropt(&s->str[STRING_MAIL_AUTH], ptr);
return Curl_setstropt(data, STRING_MAIL_AUTH, ptr);
#endif
case CURLOPT_SASL_AUTHZID:
/* 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
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:
return Curl_setstropt(&s->str[STRING_RTSP_STREAM_URI], ptr);
return Curl_setstropt(data, STRING_RTSP_STREAM_URI, ptr);
case CURLOPT_RTSP_TRANSPORT:
return Curl_setstropt(&s->str[STRING_RTSP_TRANSPORT], ptr);
return Curl_setstropt(data, STRING_RTSP_TRANSPORT, ptr);
case CURLOPT_INTERLEAVEDATA:
s->rtp_out = ptr;
break;
@ -2427,7 +2441,7 @@ static CURLcode setopt_cptr_misc(struct Curl_easy *data, CURLoption option,
return CURLE_OUT_OF_MEMORY;
}
if(ptr) {
result = Curl_setstropt(&s->str[STRING_HSTS], ptr);
result = Curl_setstropt(data, STRING_HSTS, ptr);
if(result)
return result;
/* 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)
return CURLE_OUT_OF_MEMORY;
}
result = Curl_setstropt(&s->str[STRING_ALTSVC], ptr);
result = Curl_setstropt(data, STRING_ALTSVC, ptr);
if(result)
break;
if(ptr)
@ -2719,10 +2733,9 @@ static CURLcode setopt_offt(struct Curl_easy *data, CURLoption option,
if(offt < -1)
return CURLE_BAD_FUNCTION_ARGUMENT;
if(s->postfieldsize < offt &&
s->postfields == s->str[STRING_COPYPOSTFIELDS]) {
if(s->postfieldsize < offt && s->str_copypostfields) {
/* Previous CURLOPT_COPYPOSTFIELDS is no longer valid. */
curlx_safefree(s->str[STRING_COPYPOSTFIELDS]);
curlx_safefree(s->str_copypostfields);
s->postfields = NULL;
}
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
#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,
const struct curl_blob *blob) WARN_UNUSED_RESULT;
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)
{
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 */
if(custom)
@ -912,6 +912,7 @@ static CURLcode smtp_perform_mail(struct Curl_easy *data,
char *from = NULL;
char *auth = NULL;
char *size = NULL;
const char *str;
CURLcode result = CURLE_OK;
/* 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;
/* Calculate the FROM parameter */
if(data->set.str[STRING_MAIL_FROM]) {
str = CURL_EASY_STR(data, STRING_MAIL_FROM);
if(str) {
char *address = NULL;
struct hostname host = { NULL, NULL, NULL, NULL };
const char *suffix = "";
/* Parse the FROM mailbox into the local address and hostname parts,
converting the hostname to an IDN A-label if necessary */
result = smtp_parse_address(data, data->set.str[STRING_MAIL_FROM],
&address, &host, &suffix);
result = smtp_parse_address(data, str, &address, &host, &suffix);
if(result)
goto out;
@ -962,16 +963,16 @@ static CURLcode smtp_perform_mail(struct Curl_easy *data,
}
/* Calculate the optional AUTH parameter */
if(data->set.str[STRING_MAIL_AUTH] && smtpc->sasl.authused) {
if(data->set.str[STRING_MAIL_AUTH][0] != '\0') {
str = CURL_EASY_STR(data, STRING_MAIL_AUTH);
if(str && smtpc->sasl.authused) {
if(str[0] != '\0') {
char *address = NULL;
struct hostname host = { NULL, NULL, NULL, NULL };
const char *suffix = "";
/* Parse the AUTH mailbox into the local address and hostname parts,
converting the hostname to an IDN A-label if necessary */
result = smtp_parse_address(data, data->set.str[STRING_MAIL_AUTH],
&address, &host, &suffix);
result = smtp_parse_address(data, str, &address, &host, &suffix);
if(result)
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. */
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 */
failf(data, "No URL set");
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
is allowed to be changed by the user between transfers */
if(data->set.uh) {
char *url = NULL;
CURLUcode uc;
curlx_free(data->set.str[STRING_SET_URL]);
uc = curl_url_get(data->set.uh,
CURLUPART_URL, &data->set.str[STRING_SET_URL], 0);
uc = curl_url_get(data->set.uh, CURLUPART_URL, &url, 0);
if(uc) {
/* clear the pointer to not point to freed memory anymore */
Curl_bufref_set(&data->state.url, NULL, 0, NULL);
failf(data, "No URL set");
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) {
/* we cannot */
@ -505,9 +508,9 @@ CURLcode Curl_pretransfer(struct Curl_easy *data)
Curl_data_priority_clear_state(data);
if(data->set.http_auto_referer)
Curl_bufref_free(&data->state.referer);
if(data->set.str[STRING_SET_REFERER])
Curl_bufref_set(&data->state.referer, data->set.str[STRING_SET_REFERER],
0, NULL);
if(CURL_EASY_STR(data, STRING_SET_REFERER))
Curl_bufref_set(&data->state.referer,
CURL_EASY_STR(data, STRING_SET_REFERER), 0, NULL);
else
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)
{
/* Free all dynamic strings stored in the data->set substructure. */
enum dupstring i;
enum dupblob j;
for(i = (enum dupstring)0; i < STRING_LAST; i++) {
if(i == STRING_PASSWORD ||
i == STRING_KEY_PASSWD ||
CURL_EASY_STR_CLEAR0(data, STRING_PASSWORD);
CURL_EASY_STR_CLEAR0(data, STRING_KEY_PASSWD);
CURL_EASY_STR_CLEAR0(data, STRING_BEARER);
#ifndef CURL_DISABLE_PROXY
i == STRING_PROXYPASSWORD ||
i == STRING_KEY_PASSWD_PROXY ||
CURL_EASY_STR_CLEAR0(data, STRING_PROXYPASSWORD);
CURL_EASY_STR_CLEAR0(data, STRING_KEY_PASSWD_PROXY);
#endif
i == STRING_BEARER) {
curlx_strzero(data->set.str[i]);
}
curlx_safefree(data->set.str[i]);
}
Curl_u8_strset_clear(&data->set.strings);
curlx_safefree(data->set.str_copypostfields);
for(j = (enum dupblob)0; j < BLOB_LAST; j++) {
curlx_safefree(data->set.blobs[j]);
@ -257,11 +253,11 @@ CURLcode Curl_close(struct Curl_easy **datap)
curlx_dyn_free(&data->state.headerb);
Curl_flush_cookies(data, TRUE);
#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);
#endif
#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)
Curl_hsts_cleanup(&data->hsts);
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->err = stderr; /* default stderr to stderr */
Curl_u8_strset_init(&data->set.strings);
#if defined(__clang__) && __clang_major__ >= 16
#pragma clang diagnostic push
#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_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);
Curl_bufref_init(&data->state.url);
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 */
/* Store the local bind parameters that will be used for this connection */
if(data->set.str[STRING_DEVICE]) {
conn->localdev = curlx_strdup(data->set.str[STRING_DEVICE]);
if(CURL_EASY_STR(data, STRING_DEVICE)) {
conn->localdev = curlx_strdup(CURL_EASY_STR(data, STRING_DEVICE));
if(!conn->localdev)
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,
data->state.origin->hostname,
Curl_creds_user(ncreds_in),
data->set.str[STRING_NETRC_FILE],
CURL_EASY_STR(data, STRING_NETRC_FILE),
&ncreds_out);
DEBUGASSERT(!ret || !ncreds_out);
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))) {
infof(data, "Could not find host %s in the %s file; using defaults",
data->state.origin->hostname,
(data->set.str[STRING_NETRC_FILE] ?
data->set.str[STRING_NETRC_FILE] : ".netrc"));
(CURL_EASY_STR(data, STRING_NETRC_FILE) ?
CURL_EASY_STR(data, STRING_NETRC_FILE) : ".netrc"));
}
else if(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;
CURLcode result = CURLE_OK;
if((data->set.str[STRING_USERNAME] ||
data->set.str[STRING_PASSWORD] ||
data->set.str[STRING_BEARER] ||
data->set.str[STRING_SASL_AUTHZID] ||
data->set.str[STRING_SERVICE_NAME]) &&
if((CURL_EASY_STR(data, STRING_USERNAME) ||
CURL_EASY_STR(data, STRING_PASSWORD) ||
CURL_EASY_STR(data, STRING_BEARER) ||
CURL_EASY_STR(data, STRING_SASL_AUTHZID) ||
CURL_EASY_STR(data, STRING_SERVICE_NAME)) &&
Curl_auth_allowed_to_origin(data, data->state.origin)) {
result = Curl_creds_create(data->set.str[STRING_USERNAME],
data->set.str[STRING_PASSWORD],
data->set.str[STRING_BEARER],
data->set.str[STRING_SASL_AUTHZID],
data->set.str[STRING_SERVICE_NAME],
result = Curl_creds_create(CURL_EASY_STR(data, STRING_USERNAME),
CURL_EASY_STR(data, STRING_PASSWORD),
CURL_EASY_STR(data, STRING_BEARER),
CURL_EASY_STR(data, STRING_SASL_AUTHZID),
CURL_EASY_STR(data, STRING_SERVICE_NAME),
CREDS_OPTION, &newcreds);
if(result)
goto out;
@ -1547,8 +1547,8 @@ static CURLcode url_set_conn_origin_etc(struct Curl_easy *data,
goto out;
/* set the connection options */
if(data->set.str[STRING_OPTIONS]) {
conn->options = curlx_strdup(data->set.str[STRING_OPTIONS]);
if(CURL_EASY_STR(data, STRING_OPTIONS)) {
conn->options = curlx_strdup(CURL_EASY_STR(data, STRING_OPTIONS));
if(!conn->options) {
result = CURLE_OUT_OF_MEMORY;
goto out;
@ -1579,14 +1579,14 @@ static CURLcode setup_range(struct Curl_easy *data)
{
struct UrlState *s = &data->state;
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)
curlx_free(s->range);
if(s->resume_from)
s->range = curl_maprintf("%" FMT_OFF_T "-", s->resume_from);
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)
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.
*************************************************************/
if(network_scheme && data->set.str[STRING_UNIX_SOCKET_PATH]) {
result = Curl_peer_uds_create(needle->origin->scheme,
data->set.str[STRING_UNIX_SOCKET_PATH],
(bool)data->set.abstract_unix_socket,
&needle->via_peer);
if(network_scheme && CURL_EASY_STR(data, STRING_UNIX_SOCKET_PATH)) {
result = Curl_peer_uds_create(
needle->origin->scheme, CURL_EASY_STR(data, STRING_UNIX_SOCKET_PATH),
(bool)data->set.abstract_unix_socket, &needle->via_peer);
if(result)
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
* 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)) {
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));
if(!url) {
result = CURLE_OUT_OF_MEMORY;

View file

@ -69,6 +69,7 @@
#include "request.h"
#include "ratelimit.h"
#include "netrc.h"
#include "uint-hashset.h"
#include "vdns/asyn.h"
#include "vdns/hostip.h"
#include "vtls/vtls_config.h"
@ -804,14 +805,6 @@ enum dupstring {
STRING_ECH_PUBLIC, /* CURLOPT_ECH_PUBLIC */
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 */
};
@ -839,6 +832,7 @@ struct UserDefined {
uint32_t httpauth; /* kind of HTTP authentication to use (bitmask) */
uint32_t proxyauth; /* kind of proxy authentication to use (bitmask) */
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_off_t postfieldsize; /* if POST, this might have a size to use instead
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 new_directory_perms; /* when creating remote dirs */
#endif
char *str[STRING_LAST]; /* array of strings, pointing to allocated memory */
struct u8_strset strings;
struct curl_blob *blobs[BLOB_LAST];
uint32_t new_file_perms; /* when creating remote files */
#ifdef USE_IPV6
@ -1230,6 +1224,17 @@ struct Curl_easy {
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"
#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;
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;
#ifdef DEBUGBUILD
@ -696,7 +696,7 @@ static CURLcode async_ares_set_dns_interface(struct Curl_easy *data,
struct Curl_resolv_async *async)
{
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)
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 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)) {
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
struct async_ares_ctx *ares = async ? &async->ares : NULL;
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)) {
/* 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_capath = data->set.ssl.custom_capath;
doh->set.ssl.custom_cablob = data->set.ssl.custom_cablob;
if(data->set.str[STRING_SSL_CAFILE]) {
ERROR_CHECK_SETOPT(CURLOPT_CAINFO, data->set.str[STRING_SSL_CAFILE]);
if(CURL_EASY_STR(data, STRING_SSL_CAFILE)) {
ERROR_CHECK_SETOPT(CURLOPT_CAINFO,
CURL_EASY_STR(data, STRING_SSL_CAFILE));
}
if(data->set.blobs[BLOB_CAINFO]) {
ERROR_CHECK_SETOPT(CURLOPT_CAINFO_BLOB, data->set.blobs[BLOB_CAINFO]);
}
if(data->set.str[STRING_SSL_CAPATH]) {
ERROR_CHECK_SETOPT(CURLOPT_CAPATH, data->set.str[STRING_SSL_CAPATH]);
if(CURL_EASY_STR(data, STRING_SSL_CAPATH)) {
ERROR_CHECK_SETOPT(CURLOPT_CAPATH,
CURL_EASY_STR(data, STRING_SSL_CAPATH));
}
if(data->set.str[STRING_SSL_CRLFILE]) {
ERROR_CHECK_SETOPT(CURLOPT_CRLFILE, data->set.str[STRING_SSL_CRLFILE]);
if(CURL_EASY_STR(data, STRING_SSL_CRLFILE)) {
ERROR_CHECK_SETOPT(CURLOPT_CRLFILE,
CURL_EASY_STR(data, STRING_SSL_CRLFILE));
}
if(data->set.ssl.certinfo)
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);
if(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,
data->set.str[STRING_SSL_EC_CURVES]);
CURL_EASY_STR(data, STRING_SSL_EC_CURVES));
}
(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) {
/* create IPv6 DoH request */
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,
&dohp->probe_mid[DOH_SLOT_IPV6]);
if(result)
@ -454,7 +458,8 @@ CURLcode Curl_doh(struct Curl_easy *data,
/* create IPv4 DoH request */
if(async->dns_queries & CURL_DNSQ_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,
&dohp->probe_mid[DOH_SLOT_IPV4]);
if(result)
@ -473,7 +478,7 @@ CURLcode Curl_doh(struct Curl_easy *data,
}
result = doh_probe_run(data, CURL_DNS_TYPE_HTTPS,
qname ? qname : async->peer->hostname,
data->set.str[STRING_DOH], data->multi,
CURL_EASY_STR(data, STRING_DOH), data->multi,
async->id,
&dohp->probe_mid[DOH_SLOT_HTTPS_RR]);
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,
!data->state.http_ignorecustom ?
data->set.str[STRING_CUSTOMREQUEST] : NULL,
0, pnwritten);
!data->state.http_ignorecustom ?
CURL_EASY_STR(data, STRING_CUSTOMREQUEST) : NULL,
0, pnwritten);
if(result)
goto out;
if(!stream->h1.done) {

View file

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

View file

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

View file

@ -1022,7 +1022,7 @@ CURLcode Curl_cf_quic_insert_after(struct Curl_cfilter *cf_at,
CURLECH_ENABLED(data) &&
Curl_ssl_supports(data, SSLSUPP_ECH) &&
(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,
cf_at->sockindex, origin);
}

View file

@ -109,10 +109,10 @@ static CURLcode sftp_error_to_CURLE(int err)
}
/* Multiple options:
* 1. data->set.str[STRING_SSH_HOST_PUBLIC_KEY_SHA256] is set with a SHA256
* hash.
* 2. data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5] is set with an MD5
* hash (90s style auth, not sure we should have it here)
* 1. CURL_EASY_STR(data, STRING_SSH_HOST_PUBLIC_KEY_SHA256) is set
* with a SHA256 hash.
* 2. CURL_EASY_STR(data, STRING_SSH_HOST_PUBLIC_KEY_MD5) is set
* 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
* use. We even save on knownhosts if CURLKHSTAT_FINE_ADD_TO_FILE
* 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)
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 =
data->set.str[STRING_SSH_HOST_PUBLIC_KEY_SHA256];
CURL_EASY_STR(data, STRING_SSH_HOST_PUBLIC_KEY_SHA256);
char *fingerprint_b64 = NULL;
size_t fingerprint_b64_len;
size_t pub_pos = 0;
@ -197,8 +197,9 @@ static int myssh_is_known(struct Curl_easy *data, struct ssh_conn *sshc)
goto cleanup;
}
if(data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5]) {
const char *pubkey_md5 = data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5];
if(CURL_EASY_STR(data, STRING_SSH_HOST_PUBLIC_KEY_MD5)) {
const char *pubkey_md5 =
CURL_EASY_STR(data, STRING_SSH_HOST_PUBLIC_KEY_MD5);
char md5buffer[33];
int i;
@ -227,7 +228,7 @@ static int myssh_is_known(struct Curl_easy *data, struct ssh_conn *sshc)
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 */
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]) {
infof(data, "Known hosts: %s", data->set.str[STRING_SSH_KNOWNHOSTS]);
if(CURL_EASY_STR(data, 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,
data->set.str[STRING_SSH_KNOWNHOSTS]);
CURL_EASY_STR(data, STRING_SSH_KNOWNHOSTS));
if(rc == SSH_OK)
/* libssh has two separate options for this. Set both to the same file
to avoid surprises */
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) {
failf(data, "Could not set known hosts file path");
return CURLE_FAILED_INIT;

View file

@ -316,7 +316,7 @@ static CURLcode ssh_knownhost(struct Curl_easy *data,
int rc = 0;
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");
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
known_hosts file */
int wrc =
libssh2_knownhost_writefile(sshc->kh,
data->set.str[STRING_SSH_KNOWNHOSTS],
LIBSSH2_KNOWNHOST_FILE_OPENSSH);
libssh2_knownhost_writefile(
sshc->kh, CURL_EASY_STR(data, STRING_SSH_KNOWNHOSTS),
LIBSSH2_KNOWNHOST_FILE_OPENSSH);
if(wrc) {
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,
struct ssh_conn *sshc)
{
const char *pubkey_md5 = data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5];
const char *pubkey_sha256 = data->set.str[STRING_SSH_HOST_PUBLIC_KEY_SHA256];
const char *pubkey_md5 =
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) {
const char *fingerprint = NULL;
@ -646,8 +648,8 @@ static CURLcode ssh_force_knownhost_key_type(struct Curl_easy *data,
bool found = FALSE;
if(sshc->kh &&
!data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5] &&
!data->set.str[STRING_SSH_HOST_PUBLIC_KEY_SHA256]) {
!CURL_EASY_STR(data, STRING_SSH_HOST_PUBLIC_KEY_MD5) &&
!CURL_EASY_STR(data, STRING_SSH_HOST_PUBLIC_KEY_SHA256)) {
struct libssh2_knownhost *store = NULL;
struct connectdata *conn = data->conn;
/* 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, "]:");
if(!kh_name_end) {
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;
}
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;
const char *hostkey_method = NULL;
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) {
case LIBSSH2_KNOWNHOST_KEY_ED25519:
@ -738,7 +742,8 @@ static CURLcode ssh_force_knownhost_key_type(struct Curl_easy *data,
}
else {
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");
}
if(data->set.str[STRING_SSH_KNOWNHOSTS]) {
if(CURL_EASY_STR(data, STRING_SSH_KNOWNHOSTS)) {
int rc;
sshc->kh = libssh2_knownhost_init(sshc->ssh_session);
if(!sshc->kh) {
@ -3485,12 +3490,12 @@ static CURLcode ssh_connect(struct Curl_easy *data, bool *done)
}
/* read all known hosts from there */
rc = libssh2_knownhost_readfile(sshc->kh,
data->set.str[STRING_SSH_KNOWNHOSTS],
LIBSSH2_KNOWNHOST_FILE_OPENSSH);
rc = libssh2_knownhost_readfile(
sshc->kh, CURL_EASY_STR(data, STRING_SSH_KNOWNHOSTS),
LIBSSH2_KNOWNHOST_FILE_OPENSSH);
if(rc < 0)
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

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) {
sshc->pub_key = sshc->priv_key = NULL;
if(data->set.str[STRING_SSH_PRIVATE_KEY]) {
sshc->priv_key = curlx_strdup(data->set.str[STRING_SSH_PRIVATE_KEY]);
if(CURL_EASY_STR(data, STRING_SSH_PRIVATE_KEY)) {
sshc->priv_key = curlx_strdup(
CURL_EASY_STR(data, STRING_SSH_PRIVATE_KEY));
if(!sshc->priv_key)
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
* 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 */
data->set.str[STRING_SSH_PUBLIC_KEY][0]) {
sshc->pub_key = curlx_strdup(data->set.str[STRING_SSH_PUBLIC_KEY]);
CURL_EASY_STR(data, STRING_SSH_PUBLIC_KEY)[0]) {
sshc->pub_key = curlx_strdup(
CURL_EASY_STR(data, STRING_SSH_PUBLIC_KEY));
if(!sshc->pub_key)
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);
#ifndef CURL_DISABLE_PROXY
const char *pinned_key = Curl_ssl_cf_is_proxy(cf) ?
data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
data->set.str[STRING_SSL_PINNEDPUBLICKEY];
CURL_EASY_STR(data, STRING_SSL_PINNEDPUBLICKEY_PROXY) :
CURL_EASY_STR(data, STRING_SSL_PINNEDPUBLICKEY);
#else
const char *pinned_key = data->set.str[STRING_SSL_PINNEDPUBLICKEY];
const char *pinned_key = CURL_EASY_STR(data, STRING_SSL_PINNEDPUBLICKEY);
#endif
CURLcode result;

View file

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

View file

@ -3477,7 +3477,7 @@ bool Curl_ossl_need_httpsrr(struct Curl_easy *data)
if(!CURLECH_ENABLED(data))
return FALSE;
if((data->set.tls_ech == CURLECH_GREASE) ||
data->set.str[STRING_ECH_CONFIG])
CURL_EASY_STR(data, STRING_ECH_CONFIG))
return FALSE;
return TRUE;
}
@ -3487,9 +3487,7 @@ static CURLcode ossl_init_ech(struct ossl_ctx *octx,
struct Curl_easy *data,
struct ssl_peer *peer)
{
unsigned char *ech_config = NULL;
size_t ech_config_len = 0;
char *outername = data->set.str[STRING_ECH_PUBLIC];
const char *outername = CURL_EASY_STR(data, STRING_ECH_PUBLIC);
int trying_ech_now = 0;
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);
#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
/* 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;
if(!b64) {
@ -3530,13 +3530,16 @@ static CURLcode ossl_init_ech(struct ossl_ctx *octx,
curlx_free(ech_config);
trying_ech_now = 1;
#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) {
infof(data, "ECH: ECHConfig from command line empty");
return CURLE_SSL_CONNECT_ERROR;
}
ech_config_len = strlen(data->set.str[STRING_ECH_CONFIG]);
if(SSL_set1_ech_config_list(octx->ssl, ech_config, ech_config_len) != 1) {
ech_config_len = strlen(ech_config);
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");
if(data->set.tls_ech == CURLECH_HARD)
return CURLE_SSL_CONNECT_ERROR;
@ -4599,10 +4602,10 @@ static CURLcode ossl_check_pinned_key(struct Curl_cfilter *cf,
(void)cf;
#ifndef CURL_DISABLE_PROXY
ptr = Curl_ssl_cf_is_proxy(cf) ?
data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
data->set.str[STRING_SSL_PINNEDPUBLICKEY];
CURL_EASY_STR(data, STRING_SSL_PINNEDPUBLICKEY_PROXY) :
CURL_EASY_STR(data, STRING_SSL_PINNEDPUBLICKEY);
#else
ptr = data->set.str[STRING_SSL_PINNEDPUBLICKEY];
ptr = CURL_EASY_STR(data, STRING_SSL_PINNEDPUBLICKEY);
#endif
if(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))
return FALSE;
if((data->set.tls_ech == CURLECH_GREASE) ||
data->set.str[STRING_ECH_CONFIG])
CURL_EASY_STR(data, STRING_ECH_CONFIG))
return FALSE;
return TRUE;
}
@ -948,7 +948,7 @@ init_config_builder_ech(struct Curl_easy *data,
goto cleanup;
}
if(data->set.str[STRING_ECH_PUBLIC]) {
if(CURL_EASY_STR(data, STRING_ECH_PUBLIC)) {
failf(data, "rustls: ECH outername not supported");
result = CURLE_SSL_CONNECT_ERROR;
goto cleanup;
@ -964,8 +964,8 @@ init_config_builder_ech(struct Curl_easy *data,
return CURLE_OK;
}
if(data->set.tls_ech && data->set.str[STRING_ECH_CONFIG]) {
const char *b64 = data->set.str[STRING_ECH_CONFIG];
if(data->set.tls_ech && CURL_EASY_STR(data, STRING_ECH_CONFIG)) {
const char *b64 = CURL_EASY_STR(data, STRING_ECH_CONFIG);
size_t decode_result;
if(!b64) {
infof(data, "rustls: ECHConfig from command line empty");
@ -1005,7 +1005,7 @@ init_config_builder_ech(struct Curl_easy *data,
}
cleanup:
/* 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);
}
if(dns) {

View file

@ -1458,10 +1458,10 @@ static CURLcode schannel_connect_step2(struct Curl_cfilter *cf,
#ifndef CURL_DISABLE_PROXY
pubkey_ptr = Curl_ssl_cf_is_proxy(cf) ?
data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
data->set.str[STRING_SSL_PINNEDPUBLICKEY];
CURL_EASY_STR(data, STRING_SSL_PINNEDPUBLICKEY_PROXY) :
CURL_EASY_STR(data, STRING_SSL_PINNEDPUBLICKEY);
#else
pubkey_ptr = data->set.str[STRING_SSL_PINNEDPUBLICKEY];
pubkey_ptr = CURL_EASY_STR(data, STRING_SSL_PINNEDPUBLICKEY);
#endif
if(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) &&
Curl_ssl_supports(data, SSLSUPP_ECH) &&
(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,
origin);
}

View file

@ -236,12 +236,18 @@ static void ssl_easy_config_compl_options(struct Curl_peer *origin,
!!(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,
struct Curl_peer *origin)
{
struct ssl_config_data *sslc = &data->set.ssl;
#if defined(CURL_CA_PATH) || defined(CURL_CA_BUNDLE)
struct UserDefined *set = &data->set;
CURLcode result;
#endif
@ -253,42 +259,43 @@ CURLcode Curl_ssl_easy_config_complete(struct Curl_easy *data,
sslc->native_ca_store = TRUE;
#endif
#ifdef CURL_CA_PATH
if(!sslc->custom_capath && !set->str[STRING_SSL_CAPATH]) {
result = Curl_setstropt(&set->str[STRING_SSL_CAPATH], CURL_CA_PATH);
if(!sslc->custom_capath && !CURL_EASY_STR(data, STRING_SSL_CAPATH)) {
result = Curl_setstropt(data, STRING_SSL_CAPATH, CURL_CA_PATH);
if(result)
return result;
}
#endif
#ifdef CURL_CA_BUNDLE
if(!sslc->custom_cafile && !set->str[STRING_SSL_CAFILE]) {
result = Curl_setstropt(&set->str[STRING_SSL_CAFILE], CURL_CA_BUNDLE);
if(!sslc->custom_cafile && !CURL_EASY_STR(data, STRING_SSL_CAFILE)) {
result = Curl_setstropt(data, STRING_SSL_CAFILE, CURL_CA_BUNDLE);
if(result)
return result;
}
#endif
}
sslc->primary.CAfile = data->set.str[STRING_SSL_CAFILE];
sslc->primary.CRLfile = data->set.str[STRING_SSL_CRLFILE];
sslc->primary.CApath = data->set.str[STRING_SSL_CAPATH];
sslc->primary.cipher_list = data->set.str[STRING_SSL_CIPHER_LIST];
sslc->primary.cipher_list13 = data->set.str[STRING_SSL_CIPHER13_LIST];
sslc->primary.CAfile = ssl_easy_steal(data, STRING_SSL_CAFILE);
sslc->primary.CRLfile = ssl_easy_steal(data, STRING_SSL_CRLFILE);
sslc->primary.CApath = ssl_easy_steal(data, STRING_SSL_CAPATH);
sslc->primary.cipher_list = ssl_easy_steal(data, STRING_SSL_CIPHER_LIST);
sslc->primary.cipher_list13 = ssl_easy_steal(data, STRING_SSL_CIPHER13_LIST);
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.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
* 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];
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_type = data->set.str[STRING_CERT_TYPE];
sslc->primary.key = data->set.str[STRING_KEY];
sslc->primary.key_type = data->set.str[STRING_KEY_TYPE];
sslc->primary.key_passwd = data->set.str[STRING_KEY_PASSWD];
sslc->primary.clientcert = data->set.str[STRING_CERT];
sslc->primary.cert_type = ssl_easy_steal(data, STRING_CERT_TYPE);
sslc->primary.key = ssl_easy_steal(data, STRING_KEY);
sslc->primary.key_type = ssl_easy_steal(data, STRING_KEY_TYPE);
sslc->primary.key_passwd = ssl_easy_steal(data, STRING_KEY_PASSWD);
sslc->primary.clientcert = ssl_easy_steal(data, STRING_CERT);
sslc->primary.key_blob = data->set.blobs[BLOB_KEY];
}
else {
@ -313,37 +320,40 @@ CURLcode Curl_ssl_easy_config_complete(struct Curl_easy *data,
sslc->native_ca_store = TRUE;
#endif
#ifdef CURL_CA_PATH
if(!sslc->custom_capath && !set->str[STRING_SSL_CAPATH_PROXY]) {
result = Curl_setstropt(&set->str[STRING_SSL_CAPATH_PROXY],
CURL_CA_PATH);
if(!sslc->custom_capath &&
!CURL_EASY_STR(data, STRING_SSL_CAPATH_PROXY)) {
result = Curl_setstropt(data, STRING_SSL_CAPATH_PROXY, CURL_CA_PATH);
if(result)
return result;
}
#endif
#ifdef CURL_CA_BUNDLE
if(!sslc->custom_cafile && !set->str[STRING_SSL_CAFILE_PROXY]) {
result = Curl_setstropt(&set->str[STRING_SSL_CAFILE_PROXY],
CURL_CA_BUNDLE);
if(!sslc->custom_cafile &&
!CURL_EASY_STR(data, STRING_SSL_CAFILE_PROXY)) {
result = Curl_setstropt(data, STRING_SSL_CAFILE_PROXY, CURL_CA_BUNDLE);
if(result)
return result;
}
#endif
}
sslc->primary.CAfile = data->set.str[STRING_SSL_CAFILE_PROXY];
sslc->primary.CApath = data->set.str[STRING_SSL_CAPATH_PROXY];
sslc->primary.cipher_list = data->set.str[STRING_SSL_CIPHER_LIST_PROXY];
sslc->primary.cipher_list13 = data->set.str[STRING_SSL_CIPHER13_LIST_PROXY];
sslc->primary.pinned_key = data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY];
sslc->primary.CAfile = ssl_easy_steal(data, STRING_SSL_CAFILE_PROXY);
sslc->primary.CApath = ssl_easy_steal(data, STRING_SSL_CAPATH_PROXY);
sslc->primary.cipher_list =
ssl_easy_steal(data, STRING_SSL_CIPHER_LIST_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.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.CRLfile = data->set.str[STRING_SSL_CRLFILE_PROXY];
sslc->primary.cert_type = data->set.str[STRING_CERT_TYPE_PROXY];
sslc->primary.key = data->set.str[STRING_KEY_PROXY];
sslc->primary.key_type = data->set.str[STRING_KEY_TYPE_PROXY];
sslc->primary.key_passwd = data->set.str[STRING_KEY_PASSWD_PROXY];
sslc->primary.clientcert = data->set.str[STRING_CERT_PROXY];
sslc->primary.CRLfile = ssl_easy_steal(data, STRING_SSL_CRLFILE_PROXY);
sslc->primary.cert_type = ssl_easy_steal(data, STRING_CERT_TYPE_PROXY);
sslc->primary.key = ssl_easy_steal(data, STRING_KEY_PROXY);
sslc->primary.key_type = ssl_easy_steal(data, STRING_KEY_TYPE_PROXY);
sslc->primary.key_passwd = ssl_easy_steal(data, STRING_KEY_PASSWD_PROXY);
sslc->primary.clientcert = ssl_easy_steal(data, STRING_CERT_PROXY);
sslc->primary.key_blob = data->set.blobs[BLOB_KEY_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;
if(data->set.str[STRING_ECH_PUBLIC]) {
if(CURL_EASY_STR(data, STRING_ECH_PUBLIC)) {
infof(data, "ECH: outername not (yet) supported"
" with wolfSSL");
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"
" wolfSSL: no need to ask");
}
if(data->set.tls_ech && data->set.str[STRING_ECH_CONFIG]) {
char *b64val = data->set.str[STRING_ECH_CONFIG];
if(data->set.tls_ech && CURL_EASY_STR(data, STRING_ECH_CONFIG)) {
const char *b64val = CURL_EASY_STR(data, STRING_ECH_CONFIG);
word32 b64len = 0;
b64len = (word32)strlen(b64val);
@ -1477,7 +1477,7 @@ bool Curl_wssl_need_httpsrr(struct Curl_easy *data)
if(!CURLECH_ENABLED(data))
return FALSE;
if((data->set.tls_ech == CURLECH_GREASE) ||
data->set.str[STRING_ECH_CONFIG])
CURL_EASY_STR(data, STRING_ECH_CONFIG))
return FALSE;
return TRUE;
#else
@ -1580,10 +1580,11 @@ CURLcode Curl_wssl_verify_pinned(struct Curl_cfilter *cf,
CURLcode result = CURLE_OK;
#ifndef CURL_DISABLE_PROXY
const char * const pinnedpubkey = Curl_ssl_cf_is_proxy(cf) ?
data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
data->set.str[STRING_SSL_PINNEDPUBLICKEY];
CURL_EASY_STR(data, STRING_SSL_PINNEDPUBLICKEY_PROXY) :
CURL_EASY_STR(data, STRING_SSL_PINNEDPUBLICKEY);
#else
const char * const pinnedpubkey = data->set.str[STRING_SSL_PINNEDPUBLICKEY];
const char * const pinnedpubkey =
CURL_EASY_STR(data, STRING_SSL_PINNEDPUBLICKEY);
(void)cf;
#endif

View file

@ -1205,7 +1205,7 @@ CURLcode curl_easy_setopt_ccsid(CURL *curl, CURLoption tag, ...)
}
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;
default:

View file

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

View file

@ -127,7 +127,7 @@ static CURLcode test_unit1620(const char *arg)
Curl_freeset(empty);
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);

View file

@ -24,10 +24,11 @@
#include "unitcheck.h"
#include "urldata.h"
#include "uint-bset.h"
#include "uint-hashset.h"
#include "curl_trc.h"
static void check_set(const char *name, uint32_t capacity,
const uint32_t *s, size_t slen)
static void t3211_check_bset(const char *name, uint32_t capacity,
const uint32_t *s, size_t slen)
{
struct uint32_bset bset;
size_t i, j;
@ -122,6 +123,103 @@ static void check_set(const char *name, uint32_t capacity,
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)
{
UNITTEST_BEGIN_SIMPLE
@ -142,8 +240,10 @@ static CURLcode test_unit3211(const char *arg)
120, 121, 122, 123, 124, 125, 126, 127,
};
check_set("s1", 100, s1, CURL_ARRAYSIZE(s1));
check_set("s2", 1000, s2, CURL_ARRAYSIZE(s2));
t3211_check_bset("s1", 100, s1, CURL_ARRAYSIZE(s1));
t3211_check_bset("s2", 1000, s2, CURL_ARRAYSIZE(s2));
t3211_check_strset1();
UNITTEST_END_SIMPLE
}