strparse: provide access functions

To access the string and the length without having to directly use the
struct field names. Gives more freedom, flexbility and keeps
implementation specifics out of users' code.

Closes #16386
This commit is contained in:
Daniel Stenberg 2025-02-19 08:49:54 +01:00
parent 1aea05a6c2
commit f0d7318193
No known key found for this signature in database
GPG Key ID: 5CC908FDB71E12C2
9 changed files with 117 additions and 84 deletions

View File

@ -30,6 +30,19 @@ struct Curl_str {
}; };
~~~ ~~~
Access the struct fields with `Curl_str()` for the pointer and `Curl_strlen()`
for the length rather than using the struct fields directly.
## `Curl_str_init`
~~~c
void Curl_str_init(struct Curl_str *out)
~~~
This initiates a string struct. The parser functions that store info in
strings always init the string themselves, so this stand-alone use is often
not necessary.
## `Curl_str_word` ## `Curl_str_word`
~~~c ~~~c

View File

@ -138,12 +138,14 @@ static struct altsvc *altsvc_create(struct Curl_str *srchost,
size_t srcport, size_t srcport,
size_t dstport) size_t dstport)
{ {
enum alpnid dstalpnid = Curl_alpn2alpnid(dstalpn->str, dstalpn->len); enum alpnid dstalpnid =
enum alpnid srcalpnid = Curl_alpn2alpnid(srcalpn->str, srcalpn->len); Curl_alpn2alpnid(Curl_str(dstalpn), Curl_strlen(dstalpn));
enum alpnid srcalpnid =
Curl_alpn2alpnid(Curl_str(srcalpn), Curl_strlen(srcalpn));
if(!srcalpnid || !dstalpnid) if(!srcalpnid || !dstalpnid)
return NULL; return NULL;
return altsvc_createid(srchost->str, srchost->len, return altsvc_createid(Curl_str(srchost), Curl_strlen(srchost),
dsthost->str, dsthost->len, Curl_str(dsthost), Curl_strlen(dsthost),
srcalpnid, dstalpnid, srcalpnid, dstalpnid,
srcport, dstport); srcport, dstport);
} }
@ -190,8 +192,8 @@ static CURLcode altsvc_add(struct altsvcinfo *asi, const char *line)
/* The date parser works on a null terminated string. The maximum length /* The date parser works on a null terminated string. The maximum length
is upheld by Curl_str_quotedword(). */ is upheld by Curl_str_quotedword(). */
memcpy(dbuf, date.str, date.len); memcpy(dbuf, Curl_str(&date), Curl_strlen(&date));
dbuf[date.len] = 0; dbuf[Curl_strlen(&date)] = 0;
expires = Curl_getdate_capped(dbuf); expires = Curl_getdate_capped(dbuf);
as = altsvc_create(&srchost, &dsthost, &srcalpn, &dstalpn, as = altsvc_create(&srchost, &dsthost, &srcalpn, &dstalpn,
(size_t)srcport, (size_t)dstport); (size_t)srcport, (size_t)dstport);

View File

