diff options
author | Eric Haszlakiewicz <erh+git@nimenees.com> | 2014-02-11 23:13:19 -0500 |
---|---|---|
committer | Eric Haszlakiewicz <erh+git@nimenees.com> | 2014-02-11 23:13:19 -0500 |
commit | ceeaf42bc80f84a4ffab6660f4a062d4efef13cd (patch) | |
tree | bbc4c6d778c7e02a72f3dc998923fe038027981a | |
parent | b821f0e10f20b35769d13ab9bac96c5973914854 (diff) | |
parent | c51b88d69a3bb70f7bfed3f78a9283726cc827dd (diff) |
Merge pull request #109 from kdopen/use_strtod
Avoid potential overflow in json_object_get_double
-rw-r--r-- | json_object.c | 33 |
1 files changed, 32 insertions, 1 deletions
diff --git a/json_object.c b/json_object.c index faf6193..377ab59 100644 --- a/json_object.c +++ b/json_object.c @@ -17,6 +17,7 @@ #include <stddef.h> #include <string.h> #include <math.h> +#include <errno.h> #include "debug.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 cdouble; + char *errPtr = NULL; if(!jso) return 0.0; switch(jso->o_type) { @@ -646,7 +648,36 @@ double json_object_get_double(struct json_object *jso) case json_type_boolean: return jso->o.c_boolean; 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: return 0.0; } |