json: Improve handling of large exponents in the JSON parsor.

* src/cJSON.c: Include stdint.h.
(parse_number): Avoid overflob in SUBSCALE and cap integer values.
--

GnuPG-bug-id: 4330
Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
Werner Koch 2019-06-04 10:42:40 +02:00
parent 1024884e07
commit fabe96126b
No known key found for this signature in database
GPG Key ID: E3FDFF218E45B72B

View File

@ -40,6 +40,7 @@
#include <stdio.h> #include <stdio.h>
#include <math.h> #include <math.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdint.h>
#include <float.h> #include <float.h>
#include <limits.h> #include <limits.h>
#include <ctype.h> #include <ctype.h>
@ -146,8 +147,13 @@ cJSON_Delete (cJSON * c)
static const char * static const char *
parse_number (cJSON * item, const char *num) parse_number (cJSON * item, const char *num)
{ {
double n = 0, sign = 1, scale = 0; int subscale = 0;
int subscale = 0, signsubscale = 1; int signsubscale = 1;
double n = 0;
double sign = 1;
double scale = 0;
double dblmin = INT32_MIN;
double dblmax = INT32_MAX;
if (*num == '-') if (*num == '-')
sign = -1, num++; /* Has sign? */ sign = -1, num++; /* Has sign? */
@ -169,17 +175,37 @@ parse_number (cJSON * item, const char *num)
num++; num++;
if (*num == '+') if (*num == '+')
num++; num++;
else if (*num == '-') else if (*num == '-') /* With sign? */
signsubscale = -1, num++; /* With sign? */ signsubscale = -1, num++;
while (*num >= '0' && *num <= '9') while (*num >= '0' && *num <= '9')
subscale = (subscale * 10) + (*num++ - '0'); /* Number? */ {
if ((10 * (double)subscale) > dblmax)
break;
subscale = (subscale * 10) + (*num++ - '0');
}
} }
/* number = +/- number.fraction * 10^+/- exponent */ /* number = +/- number.fraction * 10^+/- exponent */
n = sign * n * pow (10.0, (scale + subscale * signsubscale)); n = sign * n * pow (10.0, (scale + subscale * signsubscale));
/* For NAN set both parts to 0. For out of range values let the
* integer part be 0. */
if (isnan (n) || isinf (n))
{
item->valuedouble = 0;
item->valueint = 0;
}
else if (n > dblmax || n < dblmin)
{
item->valuedouble = n;
item->valueint = 0;
}
else
{
item->valuedouble = n; item->valuedouble = n;
item->valueint = (int)n; item->valueint = (int)n;
}
item->type = cJSON_Number; item->type = cJSON_Number;
return num; return num;
} }