lib: new easy option string storage
No binary (build failed)
—
(log yok)
| @@ -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 \ | |
| @@ -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); | |
| } | |
| @@ -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; | |
| @@ -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))) { | |
| @@ -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 | |
| @@ -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); | |
| @@ -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 | |
| @@ -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) { | |
| /* | |
| @@ -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; | |
| @@ -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"; | |
| @@ -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; | |
| @@ -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; | |
| } | |
| @@ -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 */ | |
| @@ -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; | |
| @@ -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"); | |
| @@ -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; | |
| } | |
| } | |
| @@ -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. */ |
| - | |
| - | 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; |
| - | } |
| + | DEBUGASSERT((unsigned)id <= UINT8_MAX); |
| + | if(s && (strlen(s) > CURL_MAX_INPUT_LENGTH)) |
| + | return CURLE_BAD_FUNCTION_ARGUMENT; |
| - | 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; | |
| @@ -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) | |
| @@ -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; | |
| @@ -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); | |
| @@ -0,0 +1,305 @@ | |
| + | /*************************************************************************** |
| + | * _ _ ____ _ |
| + | * Project ___| | | | _ \| | |
| + | * / __| | | | |_) | | |
| + | * | (__| |_| | _ <| |___ |
| + | * \___|\___/|_| \_\_____| |
| + | * |
| + | * Copyright (C) Daniel Stenberg, <[email protected]>, 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; |
| + | } |
| @@ -0,0 +1,80 @@ | |
| + | #ifndef HEADER_CURL_UINT_HASHSET_H |
| + | #define HEADER_CURL_UINT_HASHSET_H |
| + | /*************************************************************************** |
| + | * _ _ ____ _ |
| + | * Project ___| | | | _ \| | |
| + | * / __| | | | |_) | | |
| + | * | (__| |_| | _ <| |___ |
| + | * \___|\___/|_| \_\_____| |
| + | * |
| + | * Copyright (C) Daniel Stenberg, <[email protected]>, 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 */ |
| @@ -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; | |
| @@ -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 */ | |
| @@ -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 */ | |
| @@ -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); | |
| @@ -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) { | |
| @@ -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) { | |
| @@ -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) | |
| @@ -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); | |
| } | |
| @@ -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; | |
| @@ -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 | |
| @@ -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; | |
| } | |
| @@ -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; | |
| @@ -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 | |
| @@ -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); | |
| @@ -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) { | |
| @@ -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); | |
| @@ -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); | |
| } | |
| @@ -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 */ | |
| @@ -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 | |
| @@ -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: | |
| @@ -13,7 +13,7 @@ uint_bset | |
| unittest | |
| </features> | |
| <name> | |
| - | uint_bset unit tests |
| + | uint_bset and uint_hashset unit tests |
| </name> | |
| </client> | |
| </testcase> | |
| @@ -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); | |
| @@ -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 | |
| } | |