From 86ac471dc62893f47bce3cb0aa6c797588056384 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 5 Mar 2025 10:02:36 +0100 Subject: [PATCH] tool_paramhlp: do --proto parsing without strtok Saves a strdup. Avoids a banned function. Closes #16567 --- src/tool_paramhlp.c | 73 ++++++++++++++++++++++----------------------- 1 file changed, 35 insertions(+), 38 deletions(-) diff --git a/src/tool_paramhlp.c b/src/tool_paramhlp.c index 7cd1354a66..76792a0099 100644 --- a/src/tool_paramhlp.c +++ b/src/tool_paramhlp.c @@ -424,9 +424,6 @@ static void protoset_clear(const char **protoset, const char *proto) ParameterError proto2num(struct OperationConfig *config, const char * const *val, char **ostr, const char *str) { - char *buffer; - const char *sep = ","; - char *token; const char **protoset; struct curlx_dynbuf obuf; size_t proto; @@ -434,18 +431,9 @@ ParameterError proto2num(struct OperationConfig *config, curlx_dyn_init(&obuf, MAX_PROTOSTRING); - if(!str) - return PARAM_OPTION_AMBIGUOUS; - - buffer = strdup(str); /* because strtok corrupts it */ - if(!buffer) - return PARAM_NO_MEM; - protoset = malloc((proto_count + 1) * sizeof(*protoset)); - if(!protoset) { - free(buffer); + if(!protoset) return PARAM_NO_MEM; - } /* Preset protocol set with default values. */ protoset[0] = NULL; @@ -456,33 +444,35 @@ ParameterError proto2num(struct OperationConfig *config, protoset_set(protoset, p); } - /* Allow strtok() here since this is not used threaded */ - /* !checksrc! disable BANNEDFUNC 2 */ - for(token = strtok(buffer, sep); - token; - token = strtok(NULL, sep)) { + while(*str) { + const char *next = strchr(str, ','); + size_t plen; enum e_action { allow, deny, set } action = allow; + if(next) + plen = next - str - 1; + else + plen = strlen(str) - 1; + /* Process token modifiers */ - while(!ISALNUM(*token)) { /* may be NULL if token is all modifiers */ - switch(*token++) { - case '=': - action = set; - break; - case '-': - action = deny; - break; - case '+': - action = allow; - break; - default: /* Includes case of terminating NULL */ - free(buffer); - free((char *) protoset); - return PARAM_BAD_USE; - } + switch(*str++) { + case '=': + action = set; + break; + case '-': + action = deny; + break; + case '+': + action = allow; + break; + default: + /* no modifier */ + str--; + plen++; + break; } - if(curl_strequal(token, "all")) { + if((plen == 3) && curl_strnequal(str, "all", 3)) { switch(action) { case deny: protoset[0] = NULL; @@ -495,7 +485,11 @@ ParameterError proto2num(struct OperationConfig *config, } } else { - const char *p = proto_token(token); + char buffer[32]; + const char *p; + msnprintf(buffer, sizeof(buffer), "%.*s", (int)plen, str); + + p = proto_token(buffer); if(p) switch(action) { @@ -514,11 +508,14 @@ ParameterError proto2num(struct OperationConfig *config, if no protocols are allowed */ if(action == set) protoset[0] = NULL; - warnf(config->global, "unrecognized protocol '%s'", token); + warnf(config->global, "unrecognized protocol '%s'", buffer); } } + if(next) + str = next + 1; + else + break; } - free(buffer); /* We need the protocols in alphabetic order for CI tests requirements. */ qsort((char *) protoset, protoset_index(protoset, NULL), sizeof(*protoset), -- 2.47.3