@ -507,15 +507,14 @@ parse_cookie_header(struct Curl_easy *data,
Curl_str_trimblanks(&val); Curl_str_trimblanks(&val);
/* Reject cookies with a TAB inside the value */ /* Reject cookies with a TAB inside the value */
if(memchr(val.str, '\t', val.len)) { if(memchr(Curl_str(&val), '\t', Curl_strlen(&val))) {
infof(data, "cookie contains TAB, dropping"); infof(data, "cookie contains TAB, dropping");
return CERR_TAB; return CERR_TAB;
} }
} }
} }
else { else {
val.str = NULL; Curl_str_init(&val);
val.len = 0;
} }
/* /*
@ -523,10 +522,11 @@ parse_cookie_header(struct Curl_easy *data,
* combination of name + contents. Chrome and Firefox support 4095 or * combination of name + contents. Chrome and Firefox support 4095 or
* 4096 bytes combo * 4096 bytes combo
*/ */
if(name.len >= (MAX_NAME-1) || val.len >= (MAX_NAME-1) || if(Curl_strlen(&name) >= (MAX_NAME-1) ||
((name.len + val.len) > MAX_NAME)) { Curl_strlen(&val) >= (MAX_NAME-1) ||
((Curl_strlen(&name) + Curl_strlen(&val)) > MAX_NAME)) {
infof(data, "oversized cookie dropped, name/val %zu + %zu bytes", infof(data, "oversized cookie dropped, name/val %zu + %zu bytes",
name.len, val.len); Curl_strlen(&name), Curl_strlen(&val));
return CERR_TOO_BIG; return CERR_TOO_BIG;
} }
@ -536,9 +536,9 @@ parse_cookie_header(struct Curl_easy *data,
* "the rest". Prefixes must start with '__' and end with a '-', so * "the rest". Prefixes must start with '__' and end with a '-', so
* only test for names where that can possibly be true. * only test for names where that can possibly be true.
*/ */
if(strncasecompare("__Secure-", name.str, 9)) if(strncasecompare("__Secure-", Curl_str(&name), 9))
co->prefix_secure = TRUE; co->prefix_secure = TRUE;
else if(strncasecompare("__Host-", name.str, 7)) else if(strncasecompare("__Host-", Curl_str(&name), 7))
co->prefix_host = TRUE; co->prefix_host = TRUE;
/* /*
@ -553,8 +553,8 @@ parse_cookie_header(struct Curl_easy *data,
/* Bad name/value pair. */ /* Bad name/value pair. */
return CERR_NO_SEP; return CERR_NO_SEP;
strstore(&co->name, name.str, name.len); strstore(&co->name, Curl_str(&name), Curl_strlen(&name));
strstore(&co->value, val.str, val.len); strstore(&co->value, Curl_str(&val), Curl_strlen(&val));
done = TRUE; done = TRUE;
if(!co->name || !co->value) if(!co->name || !co->value)
return CERR_NO_NAME_VALUE; return CERR_NO_NAME_VALUE;
@ -564,7 +564,7 @@ parse_cookie_header(struct Curl_easy *data,
return CERR_INVALID_OCTET; return CERR_INVALID_OCTET;
} }
} }
else if(!val.len) { else if(!Curl_strlen(&val)) {
/* /*
* this was a "<name>=" with no content, and we must allow * this was a "<name>=" with no content, and we must allow
* 'secure' and 'httponly' specified this weirdly * 'secure' and 'httponly' specified this weirdly
@ -592,7 +592,7 @@ parse_cookie_header(struct Curl_easy *data,
if(done) if(done)
; ;
else if(Curl_str_casecompare(&name, "path")) { else if(Curl_str_casecompare(&name, "path")) {
strstore(&co->path, val.str, val.len); strstore(&co->path, Curl_str(&val), Curl_strlen(&val));
if(!co->path) if(!co->path)
return CERR_OUT_OF_MEMORY; return CERR_OUT_OF_MEMORY;
free(co->spath); /* if this is set again */ free(co->spath); /* if this is set again */
@ -600,15 +600,15 @@ parse_cookie_header(struct Curl_easy *data,
if(!co->spath) if(!co->spath)
return CERR_OUT_OF_MEMORY; return CERR_OUT_OF_MEMORY;
} }
else if(Curl_str_casecompare(&name, "domain") && val.len) { else if(Curl_str_casecompare(&name, "domain") && Curl_strlen(&val)) {
bool is_ip; bool is_ip;
const char *v = Curl_str(&val);
/* /*
* Now, we make sure that our host is within the given domain, or * Now, we make sure that our host is within the given domain, or
* the given domain is not valid and thus cannot be set. * the given domain is not valid and thus cannot be set.
*/ */
if('.' == val.str[0]) if('.' == *v)
Curl_str_nudge(&val, 1); Curl_str_nudge(&val, 1);
#ifndef USE_LIBPSL #ifndef USE_LIBPSL
@ -617,17 +617,18 @@ parse_cookie_header(struct Curl_easy *data,
* TLD or otherwise "protected" suffix. To reduce risk, we require a * TLD or otherwise "protected" suffix. To reduce risk, we require a
* dot OR the exact hostname being "localhost". * dot OR the exact hostname being "localhost".
*/ */
if(bad_domain(val.str, val.len)) if(bad_domain(Curl_str(&val), Curl_strlen(&val)))
domain = ":"; domain = ":";
#endif #endif
is_ip = Curl_host_is_ipnum(domain ? domain : val.str); is_ip = Curl_host_is_ipnum(domain ? domain : Curl_str(&val));
if(!domain if(!domain
|| (is_ip && !strncmp(val.str, domain, val.len) && || (is_ip && !strncmp(Curl_str(&val), domain, Curl_strlen(&val)) &&
(val.len == strlen(domain))) (Curl_strlen(&val) == strlen(domain)))
|| (!is_ip && cookie_tailmatch(val.str, val.len, domain))) { || (!is_ip && cookie_tailmatch(Curl_str(&val),
strstore(&co->domain, val.str, val.len); Curl_strlen(&val), domain))) {
strstore(&co->domain, Curl_str(&val), Curl_strlen(&val));
if(!co->domain) if(!co->domain)
return CERR_OUT_OF_MEMORY; return CERR_OUT_OF_MEMORY;
@ -641,14 +642,14 @@ parse_cookie_header(struct Curl_easy *data,
* not a domain to which the current host belongs. Mark as bad. * not a domain to which the current host belongs. Mark as bad.
*/ */
infof(data, "skipped cookie with bad tailmatch domain: %s", infof(data, "skipped cookie with bad tailmatch domain: %s",
val.str); Curl_str(&val));
return CERR_NO_TAILMATCH; return CERR_NO_TAILMATCH;
} }
} }
else if(Curl_str_casecompare(&name, "version")) { else if(Curl_str_casecompare(&name, "version")) {
/* just ignore */ /* just ignore */
} }
else if(Curl_str_casecompare(&name, "max-age") && val.len) { else if(Curl_str_casecompare(&name, "max-age") && Curl_strlen(&val)) {
/* /*
* Defined in RFC2109: * Defined in RFC2109:
* *
@ -659,7 +660,7 @@ parse_cookie_header(struct Curl_easy *data,
* cookie should be discarded immediately. * cookie should be discarded immediately.
*/ */
int rc; int rc;
const char *maxage = val.str; const char *maxage = Curl_str(&val);
if(*maxage == '\"') if(*maxage == '\"')
maxage++; maxage++;
rc = Curl_str_number(&maxage, &co->expires, CURL_OFF_T_MAX); rc = Curl_str_number(&maxage, &co->expires, CURL_OFF_T_MAX);
@ -686,8 +687,8 @@ parse_cookie_header(struct Curl_easy *data,
} }
cap_expires(now, co); cap_expires(now, co);
} }
else if(Curl_str_casecompare(&name, "expires") && val.len) { else if(Curl_str_casecompare(&name, "expires") && Curl_strlen(&val)) {
if(!co->expires && (val.len < MAX_DATE_LENGTH)) { if(!co->expires && (Curl_strlen(&val) < MAX_DATE_LENGTH)) {
/* /*
* Let max-age have priority. * Let max-age have priority.
* *
@ -695,8 +696,8 @@ parse_cookie_header(struct Curl_easy *data,
* will be treated as a session cookie * will be treated as a session cookie
*/ */
char dbuf[MAX_DATE_LENGTH + 1]; char dbuf[MAX_DATE_LENGTH + 1];
memcpy(dbuf, val.str, val.len); memcpy(dbuf, Curl_str(&val), Curl_strlen(&val));
dbuf[val.len] = 0; dbuf[Curl_strlen(&val)] = 0;
co->expires = Curl_getdate_capped(dbuf); co->expires = Curl_getdate_capped(dbuf);
/* /*

View File

@ -394,7 +394,7 @@ static CURLcode trc_opt(const char *config)
struct Curl_str out; struct Curl_str out;
while(!Curl_str_until(&config, &out, 32, ',')) { while(!Curl_str_until(&config, &out, 32, ',')) {
int lvl = CURL_LOG_LVL_INFO; int lvl = CURL_LOG_LVL_INFO;
const char *token = out.str; const char *token = Curl_str(&out);
if(*token == '-') { if(*token == '-') {
lvl = CURL_LOG_LVL_NONE; lvl = CURL_LOG_LVL_NONE;

View File

@ -1150,7 +1150,8 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
if(!Curl_str_number(&host, &num, 0xffff)) { if(!Curl_str_number(&host, &num, 0xffff)) {
/* Create an entry id, based upon the hostname and port */ /* Create an entry id, based upon the hostname and port */
entry_len = create_hostcache_id(source.str, source.len, (int)num, entry_len = create_hostcache_id(Curl_str(&source),
Curl_strlen(&source), (int)num,
entry_id, sizeof(entry_id)); entry_id, sizeof(entry_id));
if(data->share) if(data->share)
Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE); Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
@ -1224,11 +1225,11 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
} }
#endif #endif
if(target.len >= sizeof(address)) if(Curl_strlen(&target) >= sizeof(address))
goto err; goto err;
memcpy(address, target.str, target.len); memcpy(address, Curl_str(&target), Curl_strlen(&target));
address[target.len] = '\0'; address[Curl_strlen(&target)] = '\0';
ai = Curl_str2addr(address, (int)port); ai = Curl_str2addr(address, (int)port);
if(!ai) { if(!ai) {
@ -1260,7 +1261,8 @@ err:
} }
/* Create an entry id, based upon the hostname and port */ /* Create an entry id, based upon the hostname and port */
entry_len = create_hostcache_id(source.str, source.len, (int)port, entry_len = create_hostcache_id(Curl_str(&source), Curl_strlen(&source),
(int)port,
entry_id, sizeof(entry_id)); entry_id, sizeof(entry_id));
if(data->share) if(data->share)
@ -1271,7 +1273,8 @@ err:
if(dns) { if(dns) {
infof(data, "RESOLVE %.*s:%" CURL_FORMAT_CURL_OFF_T infof(data, "RESOLVE %.*s:%" CURL_FORMAT_CURL_OFF_T
" - old addresses discarded", (int)source.len, source.str, port); " - old addresses discarded", (int)Curl_strlen(&source),
Curl_str(&source), port);
/* delete old entry, there are two reasons for this /* delete old entry, there are two reasons for this
1. old entry may have different addresses. 1. old entry may have different addresses.
2. even if entry with correct addresses is already in the cache, 2. even if entry with correct addresses is already in the cache,
@ -1287,8 +1290,8 @@ err:
} }
/* put this new host in the cache */ /* put this new host in the cache */
dns = Curl_cache_addr(data, head, source.str, source.len, (int)port, dns = Curl_cache_addr(data, head, Curl_str(&source),
permanent); Curl_strlen(&source), (int)port, permanent);
if(dns) { if(dns) {
/* release the returned reference; the cache itself will keep the /* release the returned reference; the cache itself will keep the
* entry alive: */ * entry alive: */
@ -1304,12 +1307,12 @@ err:
} }
#ifndef CURL_DISABLE_VERBOSE_STRINGS #ifndef CURL_DISABLE_VERBOSE_STRINGS
infof(data, "Added %.*s:%" CURL_FORMAT_CURL_OFF_T ":%s to DNS cache%s", infof(data, "Added %.*s:%" CURL_FORMAT_CURL_OFF_T ":%s to DNS cache%s",
(int)source.len, source.str, port, addresses, (int)Curl_strlen(&source), Curl_str(&source), port, addresses,
permanent ? "" : " (non-permanent)"); permanent ? "" : " (non-permanent)");
#endif #endif
/* Wildcard hostname */ /* Wildcard hostname */
if((source.len == 1) && (source.str[0] == '*')) { if(Curl_str_casecompare(&source, "*")) {
infof(data, "RESOLVE *:%" CURL_FORMAT_CURL_OFF_T " using wildcard", infof(data, "RESOLVE *:%" CURL_FORMAT_CURL_OFF_T " using wildcard",
port); port);
data->state.wildcard_resolve = TRUE; data->state.wildcard_resolve = TRUE;

View File

@ -433,26 +433,26 @@ static CURLcode hsts_add(struct hsts *h, const char *line)
struct stsentry *e; struct stsentry *e;
char dbuf[MAX_HSTS_DATELEN + 1]; char dbuf[MAX_HSTS_DATELEN + 1];
time_t expires; time_t expires;
const char *hp = Curl_str(&host);
/* The date parser works on a null terminated string. The maximum length /* The date parser works on a null terminated string. The maximum length
is upheld by Curl_str_quotedword(). */ is upheld by Curl_str_quotedword(). */
memcpy(dbuf, date.str, date.len); memcpy(dbuf, Curl_str(&date), Curl_strlen(&date));
dbuf[date.len] = 0; dbuf[Curl_strlen(&date)] = 0;
expires = strcmp(dbuf, UNLIMITED) ? Curl_getdate_capped(dbuf) : expires = strcmp(dbuf, UNLIMITED) ? Curl_getdate_capped(dbuf) :
TIME_T_MAX; TIME_T_MAX;
if(host.str[0] == '.') { if(hp[0] == '.') {
host.str++; Curl_str_nudge(&host, 1);
host.len--;
subdomain = TRUE; subdomain = TRUE;
} }
/* only add it if not already present */ /* only add it if not already present */
e = Curl_hsts(h, host.str, host.len, subdomain); e = Curl_hsts(h, Curl_str(&host), Curl_strlen(&host), subdomain);
if(!e) if(!e)
result = hsts_create(h, host.str, host.len, subdomain, expires); result = hsts_create(h, Curl_str(&host), Curl_strlen(&host),
else if((strlen(e->host) == host.len) && subdomain, expires);
strncasecompare(host.str, e->host, host.len)) { else if(Curl_str_casecompare(&host, e->host)) {
/* the same hostname, use the largest expire time */ /* the same hostname, use the largest expire time */
if(expires > e->expires) if(expires > e->expires)
e->expires = expires; e->expires = expires;

View File

@ -652,7 +652,7 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data, bool proxy)
/* nothing to do */ /* nothing to do */
} }
if(!service.len) { if(!Curl_strlen(&service)) {
const char *p = hostname; const char *p = hostname;
if(Curl_str_until(&p, &service, MAX_SIGV4_LEN, '.') || if(Curl_str_until(&p, &service, MAX_SIGV4_LEN, '.') ||
Curl_str_single(&p, '.')) { Curl_str_single(&p, '.')) {
@ -662,9 +662,9 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data, bool proxy)
} }
infof(data, "aws_sigv4: picked service %.*s from host", infof(data, "aws_sigv4: picked service %.*s from host",
(int)service.len, service.str); (int)Curl_strlen(&service), Curl_str(&service));
if(!region.len) { if(!Curl_strlen(&region)) {
if(Curl_str_until(&p, &region, MAX_SIGV4_LEN, '.') || if(Curl_str_until(&p, &region, MAX_SIGV4_LEN, '.') ||
Curl_str_single(&p, '.')) { Curl_str_single(&p, '.')) {
failf(data, "aws-sigv4: region missing in parameters and hostname"); failf(data, "aws-sigv4: region missing in parameters and hostname");
@ -672,14 +672,15 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data, bool proxy)
goto fail; goto fail;
} }
infof(data, "aws_sigv4: picked region %.*s from host", infof(data, "aws_sigv4: picked region %.*s from host",
(int)region.len, region.str); (int)Curl_strlen(&region), Curl_str(&region));
} }
} }
Curl_http_method(data, conn, &method, &httpreq); Curl_http_method(data, conn, &method, &httpreq);
payload_hash = parse_content_sha_hdr(data, provider1.str, provider1.len, payload_hash =
&payload_hash_len); parse_content_sha_hdr(data, Curl_str(&provider1), Curl_strlen(&provider1),
&payload_hash_len);
if(!payload_hash) { if(!payload_hash) {
/* AWS S3 requires a x-amz-content-sha256 header, and supports special /* AWS S3 requires a x-amz-content-sha256 header, and supports special
@ -688,9 +689,9 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data, bool proxy)
Curl_str_casecompare(&service, "s3"); Curl_str_casecompare(&service, "s3");
if(sign_as_s3) if(sign_as_s3)
result = calc_s3_payload_hash(data, httpreq, result = calc_s3_payload_hash(data, httpreq, Curl_str(&provider1),
provider1.str, provider1.len, Curl_strlen(&provider1), sha_hash, sha_hex,
sha_hash, sha_hex, content_sha256_hdr); content_sha256_hdr);
else else
result = calc_payload_hash(data, sha_hash, sha_hex); result = calc_payload_hash(data, sha_hash, sha_hex);
if(result) if(result)
@ -722,7 +723,7 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data, bool proxy)
} }
result = make_headers(data, hostname, timestamp, result = make_headers(data, hostname, timestamp,
provider1.str, provider1.len, Curl_str(&provider1), Curl_strlen(&provider1),
&date_header, content_sha256_hdr, &date_header, content_sha256_hdr,
&canonical_headers, &signed_headers); &canonical_headers, &signed_headers);
if(result) if(result)
@ -767,17 +768,18 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data, bool proxy)
DEBUGF(infof(data, "Canonical request: %s", canonical_request)); DEBUGF(infof(data, "Canonical request: %s", canonical_request));
request_type = aprintf("%.*s4_request", (int)provider0.len, provider0.str); request_type = aprintf("%.*s4_request",
(int)Curl_strlen(&provider0), Curl_str(&provider0));
if(!request_type) if(!request_type)
goto fail; goto fail;
/* provider0 is lowercased *after* aprintf() so that the buffer can be /* provider0 is lowercased *after* aprintf() so that the buffer can be
written to */ written to */
Curl_strntolower(request_type, request_type, provider0.len); Curl_strntolower(request_type, request_type, Curl_strlen(&provider0));
credential_scope = aprintf("%s/%.*s/%.*s/%s", credential_scope = aprintf("%s/%.*s/%.*s/%s", date,
date, (int)region.len, region.str, (int)Curl_strlen(&region), Curl_str(&region),
(int)service.len, service.str, (int)Curl_strlen(&service), Curl_str(&service),
request_type); request_type);
if(!credential_scope) if(!credential_scope)
goto fail; goto fail;
@ -796,7 +798,7 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data, bool proxy)
"%s\n" /* RequestDateTime */ "%s\n" /* RequestDateTime */
"%s\n" /* CredentialScope */ "%s\n" /* CredentialScope */
"%s", /* HashedCanonicalRequest in hex */ "%s", /* HashedCanonicalRequest in hex */
(int)provider0.len, provider0.str, (int)Curl_strlen(&provider0), Curl_str(&provider0),
timestamp, timestamp,
credential_scope, credential_scope,
sha_hex); sha_hex);
@ -804,19 +806,21 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data, bool proxy)
goto fail; goto fail;
/* make provider0 part done uppercase */ /* make provider0 part done uppercase */
Curl_strntoupper(str_to_sign, provider0.str, provider0.len); Curl_strntoupper(str_to_sign, Curl_str(&provider0), Curl_strlen(&provider0));
secret = aprintf("%.*s4%s", (int)provider0.len, provider0.str, secret = aprintf("%.*s4%s", (int)Curl_strlen(&provider0),
data->state.aptr.passwd ? Curl_str(&provider0), data->state.aptr.passwd ?
data->state.aptr.passwd : ""); data->state.aptr.passwd : "");
if(!secret) if(!secret)
goto fail; goto fail;
/* make provider0 part done uppercase */ /* make provider0 part done uppercase */
Curl_strntoupper(secret, provider0.str, provider0.len); Curl_strntoupper(secret, Curl_str(&provider0), Curl_strlen(&provider0));
HMAC_SHA256(secret, strlen(secret), date, strlen(date), sign0); HMAC_SHA256(secret, strlen(secret), date, strlen(date), sign0);
HMAC_SHA256(sign0, sizeof(sign0), region.str, region.len, sign1); HMAC_SHA256(sign0, sizeof(sign0),
HMAC_SHA256(sign1, sizeof(sign1), service.str, service.len, sign0); Curl_str(&region), Curl_strlen(&region), sign1);
HMAC_SHA256(sign1, sizeof(sign1),
Curl_str(&service), Curl_strlen(&service), sign0);
HMAC_SHA256(sign0, sizeof(sign0), request_type, strlen(request_type), sign1); HMAC_SHA256(sign0, sizeof(sign0), request_type, strlen(request_type), sign1);
HMAC_SHA256(sign1, sizeof(sign1), str_to_sign, strlen(str_to_sign), sign0); HMAC_SHA256(sign1, sizeof(sign1), str_to_sign, strlen(str_to_sign), sign0);
@ -833,7 +837,7 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data, bool proxy)
*/ */
"%s" "%s"
"%s", /* optional sha256 header includes \r\n */ "%s", /* optional sha256 header includes \r\n */
(int)provider0.len, provider0.str, (int)Curl_strlen(&provider0), Curl_str(&provider0),
user, user,
credential_scope, credential_scope,
Curl_dyn_ptr(&signed_headers), Curl_dyn_ptr(&signed_headers),
@ -845,7 +849,7 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data, bool proxy)
} }
/* provider 0 uppercase */ /* provider 0 uppercase */
Curl_strntoupper(&auth_headers[sizeof("Authorization: ") - 1], Curl_strntoupper(&auth_headers[sizeof("Authorization: ") - 1],
provider0.str, provider0.len); Curl_str(&provider0), Curl_strlen(&provider0));
Curl_safefree(data->state.aptr.userpwd); Curl_safefree(data->state.aptr.userpwd);
data->state.aptr.userpwd = auth_headers; data->state.aptr.userpwd = auth_headers;

