mirror of
https://github.com/curl/curl.git
synced 2025-09-10 14:12:41 +03:00
mprintf: switch three number parsers to use strparse
Also add more const char pointers and reduced the scope for some variables. Closes #16628
This commit is contained in:
parent
8dca3b0656
commit
f8e7a4df94
109
lib/mprintf.c
109
lib/mprintf.c
|
@ -25,6 +25,7 @@
|
||||||
#include "curl_setup.h"
|
#include "curl_setup.h"
|
||||||
#include "dynbuf.h"
|
#include "dynbuf.h"
|
||||||
#include "curl_printf.h"
|
#include "curl_printf.h"
|
||||||
|
#include "strparse.h"
|
||||||
|
|
||||||
#include "curl_memory.h"
|
#include "curl_memory.h"
|
||||||
/* The last #include file should be: */
|
/* The last #include file should be: */
|
||||||
|
@ -134,7 +135,7 @@ enum {
|
||||||
struct va_input {
|
struct va_input {
|
||||||
FormatType type; /* FormatType */
|
FormatType type; /* FormatType */
|
||||||
union {
|
union {
|
||||||
char *str;
|
const char *str;
|
||||||
void *ptr;
|
void *ptr;
|
||||||
mp_intmax_t nums; /* signed */
|
mp_intmax_t nums; /* signed */
|
||||||
mp_uintmax_t numu; /* unsigned */
|
mp_uintmax_t numu; /* unsigned */
|
||||||
|
@ -150,7 +151,7 @@ struct outsegment {
|
||||||
int precision; /* precision OR precision parameter number */
|
int precision; /* precision OR precision parameter number */
|
||||||
unsigned int flags;
|
unsigned int flags;
|
||||||
unsigned int input; /* input argument array index */
|
unsigned int input; /* input argument array index */
|
||||||
char *start; /* format string start to output */
|
const char *start; /* format string start to output */
|
||||||
size_t outlen; /* number of bytes from the format string to output */
|
size_t outlen; /* number of bytes from the format string to output */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -169,26 +170,19 @@ struct asprintf {
|
||||||
|
|
||||||
returns -1 if no valid number was provided.
|
returns -1 if no valid number was provided.
|
||||||
*/
|
*/
|
||||||
static int dollarstring(char *input, char **end)
|
static int dollarstring(const char *p, const char **end)
|
||||||
{
|
{
|
||||||
if(ISDIGIT(*input)) {
|
curl_off_t num;
|
||||||
int number = 0;
|
if(Curl_str_number(&p, &num, MAX_PARAMETERS) ||
|
||||||
do {
|
Curl_str_single(&p, '$') || !num)
|
||||||
if(number < MAX_PARAMETERS) {
|
return -1;
|
||||||
number *= 10;
|
*end = p;
|
||||||
number += *input - '0';
|
return (int)num - 1;
|
||||||
}
|
|
||||||
input++;
|
|
||||||
} while(ISDIGIT(*input));
|
|
||||||
|
|
||||||
if(number && (number <= MAX_PARAMETERS) && ('$' == *input)) {
|
|
||||||
*end = ++input;
|
|
||||||
return number - 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define is_arg_used(x,y) ((x)[(y)/8] & (1 << ((y)&7)))
|
||||||
|
#define mark_arg_used(x,y) ((x)[y/8] |= (unsigned char)(1 << ((y)&7)))
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Parse the format string.
|
* Parse the format string.
|
||||||
*
|
*
|
||||||
|
@ -216,13 +210,8 @@ static int parsefmt(const char *format,
|
||||||
int *opieces,
|
int *opieces,
|
||||||
int *ipieces, va_list arglist)
|
int *ipieces, va_list arglist)
|
||||||
{
|
{
|
||||||
char *fmt = (char *)format;
|
const char *fmt = format;
|
||||||
int param_num = 0;
|
int param_num = 0;
|
||||||
int param;
|
|
||||||
int width;
|
|
||||||
int precision;
|
|
||||||
unsigned int flags;
|
|
||||||
FormatType type;
|
|
||||||
int max_param = -1;
|
int max_param = -1;
|
||||||
int i;
|
int i;
|
||||||
int ocount = 0;
|
int ocount = 0;
|
||||||
|
@ -230,7 +219,7 @@ static int parsefmt(const char *format,
|
||||||
size_t outlen = 0;
|
size_t outlen = 0;
|
||||||
struct outsegment *optr;
|
struct outsegment *optr;
|
||||||
int use_dollar = DOLLAR_UNKNOWN;
|
int use_dollar = DOLLAR_UNKNOWN;
|
||||||
char *start = fmt;
|
const char *start = fmt;
|
||||||
|
|
||||||
/* clear, set a bit for each used input */
|
/* clear, set a bit for each used input */
|
||||||
memset(usedinput, 0, sizeof(usedinput));
|
memset(usedinput, 0, sizeof(usedinput));
|
||||||
|
@ -239,6 +228,11 @@ static int parsefmt(const char *format,
|
||||||
if(*fmt == '%') {
|
if(*fmt == '%') {
|
||||||
struct va_input *iptr;
|
struct va_input *iptr;
|
||||||
bool loopit = TRUE;
|
bool loopit = TRUE;
|
||||||
|
FormatType type;
|
||||||
|
unsigned int flags = 0;
|
||||||
|
int width = 0;
|
||||||
|
int precision = 0;
|
||||||
|
int param = -1;
|
||||||
fmt++;
|
fmt++;
|
||||||
outlen = (size_t)(fmt - start - 1);
|
outlen = (size_t)(fmt - start - 1);
|
||||||
if(*fmt == '%') {
|
if(*fmt == '%') {
|
||||||
|
@ -258,9 +252,6 @@ static int parsefmt(const char *format,
|
||||||
continue; /* while */
|
continue; /* while */
|
||||||
}
|
}
|
||||||
|
|
||||||
flags = 0;
|
|
||||||
width = precision = 0;
|
|
||||||
|
|
||||||
if(use_dollar != DOLLAR_NOPE) {
|
if(use_dollar != DOLLAR_NOPE) {
|
||||||
param = dollarstring(fmt, &fmt);
|
param = dollarstring(fmt, &fmt);
|
||||||
if(param < 0) {
|
if(param < 0) {
|
||||||
|
@ -275,8 +266,6 @@ static int parsefmt(const char *format,
|
||||||
else
|
else
|
||||||
use_dollar = DOLLAR_USE;
|
use_dollar = DOLLAR_USE;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
param = -1;
|
|
||||||
|
|
||||||
/* Handle the flags */
|
/* Handle the flags */
|
||||||
while(loopit) {
|
while(loopit) {
|
||||||
|
@ -311,20 +300,15 @@ static int parsefmt(const char *format,
|
||||||
precision = -1;
|
precision = -1;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
bool is_neg = FALSE;
|
bool is_neg;
|
||||||
|
curl_off_t num;
|
||||||
flags |= FLAGS_PREC;
|
flags |= FLAGS_PREC;
|
||||||
precision = 0;
|
is_neg = ('-' == *fmt);
|
||||||
if('-' == *fmt) {
|
if(is_neg)
|
||||||
is_neg = TRUE;
|
|
||||||
fmt++;
|
fmt++;
|
||||||
}
|
if(Curl_str_number(&fmt, &num, INT_MAX))
|
||||||
while(ISDIGIT(*fmt)) {
|
return PFMT_PREC;
|
||||||
int n = *fmt - '0';
|
precision = (int)num;
|
||||||
if(precision > (INT_MAX - n) / 10)
|
|
||||||
return PFMT_PREC;
|
|
||||||
precision = precision * 10 + n;
|
|
||||||
fmt++;
|
|
||||||
}
|
|
||||||
if(is_neg)
|
if(is_neg)
|
||||||
precision = -precision;
|
precision = -precision;
|
||||||
}
|
}
|
||||||
|
@ -390,18 +374,15 @@ static int parsefmt(const char *format,
|
||||||
flags |= FLAGS_PAD_NIL;
|
flags |= FLAGS_PAD_NIL;
|
||||||
FALLTHROUGH();
|
FALLTHROUGH();
|
||||||
case '1': case '2': case '3': case '4':
|
case '1': case '2': case '3': case '4':
|
||||||
case '5': case '6': case '7': case '8': case '9':
|
case '5': case '6': case '7': case '8': case '9': {
|
||||||
|
curl_off_t num;
|
||||||
flags |= FLAGS_WIDTH;
|
flags |= FLAGS_WIDTH;
|
||||||
width = 0;
|
|
||||||
fmt--;
|
fmt--;
|
||||||
do {
|
if(Curl_str_number(&fmt, &num, INT_MAX))
|
||||||
int n = *fmt - '0';
|
return PFMT_WIDTH;
|
||||||
if(width > (INT_MAX - n) / 10)
|
width = (int)num;
|
||||||
return PFMT_WIDTH;
|
|
||||||
width = width * 10 + n;
|
|
||||||
fmt++;
|
|
||||||
} while(ISDIGIT(*fmt));
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case '*': /* read width from argument list */
|
case '*': /* read width from argument list */
|
||||||
flags |= FLAGS_WIDTHPARAM;
|
flags |= FLAGS_WIDTHPARAM;
|
||||||
if(use_dollar == DOLLAR_USE) {
|
if(use_dollar == DOLLAR_USE) {
|
||||||
|
@ -511,9 +492,8 @@ static int parsefmt(const char *format,
|
||||||
if(width < 0)
|
if(width < 0)
|
||||||
width = param_num++;
|
width = param_num++;
|
||||||
else {
|
else {
|
||||||
/* if this identifies a parameter already used, this
|
/* if this identifies a parameter already used, this is illegal */
|
||||||
is illegal */
|
if(is_arg_used(usedinput, width))
|
||||||
if(usedinput[width/8] & (1 << (width&7)))
|
|
||||||
return PFMT_WIDTHARG;
|
return PFMT_WIDTHARG;
|
||||||
}
|
}
|
||||||
if(width >= MAX_PARAMETERS)
|
if(width >= MAX_PARAMETERS)
|
||||||
|
@ -523,16 +503,15 @@ static int parsefmt(const char *format,
|
||||||
|
|
||||||
in[width].type = FORMAT_WIDTH;
|
in[width].type = FORMAT_WIDTH;
|
||||||
/* mark as used */
|
/* mark as used */
|
||||||
usedinput[width/8] |= (unsigned char)(1 << (width&7));
|
mark_arg_used(usedinput, width);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(flags & FLAGS_PRECPARAM) {
|
if(flags & FLAGS_PRECPARAM) {
|
||||||
if(precision < 0)
|
if(precision < 0)
|
||||||
precision = param_num++;
|
precision = param_num++;
|
||||||
else {
|
else {
|
||||||
/* if this identifies a parameter already used, this
|
/* if this identifies a parameter already used, this is illegal */
|
||||||
is illegal */
|
if(is_arg_used(usedinput, precision))
|
||||||
if(usedinput[precision/8] & (1 << (precision&7)))
|
|
||||||
return PFMT_PRECARG;
|
return PFMT_PRECARG;
|
||||||
}
|
}
|
||||||
if(precision >= MAX_PARAMETERS)
|
if(precision >= MAX_PARAMETERS)
|
||||||
|
@ -541,7 +520,7 @@ static int parsefmt(const char *format,
|
||||||
max_param = precision;
|
max_param = precision;
|
||||||
|
|
||||||
in[precision].type = FORMAT_PRECISION;
|
in[precision].type = FORMAT_PRECISION;
|
||||||
usedinput[precision/8] |= (unsigned char)(1 << (precision&7));
|
mark_arg_used(usedinput, precision);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handle the specifier */
|
/* Handle the specifier */
|
||||||
|
@ -556,7 +535,7 @@ static int parsefmt(const char *format,
|
||||||
iptr->type = type;
|
iptr->type = type;
|
||||||
|
|
||||||
/* mark this input as used */
|
/* mark this input as used */
|
||||||
usedinput[param/8] |= (unsigned char)(1 << (param&7));
|
mark_arg_used(usedinput, param);
|
||||||
|
|
||||||
fmt++;
|
fmt++;
|
||||||
optr = &out[ocount++];
|
optr = &out[ocount++];
|
||||||
|
@ -589,14 +568,14 @@ static int parsefmt(const char *format,
|
||||||
/* Read the arg list parameters into our data list */
|
/* Read the arg list parameters into our data list */
|
||||||
for(i = 0; i < max_param + 1; i++) {
|
for(i = 0; i < max_param + 1; i++) {
|
||||||
struct va_input *iptr = &in[i];
|
struct va_input *iptr = &in[i];
|
||||||
if(!(usedinput[i/8] & (1 << (i&7))))
|
if(!is_arg_used(usedinput, i))
|
||||||
/* bad input */
|
/* bad input */
|
||||||
return PFMT_INPUTGAP;
|
return PFMT_INPUTGAP;
|
||||||
|
|
||||||
/* based on the type, read the correct argument */
|
/* based on the type, read the correct argument */
|
||||||
switch(iptr->type) {
|
switch(iptr->type) {
|
||||||
case FORMAT_STRING:
|
case FORMAT_STRING:
|
||||||
iptr->val.str = va_arg(arglist, char *);
|
iptr->val.str = va_arg(arglist, const char *);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FORMAT_INTPTR:
|
case FORMAT_INTPTR:
|
||||||
|
@ -704,7 +683,7 @@ static int formatf(
|
||||||
unsigned int flags = optr->flags;
|
unsigned int flags = optr->flags;
|
||||||
|
|
||||||
if(outlen) {
|
if(outlen) {
|
||||||
char *str = optr->start;
|
const char *str = optr->start;
|
||||||
for(; outlen && *str; outlen--)
|
for(; outlen && *str; outlen--)
|
||||||
OUTCHAR(*str++);
|
OUTCHAR(*str++);
|
||||||
if(optr->flags & FLAGS_SUBSTR)
|
if(optr->flags & FLAGS_SUBSTR)
|
||||||
|
@ -873,7 +852,7 @@ number:
|
||||||
const char *str;
|
const char *str;
|
||||||
size_t len;
|
size_t len;
|
||||||
|
|
||||||
str = (char *)iptr->val.str;
|
str = iptr->val.str;
|
||||||
if(!str) {
|
if(!str) {
|
||||||
/* Write null string if there is space. */
|
/* Write null string if there is space. */
|
||||||
if(prec == -1 || prec >= (int) sizeof(nilstr) - 1) {
|
if(prec == -1 || prec >= (int) sizeof(nilstr) - 1) {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user