diff --git a/src/pack_unpack.c b/src/pack_unpack.c index fc98df4..ec04bc3 100644 --- a/src/pack_unpack.c +++ b/src/pack_unpack.c @@ -261,7 +261,7 @@ static json_t *pack_object(scanner_t *s, va_list *ap) jsonp_free(key); if(valueOptional != '*') { - set_error(s, "", json_error_null_value, "NULL object value\n"); + set_error(s, "", json_error_null_value, "NULL object value"); s->has_error = 1; } @@ -396,11 +396,47 @@ static json_t *pack_object_inter(scanner_t *s, va_list *ap, int need_incref) break; } - set_error(s, "", json_error_null_value, "NULL object key"); + set_error(s, "", json_error_null_value, "NULL object"); s->has_error = 1; return NULL; } +static json_t *pack_integer(scanner_t *s, json_int_t value) +{ + json_t *json = json_integer(value); + + if (!json) { + set_error(s, "", json_error_out_of_memory, "Out of memory"); + s->has_error = 1; + } + + return json; +} + +static json_t *pack_real(scanner_t *s, double value) +{ + /* Allocate without setting value so we can identify OOM error. */ + json_t *json = json_real(0.0); + + if (!json) { + set_error(s, "", json_error_out_of_memory, "Out of memory"); + s->has_error = 1; + + return NULL; + } + + if (json_real_set(json, value)) { + json_decref(json); + + set_error(s, "", json_error_numeric_overflow, "Invalid floating point value"); + s->has_error = 1; + + return NULL; + } + + return json; +} + static json_t *pack(scanner_t *s, va_list *ap) { switch(token(s)) { @@ -420,13 +456,13 @@ static json_t *pack(scanner_t *s, va_list *ap) return va_arg(*ap, int) ? json_true() : json_false(); case 'i': /* integer from int */ - return json_integer(va_arg(*ap, int)); + return pack_integer(s, va_arg(*ap, int)); case 'I': /* integer from json_int_t */ - return json_integer(va_arg(*ap, json_int_t)); + return pack_integer(s, va_arg(*ap, json_int_t)); case 'f': /* real */ - return json_real(va_arg(*ap, double)); + return pack_real(s, va_arg(*ap, double)); case 'O': /* a json_t object; increments refcount */ return pack_object_inter(s, ap, 1); diff --git a/test/suites/api/test_pack.c b/test/suites/api/test_pack.c index 7e1c0b5..ab3aa91 100644 --- a/test/suites/api/test_pack.c +++ b/test/suites/api/test_pack.c @@ -15,8 +15,39 @@ #include #include #include +#include #include "util.h" +#ifdef INFINITY +// This test triggers "warning C4756: overflow in constant arithmetic" +// in Visual Studio. This warning is triggered here by design, so disable it. +// (This can only be done on function level so we keep these tests separate) +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning (disable: 4756) +#endif +static void test_inifity() +{ + json_error_t error; + + if (json_pack_ex(&error, 0, "f", INFINITY)) + fail("json_pack infinity incorrectly succeeded"); + check_error(json_error_numeric_overflow, "Invalid floating point value", "", 1, 1, 1); + + if (json_pack_ex(&error, 0, "[f]", INFINITY)) + fail("json_pack infinity array element incorrectly succeeded"); + check_error(json_error_numeric_overflow, "Invalid floating point value", "", 1, 2, 2); + + if (json_pack_ex(&error, 0, "{s:f}", "key", INFINITY)) + fail("json_pack infinity object value incorrectly succeeded"); + check_error(json_error_numeric_overflow, "Invalid floating point value", "", 1, 4, 4); + +#ifdef _MSC_VER +#pragma warning(pop) +#endif +} +#endif // INFINITY + static void run_tests() { json_t *value; @@ -313,6 +344,25 @@ static void run_tests() fail("json_pack array optional failed"); json_decref(value); +#ifdef NAN + /* Invalid float values */ + if (json_pack_ex(&error, 0, "f", NAN)) + fail("json_pack NAN incorrectly succeeded"); + check_error(json_error_numeric_overflow, "Invalid floating point value", "", 1, 1, 1); + + if (json_pack_ex(&error, 0, "[f]", NAN)) + fail("json_pack NAN array element incorrectly succeeded"); + check_error(json_error_numeric_overflow, "Invalid floating point value", "", 1, 2, 2); + + if (json_pack_ex(&error, 0, "{s:f}", "key", NAN)) + fail("json_pack NAN object value incorrectly succeeded"); + check_error(json_error_numeric_overflow, "Invalid floating point value", "", 1, 4, 4); +#endif + +#ifdef INFINITY + test_inifity(); +#endif + /* Whitespace; regular string */ value = json_pack(" s\t ", "test"); if(!json_is_string(value) || strcmp("test", json_string_value(value))) @@ -439,9 +489,9 @@ static void run_tests() if(json_pack_ex(&error, 0, "{s:o}", "foo", NULL)) fail("json_pack failed to catch nullable object"); - check_error(json_error_null_value, "NULL object key", "", 1, 4, 4); + check_error(json_error_null_value, "NULL object", "", 1, 4, 4); if(json_pack_ex(&error, 0, "{s:O}", "foo", NULL)) fail("json_pack failed to catch nullable incref object"); - check_error(json_error_null_value, "NULL object key", "", 1, 4, 4); + check_error(json_error_null_value, "NULL object", "", 1, 4, 4); }