summaryrefslogtreecommitdiff
path: root/lib/mprintf.c
diff options
context:
space:
mode:
authorTobias Stoeckmann <tobias@stoeckmann.org>2020-07-25 17:29:38 +0200
committerJay Satiro <raysatiro@yahoo.com>2020-07-27 03:42:59 -0400
commit94b03664decf47429ad426afb40ae5fe1aff28cf (patch)
treecc340a4b78a1e1f1852788574ae4e911efd491ec /lib/mprintf.c
parent376d5bb323c03c0fc4af266c03abac8f067fbd0e (diff)
downloadcurl-94b03664decf47429ad426afb40ae5fe1aff28cf.tar.gz
mprintf: Fix dollar string handling
Verify that specified parameters are in range. If parameters are too large, fail early on and avoid out of boundary accesses. Also do not read behind boundaries of illegal format strings. These are defensive measures since it is expected that format strings are well-formed. Format strings should not be modifiable by user input due to possible generic format string attacks. Closes https://github.com/curl/curl/pull/5722
Diffstat (limited to 'lib/mprintf.c')
-rw-r--r--lib/mprintf.c20
1 files changed, 15 insertions, 5 deletions
diff --git a/lib/mprintf.c b/lib/mprintf.c
index 63c9d11a5..7af2f4a83 100644
--- a/lib/mprintf.c
+++ b/lib/mprintf.c
@@ -178,12 +178,14 @@ static long dprintf_DollarString(char *input, char **end)
{
int number = 0;
while(ISDIGIT(*input)) {
- number *= 10;
- number += *input-'0';
+ if(number < MAX_PARAMETERS) {
+ number *= 10;
+ number += *input - '0';
+ }
input++;
}
- if(number && ('$'==*input++)) {
- *end = input;
+ if(number <= MAX_PARAMETERS && ('$' == *input)) {
+ *end = ++input;
return number;
}
return 0;
@@ -377,6 +379,8 @@ static int dprintf_Pass1(const char *format, struct va_stack *vto,
if(width > max_param)
max_param = width;
break;
+ case '\0':
+ fmt--;
default:
break;
}
@@ -458,6 +462,9 @@ static int dprintf_Pass1(const char *format, struct va_stack *vto,
/* we have the width specified from a parameter, so we make that
parameter's info setup properly */
long k = width - 1;
+ if((k < 0) || (k >= MAX_PARAMETERS))
+ /* out of allowed range */
+ return 1;
vto[i].width = k;
vto[k].type = FORMAT_WIDTH;
vto[k].flags = FLAGS_NEW;
@@ -469,6 +476,9 @@ static int dprintf_Pass1(const char *format, struct va_stack *vto,
/* we have the precision specified from a parameter, so we make that
parameter's info setup properly */
long k = precision - 1;
+ if((k < 0) || (k >= MAX_PARAMETERS))
+ /* out of allowed range */
+ return 1;
vto[i].precision = k;
vto[k].type = FORMAT_WIDTH;
vto[k].flags = FLAGS_NEW;
@@ -476,7 +486,7 @@ static int dprintf_Pass1(const char *format, struct va_stack *vto,
vto[k].width = 0;
vto[k].precision = 0;
}
- *endpos++ = fmt + 1; /* end of this sequence */
+ *endpos++ = fmt + ((*fmt == '\0') ? 0 : 1); /* end of this sequence */
}
}