View File

@ -25,6 +25,12 @@
#include "strparse.h" #include "strparse.h"
#include "strcase.h" #include "strcase.h"
void Curl_str_init(struct Curl_str *out)
{
out->str = NULL;
out->len = 0;
}
/* Get a word until the first DELIM or end of string. At least one byte long. /* Get a word until the first DELIM or end of string. At least one byte long.
return non-zero on error */ return non-zero on error */
int Curl_str_until(const char **linep, struct Curl_str *out, int Curl_str_until(const char **linep, struct Curl_str *out,
@ -34,8 +40,7 @@ int Curl_str_until(const char **linep, struct Curl_str *out,
size_t len = 0; size_t len = 0;
DEBUGASSERT(linep && *linep && out && max && delim); DEBUGASSERT(linep && *linep && out && max && delim);
out->str = NULL; Curl_str_init(out);
out->len = 0;
while(*s && (*s != delim)) { while(*s && (*s != delim)) {
s++; s++;
if(++len > max) { if(++len > max) {
@ -68,8 +73,7 @@ int Curl_str_quotedword(const char **linep, struct Curl_str *out,
size_t len = 0; size_t len = 0;
DEBUGASSERT(linep && *linep && out && max); DEBUGASSERT(linep && *linep && out && max);
out->str = NULL; Curl_str_init(out);
out->len = 0;
if(*s != '\"') if(*s != '\"')
return STRE_BEGQUOTE; return STRE_BEGQUOTE;
s++; s++;
@ -226,8 +230,7 @@ int Curl_str_cspn(const char **linep, struct Curl_str *out, const char *reject)
*linep = &s[len]; *linep = &s[len];
return STRE_OK; return STRE_OK;
} }
out->str = NULL; Curl_str_init(out);
out->len = 0;
return STRE_SHORT; return STRE_SHORT;
} }

View File

@ -35,11 +35,18 @@
#define STRE_OVERFLOW 7 #define STRE_OVERFLOW 7
#define STRE_NO_NUM 8 #define STRE_NO_NUM 8
/* public struct, but all accesses should be done using the provided
functions */
struct Curl_str { struct Curl_str {
const char *str; const char *str;
size_t len; size_t len;
}; };
void Curl_str_init(struct Curl_str *out);
#define Curl_str(x) ((x)->str)
#define Curl_strlen(x) ((x)->len)
/* Get a word until the first space /* Get a word until the first space
return non-zero on error */ return non-zero on error */
int Curl_str_word(const char **linep, struct Curl_str *out, const size_t max); int Curl_str_word(const char **linep, struct Curl_str *out, const size_t max);