Merge pull request #109 from kdopen/use_strtod
Avoid potential overflow in json_object_get_double
This commit is contained in:
@@ -17,6 +17,7 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
#include "printbuf.h"
|
#include "printbuf.h"
|
||||||
@@ -636,6 +637,7 @@ void json_object_free_userdata(struct json_object *jso, void *userdata)
|
|||||||
double json_object_get_double(struct json_object *jso)
|
double json_object_get_double(struct json_object *jso)
|
||||||
{
|
{
|
||||||
double cdouble;
|
double cdouble;
|
||||||
|
char *errPtr = NULL;
|
||||||
|
|
||||||
if(!jso) return 0.0;
|
if(!jso) return 0.0;
|
||||||
switch(jso->o_type) {
|
switch(jso->o_type) {
|
||||||
@@ -646,7 +648,36 @@ double json_object_get_double(struct json_object *jso)
|
|||||||
case json_type_boolean:
|
case json_type_boolean:
|
||||||
return jso->o.c_boolean;
|
return jso->o.c_boolean;
|
||||||
case json_type_string:
|
case json_type_string:
|
||||||
if(sscanf(jso->o.c_string.str, "%lf", &cdouble) == 1) return cdouble;
|
errno = 0;
|
||||||
|
cdouble = strtod(jso->o.c_string.str,&errPtr);
|
||||||
|
|
||||||
|
/* if conversion stopped at the first character, return 0.0 */
|
||||||
|
if (errPtr == jso->o.c_string.str)
|
||||||
|
return 0.0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check that the conversion terminated on something sensible
|
||||||
|
*
|
||||||
|
* For example, { "pay" : 123AB } would parse as 123.
|
||||||
|
*/
|
||||||
|
if (*errPtr != '\0')
|
||||||
|
return 0.0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If strtod encounters a string which would exceed the
|
||||||
|
* capacity of a double, it returns +/- HUGE_VAL and sets
|
||||||
|
* errno to ERANGE. But +/- HUGE_VAL is also a valid result
|
||||||
|
* from a conversion, so we need to check errno.
|
||||||
|
*
|
||||||
|
* Underflow also sets errno to ERANGE, but it returns 0 in
|
||||||
|
* that case, which is what we will return anyway.
|
||||||
|
*
|
||||||
|
* See CERT guideline ERR30-C
|
||||||
|
*/
|
||||||
|
if ((HUGE_VAL == cdouble || -HUGE_VAL == cdouble) &&
|
||||||
|
(ERANGE == errno))
|
||||||
|
cdouble = 0.0;
|
||||||
|
return cdouble;
|
||||||
default:
|
default:
|
||||||
return 0.0;
|
return 0.0;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user