From 61287aea590bb00824fa693d19c59d45d3e58a19 Mon Sep 17 00:00:00 2001 From: "Hossein.M" <hossein.m9877@gmail.com> Date: Sun, 17 Apr 2022 19:21:09 +0430 Subject: [PATCH 1/4] Fix error: too few arguments --- samples/src/example.c | 57 +++++++-------- tests/src/test.c | 158 +++++++++++++++++++++++------------------- 2 files changed, 114 insertions(+), 101 deletions(-) diff --git a/samples/src/example.c b/samples/src/example.c index da00594..62a56b7 100644 --- a/samples/src/example.c +++ b/samples/src/example.c @@ -51,45 +51,45 @@ struct data { /* Add a time object property in a JSON string. "name":{"temp":-5,"hum":48}, */ -char* json_weather( char* dest, char const* name, struct weather const* weather ) { - dest = json_objOpen( dest, name ); // --> "name":{\0 - dest = json_int( dest, "temp", weather->temp ); // --> "name":{"temp":22,\0 - dest = json_int( dest, "hum", weather->hum ); // --> "name":{"temp":22,"hum":45,\0 - dest = json_objClose( dest ); // --> "name":{"temp":22,"hum":45},\0 +char* json_weather( char* dest, char const* name, struct weather const* weather, size_t* remLen ) { + dest = json_objOpen( dest, name, remLen ); // --> "name":{\0 + dest = json_int( dest, "temp", weather->temp, remLen ); // --> "name":{"temp":22,\0 + dest = json_int( dest, "hum", weather->hum, remLen ); // --> "name":{"temp":22,"hum":45,\0 + dest = json_objClose( dest, remLen ); // --> "name":{"temp":22,"hum":45},\0 return dest; } /* Add a time object property in a JSON string. "name":{"hour":18,"minute":32}, */ -char* json_time( char* dest, char const* name, struct time const* time ) { - dest = json_objOpen( dest, name ); - dest = json_int( dest, "hour", time->hour ); - dest = json_int( dest, "minute", time->minute ); - dest = json_objClose( dest ); +char* json_time( char* dest, char const* name, struct time const* time, size_t* remLen ) { + dest = json_objOpen( dest, name, remLen ); + dest = json_int( dest, "hour", time->hour, remLen ); + dest = json_int( dest, "minute", time->minute, remLen ); + dest = json_objClose( dest, remLen ); return dest; } /* Add a measure object property in a JSON string. "name":{"weather":{"temp":-5,"hum":48},"time":{"hour":18,"minute":32}}, */ -char* json_measure( char* dest, char const* name, struct measure const* measure ) { - dest = json_objOpen( dest, name ); - dest = json_weather( dest, "weather", &measure->weather ); - dest = json_time( dest, "time", &measure->time ); - dest = json_objClose( dest ); +char* json_measure( char* dest, char const* name, struct measure const* measure, size_t* remLen ) { + dest = json_objOpen( dest, name, remLen ); + dest = json_weather( dest, "weather", &measure->weather, remLen ); + dest = json_time( dest, "time", &measure->time, remLen ); + dest = json_objClose( dest, remLen ); return dest; } /* Add a data object property in a JSON string. */ -char* json_data( char* dest, char const* name, struct data const* data ) { - dest = json_objOpen( dest, NULL ); - dest = json_str( dest, "city", data->city ); - dest = json_str( dest, "street", data->street ); - dest = json_measure( dest, "measure", &data->measure ); - dest = json_arrOpen( dest, "samples" ); +char* json_data( char* dest, char const* name, struct data const* data, size_t* remLen ) { + dest = json_objOpen( dest, NULL, remLen ); + dest = json_str( dest, "city", data->city, remLen ); + dest = json_str( dest, "street", data->street, remLen ); + dest = json_measure( dest, "measure", &data->measure, remLen ); + dest = json_arrOpen( dest, "samples", remLen ); for( int i = 0; i < 4; ++i ) - dest = json_int( dest, NULL, data->samples[i] ); - dest = json_arrClose( dest ); - dest = json_objClose( dest ); + dest = json_int( dest, NULL, data->samples[i], remLen ); + dest = json_arrClose( dest, remLen ); + dest = json_objClose( dest, remLen ); return dest; } @@ -97,9 +97,9 @@ char* json_data( char* dest, char const* name, struct data const* data ) { * @param dest Destination memory block. * @param data Source data structure. * @return The JSON string length. */ -int data_to_json( char* dest, struct data const* data ) { - char* p = json_data( dest, NULL, data ); - p = json_end( p ); +int data_to_json( char* dest, struct data const* data, size_t* remLen ) { + char* p = json_data( dest, NULL, data, remLen ); + p = json_end( p, remLen ); return p - dest; } @@ -149,7 +149,8 @@ int main(int argc, char** argv) { } }; char buff[512]; - int len = data_to_json( buff, &data ); + size_t remLen = sizeof(buff); + int len = data_to_json( buff, &data, &remLen ); if( len >= sizeof buff ) { fprintf( stderr, "%s%d%s%d\n", "Error. Len: ", len, " Max: ", (int)sizeof buff - 1 ); return EXIT_FAILURE; diff --git a/tests/src/test.c b/tests/src/test.c index a8f0bac..dfee179 100644 --- a/tests/src/test.c +++ b/tests/src/test.c @@ -68,10 +68,11 @@ static int test_suit( struct test const* tests, int numtests ) { static int escape( void ) { char buff[512]; - char* p = json_objOpen( buff, NULL ); - p = json_str( p, "name", "\tHello: \"man\"\n" ); - p = json_objClose( p ); - p = json_end( p ); + size_t remLen = sizeof(buff); + char* p = json_objOpen( buff, NULL, &remLen ); + p = json_str( p, "name", "\tHello: \"man\"\n", &remLen ); + p = json_objClose( p, &remLen ); + p = json_end( p, &remLen ); printf( "\n\n%s\n\n", buff ); static char const rslt[] = "{\"name\":\"\\tHello: \\\"man\\\"\\n\"}"; check( p - buff == sizeof rslt - 1 ); @@ -81,10 +82,11 @@ static int escape( void ) { static int len( void ) { char buff[512]; - char* p = json_objOpen( buff, NULL ); - p = json_nstr( p, "name", "\tHello: \"man\"\n", 6 ); - p = json_objClose( p ); - p = json_end( p ); + size_t remLen = sizeof(buff); + char* p = json_objOpen( buff, NULL, &remLen ); + p = json_nstr( p, "name", "\tHello: \"man\"\n", 6, &remLen ); + p = json_objClose( p, &remLen ); + p = json_end( p, &remLen ); static char const rslt[] = "{\"name\":\"\\tHello\"}"; check( p - buff == sizeof rslt - 1 ); check( 0 == strcmp( buff, rslt ) ); @@ -93,34 +95,35 @@ static int len( void ) { static int empty( void ) { char buff[512]; + size_t remLen = sizeof(buff); { - char* p = json_objOpen( buff, NULL ); - p = json_objClose( p ); - p = json_end( p ); + char* p = json_objOpen( buff, NULL, &remLen ); + p = json_objClose( p, &remLen ); + p = json_end( p, &remLen ); static char const rslt[] = "{}"; check( p - buff == sizeof rslt - 1 ); check( 0 == strcmp( buff, rslt ) ); } { - char* p = json_objOpen( buff, NULL ); - p = json_arrOpen( p, "a" ); - p = json_arrClose( p ); - p = json_objClose( p ); - p = json_end( p ); + char* p = json_objOpen( buff, NULL, &remLen ); + p = json_arrOpen( p, "a", &remLen ); + p = json_arrClose( p, &remLen ); + p = json_objClose( p, &remLen ); + p = json_end( p, &remLen ); static char const rslt[] = "{\"a\":[]}"; check( p - buff == sizeof rslt - 1 ); check( 0 == strcmp( buff, rslt ) ); } { - char* p = json_objOpen( buff, NULL ); - p = json_arrOpen( p, "a" ); - p = json_objOpen( p, NULL ); - p = json_objClose( p ); - p = json_objOpen( p, NULL ); - p = json_objClose( p ); - p = json_arrClose( p ); - p = json_objClose( p ); - p = json_end( p ); + char* p = json_objOpen( buff, NULL, &remLen ); + p = json_arrOpen( p, "a", &remLen ); + p = json_objOpen( p, NULL, &remLen ); + p = json_objClose( p, &remLen ); + p = json_objOpen( p, NULL, &remLen ); + p = json_objClose( p, &remLen ); + p = json_arrClose( p, &remLen ); + p = json_objClose( p, &remLen ); + p = json_end( p, &remLen ); static char const rslt[] = "{\"a\":[{},{}]}"; check( p - buff == sizeof rslt - 1 ); check( 0 == strcmp( buff, rslt ) ); @@ -135,14 +138,15 @@ static int empty( void ) { static int primitive( void ) { char buff[512]; - char* p = json_objOpen( buff, NULL ); - p = json_verylong( p, "max", LONG_LONG_MAX ); - p = json_verylong( p, "min", LONG_LONG_MIN ); - p = json_bool( p, "boolvar0", 0 ); - p = json_bool( p, "boolvar1", 1 ); - p = json_null( p, "nullvar" ); - p = json_objClose( p ); - p = json_end( p ); + size_t remLen = sizeof(buff); + char* p = json_objOpen( buff, NULL, &remLen ); + p = json_verylong( p, "max", LONG_LONG_MAX, &remLen ); + p = json_verylong( p, "min", LONG_LONG_MIN, &remLen ); + p = json_bool( p, "boolvar0", 0, &remLen ); + p = json_bool( p, "boolvar1", 1, &remLen ); + p = json_null( p, "nullvar", &remLen ); + p = json_objClose( p, &remLen ); + p = json_end( p, &remLen ); static char const rslt[] = "{" "\"max\":9223372036854775807," "\"min\":-9223372036854775808," @@ -158,22 +162,24 @@ static int primitive( void ) { static int integers( void ) { { char buff[64]; - char* p = json_objOpen( buff, NULL ); - p = json_int( p, "a", 0 ); - p = json_int( p, "b", 1 ); - p = json_objClose( p ); - p = json_end( p ); + size_t remLen = sizeof(buff); + char* p = json_objOpen( buff, NULL, &remLen ); + p = json_int( p, "a", 0, &remLen ); + p = json_int( p, "b", 1, &remLen ); + p = json_objClose( p, &remLen ); + p = json_end( p, &remLen ); static char const rslt[] = "{\"a\":0,\"b\":1}"; check( p - buff == sizeof rslt - 1 ); check( 0 == strcmp( buff, rslt ) ); } { char buff[64]; - char* p = json_objOpen( buff, NULL ); - p = json_int( p, "max", INT_MAX ); - p = json_int( p, "min", INT_MIN ); - p = json_objClose( p ); - p = json_end( p ); + size_t remLen = sizeof(buff); + char* p = json_objOpen( buff, NULL, &remLen ); + p = json_int( p, "max", INT_MAX, &remLen ); + p = json_int( p, "min", INT_MIN, &remLen ); + p = json_objClose( p, &remLen ); + p = json_end( p, &remLen ); char rslt[ sizeof buff ]; int len = sprintf( rslt, "{\"max\":%d,\"min\":%d}", INT_MAX, INT_MIN ); check( len < sizeof buff ); @@ -182,10 +188,11 @@ static int integers( void ) { } { char buff[64]; - char* p = json_objOpen( buff, NULL ); - p = json_uint( p, "max", UINT_MAX ); - p = json_objClose( p ); - p = json_end( p ); + size_t remLen = sizeof(buff); + char* p = json_objOpen( buff, NULL, &remLen ); + p = json_uint( p, "max", UINT_MAX, &remLen ); + p = json_objClose( p, &remLen ); + p = json_end( p, &remLen ); char rslt[ sizeof buff ]; int len = sprintf( rslt, "{\"max\":%u}", UINT_MAX ); check( len < sizeof buff ); @@ -194,11 +201,12 @@ static int integers( void ) { } { char buff[64]; - char* p = json_objOpen( buff, NULL ); - p = json_long( p, "max", LONG_MAX ); - p = json_long( p, "min", LONG_MIN ); - p = json_objClose( p ); - p = json_end( p ); + size_t remLen = sizeof(buff); + char* p = json_objOpen( buff, NULL, &remLen ); + p = json_long( p, "max", LONG_MAX, &remLen ); + p = json_long( p, "min", LONG_MIN, &remLen ); + p = json_objClose( p, &remLen ); + p = json_end( p, &remLen ); char rslt[ sizeof buff ]; int len = sprintf( rslt, "{\"max\":%ld,\"min\":%ld}", LONG_MAX, LONG_MIN ); check( len < sizeof buff ); @@ -207,10 +215,11 @@ static int integers( void ) { } { char buff[64]; - char* p = json_objOpen( buff, NULL ); - p = json_ulong( p, "max", ULONG_MAX ); - p = json_objClose( p ); - p = json_end( p ); + size_t remLen = sizeof(buff); + char* p = json_objOpen( buff, NULL, &remLen ); + p = json_ulong( p, "max", ULONG_MAX, &remLen ); + p = json_objClose( p, &remLen ); + p = json_end( p, &remLen ); char rslt[ sizeof buff ]; int len = sprintf( rslt, "{\"max\":%lu}", ULONG_MAX ); check( len < sizeof buff ); @@ -219,11 +228,12 @@ static int integers( void ) { } { char buff[64]; - char* p = json_objOpen( buff, NULL ); - p = json_verylong( p, "max", LONG_LONG_MAX ); - p = json_verylong( p, "min", LONG_LONG_MIN ); - p = json_objClose( p ); - p = json_end( p ); + size_t remLen = sizeof(buff); + char* p = json_objOpen( buff, NULL, &remLen ); + p = json_verylong( p, "max", LONG_LONG_MAX, &remLen ); + p = json_verylong( p, "min", LONG_LONG_MIN, &remLen ); + p = json_objClose( p, &remLen ); + p = json_end( p, &remLen ); char rslt[ sizeof buff ]; int len = sprintf( rslt, "{\"max\":%lld,\"min\":%lld}", LONG_LONG_MAX, LONG_LONG_MIN ); check( len < sizeof buff ); @@ -235,13 +245,14 @@ static int integers( void ) { static int array( void ) { char buff[64]; - char* p = json_objOpen( buff, NULL ); - p = json_arrOpen( p, "a" ); + size_t remLen = sizeof(buff); + char* p = json_objOpen( buff, NULL, &remLen ); + p = json_arrOpen( p, "a", &remLen ); for( int i = 0; i < 4; ++i ) - p = json_int( p, NULL, i ); - p = json_arrClose( p ); - p = json_objClose( p ); - p = json_end( p ); + p = json_int( p, NULL, i, &remLen ); + p = json_arrClose( p, &remLen ); + p = json_objClose( p, &remLen ); + p = json_end( p, &remLen ); static char const rslt[] = "{\"a\":[0,1,2,3]}"; check( p - buff == sizeof rslt - 1 ); check( 0 == strcmp( buff, rslt ) ); @@ -250,14 +261,15 @@ static int array( void ) { static int real( void ) { char buff[64]; - char* p = json_objOpen( buff, NULL ); - p = json_arrOpen( p, "data" ); + size_t remLen = sizeof(buff); + char* p = json_objOpen( buff, NULL, &remLen ); + p = json_arrOpen( p, "data", &remLen ); static double const lut[] = { 0.2, 2e-6, 5e6 }; for( int i = 0; i < sizeof lut / sizeof *lut; ++i ) - p = json_double( p, NULL, lut[i] ); - p = json_arrClose( p ); - p = json_objClose( p ); - p = json_end( p ); + p = json_double( p, NULL, lut[i], &remLen ); + p = json_arrClose( p, &remLen ); + p = json_objClose( p, &remLen ); + p = json_end( p, &remLen ); #ifdef NO_SPRINTF static char const rslt1[] = "{\"data\":[0,0,5000000]}"; static char const rslt2[] = "{\"data\":[0,0,5000000]}"; From 8f5a96a24fb29895dfad0c55c06f7d5de531d956 Mon Sep 17 00:00:00 2001 From: "Hossein.M" <hossein.m9877@gmail.com> Date: Wed, 25 Oct 2023 09:56:21 +0330 Subject: [PATCH 2/4] fix: buffer overflow and NO_SPRINTF functionality --- src/json-maker.c | 80 ++++++++++++++++++++++++++++++------------------ 1 file changed, 50 insertions(+), 30 deletions(-) diff --git a/src/json-maker.c b/src/json-maker.c index 129a2c3..af49a69 100644 --- a/src/json-maker.c +++ b/src/json-maker.c @@ -32,11 +32,16 @@ * @param remLen Pointer to remaining length of dest * @return Pointer to the null character of the destination string. */ static char* chtoa( char* dest, char ch, size_t* remLen ) { - if (*remLen != 0) { + if (0 != *remLen) { --*remLen; - *dest = ch; - *++dest = '\0'; + *dest++ = ch; } + if (0 == *remLen) + { + ++*remLen; + --dest; + } + *dest = '\0'; return dest; } @@ -48,6 +53,11 @@ static char* chtoa( char* dest, char ch, size_t* remLen ) { static char* atoa( char* dest, char const* src, size_t* remLen ) { for( ; *src != '\0' && *remLen != 0; ++dest, ++src, --*remLen ) *dest = *src; + if (0 == *remLen) + { + ++*remLen; + --dest; + } *dest = '\0'; return dest; } @@ -222,6 +232,7 @@ char* json_end( char* dest, size_t* remLen ) { if ( ',' == dest[-1] ) { dest[-1] = '\0'; --dest; + *dest = '\0'; ++*remLen; } return dest; @@ -229,9 +240,17 @@ char* json_end( char* dest, size_t* remLen ) { #ifdef NO_SPRINTF -static char* format( char* dest, int len, int isnegative ) { - if ( isnegative ) +static char* format( char* dest, int len, int isnegative, size_t *remLen ) { + if ( isnegative && 0 != *remLen ) + { dest[ len++ ] = '-'; + --*remLen; + } + if (0 == *remLen) + { + --len; + ++*remLen; + } dest[ len ] = '\0'; int head = 0; int tail = len - 1; @@ -245,29 +264,30 @@ static char* format( char* dest, int len, int isnegative ) { return dest + len; } -#define numtoa( func, type, utype ) \ -static char* func( char* dest, type val ) { \ - enum { base = 10 }; \ - if ( 0 == val ) \ - return chtoa( dest, '0' ); \ - int const isnegative = 0 > val; \ - utype num = isnegative ? -val : val; \ - int len = 0; \ - while( 0 != num ) { \ - int rem = num % base; \ - dest[ len++ ] = rem + '0'; \ - num = num / base; \ - } \ - return format( dest, len, isnegative ); \ -} \ - -#define json_num( func, func2, type ) \ -char* func( char* dest, char const* name, type value ) { \ - dest = primitivename( dest, name ); \ - dest = func2( dest, value ); \ - dest = chtoa( dest, ',' ); \ - return dest; \ -} \ +#define numtoa( func, type, utype ) \ +static char* func( char* dest, type val, size_t *remLen ) { \ + enum { base = 10 }; \ + if ( 0 == val ) \ + return chtoa( dest, '0', remLen ); \ + int const isnegative = 0 > val; \ + utype num = isnegative ? -val : val; \ + int len = 0; \ + while( 0 != num && *remLen != 0 ) { \ + int rem = num % base; \ + dest[ len++ ] = rem + '0'; \ + --*remLen; \ + num = num / base; \ + } \ + return format( dest, len, isnegative, remLen ); \ +} + +#define json_num( func, func2, type ) \ +char* func( char* dest, char const* name, type value, size_t *remLen ) { \ + dest = primitivename( dest, name, remLen ); \ + dest = func2( dest, value, remLen ); \ + dest = chtoa( dest, ',', remLen ); \ + return dest; \ +} #define ALL_TYPES \ X( int, int, unsigned int ) \ @@ -284,8 +304,8 @@ ALL_TYPES ALL_TYPES #undef X -char* json_double( char* dest, char const* name, double value ) { - return json_verylong( dest, name, value ); +char* json_double( char* dest, char const* name, double value, size_t* remLen ) { + return json_verylong( dest, name, value, remLen ); } #else From 317bed38d70bec4104600df0cd1b005f128f9550 Mon Sep 17 00:00:00 2001 From: "Hossein.M" <hossein.m9877@gmail.com> Date: Wed, 25 Oct 2023 10:07:53 +0330 Subject: [PATCH 3/4] feat: add json_uverylong function --- src/include/json-maker/json-maker.h | 8 ++++++++ src/json-maker.c | 30 +++++++++++++++-------------- 2 files changed, 24 insertions(+), 14 deletions(-) diff --git a/src/include/json-maker/json-maker.h b/src/include/json-maker/json-maker.h index ed539e5..8f01290 100644 --- a/src/include/json-maker/json-maker.h +++ b/src/include/json-maker/json-maker.h @@ -142,6 +142,14 @@ char* json_ulong( char* dest, char const* name, unsigned long int value, size_t* * @return Pointer to the new end of JSON under construction. */ char* json_verylong( char* dest, char const* name, long long int value, size_t* remLen ); +/** Add a unsigned long long integer property in a JSON string. + * @param dest Pointer to the end of JSON under construction. + * @param name Pointer to null-terminated string or null for unnamed. + * @param value Value of the property. + * @param remLen Pointer to remaining length of dest + * @return Pointer to the new end of JSON under construction. */ +char* json_uverylong( char* dest, char const* name, unsigned long long int value, size_t* remLen ); + /** Add a double precision number property in a JSON string. * @param dest Pointer to the end of JSON under construction. * @param name Pointer to null-terminated string or null for unnamed. diff --git a/src/json-maker.c b/src/json-maker.c index af49a69..f4d7021 100644 --- a/src/json-maker.c +++ b/src/json-maker.c @@ -290,11 +290,12 @@ char* func( char* dest, char const* name, type value, size_t *remLen ) { \ } #define ALL_TYPES \ - X( int, int, unsigned int ) \ - X( long, long, unsigned long ) \ - X( uint, unsigned int, unsigned int ) \ - X( ulong, unsigned long, unsigned long ) \ - X( verylong, long long, unsigned long long ) \ + X( int, int, unsigned int ) \ + X( long, long, unsigned long ) \ + X( uint, unsigned int, unsigned int ) \ + X( ulong, unsigned long, unsigned long ) \ + X( verylong, long long, unsigned long long ) \ + X( uverylong, unsigned long long, unsigned long long ) #define X( name, type, utype ) numtoa( name##toa, type, utype ) ALL_TYPES @@ -312,22 +313,23 @@ char* json_double( char* dest, char const* name, double value, size_t* remLen ) #include <stdio.h> -#define ALL_TYPES \ - X( json_int, int, "%d" ) \ - X( json_long, long, "%ld" ) \ - X( json_uint, unsigned int, "%u" ) \ - X( json_ulong, unsigned long, "%lu" ) \ - X( json_verylong, long long, "%lld" ) \ - X( json_double, double, "%g" ) \ +#define ALL_TYPES \ + X( json_int, int, "%d" ) \ + X( json_long, long, "%ld" ) \ + X( json_uint, unsigned int, "%u" ) \ + X( json_ulong, unsigned long, "%lu" ) \ + X( json_verylong, long long, "%lld" ) \ + X( json_uverylong, unsigned long long, "%llu" ) \ + X( json_double, double, "%g" ) -#define json_num( funcname, type, fmt ) \ +#define json_num( funcname, type, fmt ) \ char* funcname( char* dest, char const* name, type value, size_t* remLen ) { \ int digitLen; \ dest = primitivename( dest, name, remLen ); \ digitLen = snprintf( dest, *remLen, fmt, value ); \ if(digitLen >= (int)*remLen+1){ \ - digitLen = (int)*remLen;} \ + digitLen = (int)*remLen;} \ *remLen -= (size_t)digitLen; \ dest += digitLen; \ dest = chtoa( dest, ',', remLen ); \ From 26925010aab8c4f7386cdc86d9d178154c471581 Mon Sep 17 00:00:00 2001 From: "Hossein.M" <hossein.m9877@gmail.com> Date: Wed, 25 Oct 2023 10:21:43 +0330 Subject: [PATCH 4/4] test: add test for json_uverylong --- tests/src/test.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/tests/src/test.c b/tests/src/test.c index dfee179..0639be4 100644 --- a/tests/src/test.c +++ b/tests/src/test.c @@ -136,6 +136,11 @@ static int empty( void ) { #define LONG_LONG_MIN LLONG_MIN #endif +#ifndef ULONG_LONG_MAX +#define ULONG_LONG_MAX ULLONG_MAX +#define ULONG_LONG_MIN 0 +#endif + static int primitive( void ) { char buff[512]; size_t remLen = sizeof(buff); @@ -240,6 +245,19 @@ static int integers( void ) { check( p - buff == len ); check( 0 == strcmp( buff, rslt ) ); } + { + char buff[64]; + size_t remLen = sizeof(buff); + char* p = json_objOpen( buff, NULL, &remLen ); + p = json_uverylong( p, "max", ULONG_LONG_MAX, &remLen ); + p = json_objClose( p, &remLen ); + p = json_end( p, &remLen ); + char rslt[ sizeof buff ]; + int len = sprintf( rslt, "{\"max\":%lld}", ULONG_LONG_MAX ); + check( len < sizeof buff ); + check( p - buff == len ); + check( 0 == strcmp( buff, rslt ) ); + } done(); }