diff --git a/source/core_json.c b/source/core_json.c index 15a239d9..69cb4da5 100644 --- a/source/core_json.c +++ b/source/core_json.c @@ -51,6 +51,12 @@ typedef union ( ( ( x ) == ' ' ) || ( ( x ) == '\t' ) || \ ( ( x ) == '\n' ) || ( ( x ) == '\r' ) ) +#define isOpenBracket_( x ) ( ( ( x ) == '{' ) || ( ( x ) == '[' ) ) +#define isCloseBracket_( x ) ( ( ( x ) == '}' ) || ( ( x ) == ']' ) ) +/* NB. The numeric values of the open and close bracket pairs differ by 2. */ +#define isMatchingBracket_( x, y ) \ + ( isOpenBracket_( x ) && isCloseBracket_( y ) && ( ( x ) == ( ( y ) - 2 ) ) ) + /** * @brief Advance buffer index beyond whitespace. * @@ -852,7 +858,7 @@ static bool_ skipSpaceAndComma( const char * buf, i++; skipSpace( buf, &i, max ); - if( ( i < max ) && ( buf[ i ] != '}' ) && ( buf[ i ] != ']' ) ) + if( ( i < max ) && !isCloseBracket_( buf[ i ] ) ) { ret = true; *start = i; @@ -903,7 +909,8 @@ static void skipArrayScalars( const char * buf, * * In JSON, objects consist of comma-separated key-value pairs. * A key is always a string (a scalar) while a value may be a - * scalar, an object, or an array. + * scalar, an object, or an array. A colon must appear between + * each key and value. * * @param[in] buf The buffer to parse. * @param[in,out] start The index at which to begin. @@ -916,6 +923,7 @@ static void skipObjectScalars( const char * buf, size_t max ) { size_t i; + bool_ comma; assert( ( buf != NULL ) && ( start != NULL ) && ( max > 0U ) ); @@ -938,18 +946,25 @@ static void skipObjectScalars( const char * buf, i++; skipSpace( buf, &i, max ); + if( ( i < max ) && isOpenBracket_( buf[ i ] ) ) + { + *start = i; + break; + } + if( skipAnyScalar( buf, &i, max ) != true ) { break; } - if( skipSpaceAndComma( buf, &i, max ) != true ) + comma = skipSpaceAndComma( buf, &i, max ); + *start = i; + + if( comma != true ) { break; } } - - *start = i; } /** @@ -965,7 +980,7 @@ static void skipScalars( const char * buf, size_t max, char mode ) { - assert( ( mode == '[' ) || ( mode == '{' ) ); + assert( isOpenBracket_( mode ) ); skipSpace( buf, start, max ); @@ -1028,15 +1043,21 @@ static JSONStatus_t skipCollection( const char * buf, } stack[ depth ] = c; + skipScalars( buf, &i, max, stack[ depth ] ); break; case '}': case ']': - if( depth > 0 ) + if( ( depth > 0 ) && isMatchingBracket_( stack[ depth ], c ) ) { depth--; - ( void ) skipSpaceAndComma( buf, &i, max ); + + if( skipSpaceAndComma( buf, &i, max ) == true ) + { + skipScalars( buf, &i, max, stack[ depth ] ); + } + break; } @@ -1052,8 +1073,6 @@ static JSONStatus_t skipCollection( const char * buf, { break; } - - skipScalars( buf, &i, max, stack[ depth ] ); } if( ret == JSONSuccess ) diff --git a/test/unit-test/core_json_utest.c b/test/unit-test/core_json_utest.c index a0799651..6ef3187f 100644 --- a/test/unit-test/core_json_utest.c +++ b/test/unit-test/core_json_utest.c @@ -123,6 +123,15 @@ "\":{\"" SECOND_QUERY_KEY "\" : \"" COMPLETE_QUERY_KEY_ANSWER "\",}}" #define TRAILING_COMMA_AFTER_VALUE_LENGTH ( sizeof( TRAILING_COMMA_AFTER_VALUE ) - 1 ) +#define MISSING_COMMA_AFTER_VALUE "{\"foo\":{}\"bar\":\"abc\"}" +#define MISSING_COMMA_AFTER_VALUE_LENGTH ( sizeof( MISSING_COMMA_AFTER_VALUE ) - 1 ) + +#define MISSING_VALUE_AFTER_KEY "{\"foo\":{\"bar\":}}" +#define MISSING_VALUE_AFTER_KEY_LENGTH ( sizeof( MISSING_VALUE_AFTER_KEY ) - 1 ) + +#define MISMATCHED_BRACKETS "{\"foo\":{\"bar\":\"xyz\"]}" +#define MISMATCHED_BRACKETS_LENGTH ( sizeof( MISMATCHED_BRACKETS ) - 1 ) + #define INCORRECT_OBJECT_SEPARATOR "{\"foo\": \"bar\"; \"bar\": \"foo\"}" #define INCORRECT_OBJECT_SEPARATOR_LENGTH ( sizeof( INCORRECT_OBJECT_SEPARATOR ) - 1 ) @@ -542,10 +551,26 @@ void test_JSON_Validate_Illegal_Documents( void ) CUT_AFTER_COMMA_SEPARATOR_LENGTH ); TEST_ASSERT_EQUAL( JSONIllegalDocument, jsonStatus ); + jsonStatus = JSON_Validate( CUT_AFTER_KEY, + CUT_AFTER_KEY_LENGTH ); + TEST_ASSERT_EQUAL( JSONIllegalDocument, jsonStatus ); + jsonStatus = JSON_Validate( TRAILING_COMMA_AFTER_VALUE, TRAILING_COMMA_AFTER_VALUE_LENGTH ); TEST_ASSERT_EQUAL( JSONIllegalDocument, jsonStatus ); + jsonStatus = JSON_Validate( MISSING_COMMA_AFTER_VALUE, + MISSING_COMMA_AFTER_VALUE_LENGTH ); + TEST_ASSERT_EQUAL( JSONIllegalDocument, jsonStatus ); + + jsonStatus = JSON_Validate( MISSING_VALUE_AFTER_KEY, + MISSING_VALUE_AFTER_KEY_LENGTH ); + TEST_ASSERT_EQUAL( JSONIllegalDocument, jsonStatus ); + + jsonStatus = JSON_Validate( MISMATCHED_BRACKETS, + MISMATCHED_BRACKETS_LENGTH ); + TEST_ASSERT_EQUAL( JSONIllegalDocument, jsonStatus ); + jsonStatus = JSON_Validate( NUL_ESCAPE, NUL_ESCAPE_LENGTH ); TEST_ASSERT_EQUAL( JSONIllegalDocument, jsonStatus ); @@ -717,10 +742,6 @@ void test_JSON_Validate_Partial_Documents( void ) jsonStatus = JSON_Validate( CUT_AFTER_OBJECT_START_MARKER, CUT_AFTER_OBJECT_START_MARKER_LENGTH ); TEST_ASSERT_EQUAL( JSONPartial, jsonStatus ); - - jsonStatus = JSON_Validate( CUT_AFTER_KEY, - CUT_AFTER_KEY_LENGTH ); - TEST_ASSERT_EQUAL( JSONPartial, jsonStatus ); } /**