Skip to content

Commit 424feac

Browse files
authored
Address edge cases and add tests (#30)
1 parent 7ce0367 commit 424feac

File tree

2 files changed

+54
-14
lines changed

2 files changed

+54
-14
lines changed

source/core_json.c

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,12 @@ typedef union
5151
( ( ( x ) == ' ' ) || ( ( x ) == '\t' ) || \
5252
( ( x ) == '\n' ) || ( ( x ) == '\r' ) )
5353

54+
#define isOpenBracket_( x ) ( ( ( x ) == '{' ) || ( ( x ) == '[' ) )
55+
#define isCloseBracket_( x ) ( ( ( x ) == '}' ) || ( ( x ) == ']' ) )
56+
/* NB. The numeric values of the open and close bracket pairs differ by 2. */
57+
#define isMatchingBracket_( x, y ) \
58+
( isOpenBracket_( x ) && isCloseBracket_( y ) && ( ( x ) == ( ( y ) - 2 ) ) )
59+
5460
/**
5561
* @brief Advance buffer index beyond whitespace.
5662
*
@@ -852,7 +858,7 @@ static bool_ skipSpaceAndComma( const char * buf,
852858
i++;
853859
skipSpace( buf, &i, max );
854860

855-
if( ( i < max ) && ( buf[ i ] != '}' ) && ( buf[ i ] != ']' ) )
861+
if( ( i < max ) && !isCloseBracket_( buf[ i ] ) )
856862
{
857863
ret = true;
858864
*start = i;
@@ -903,7 +909,8 @@ static void skipArrayScalars( const char * buf,
903909
*
904910
* In JSON, objects consist of comma-separated key-value pairs.
905911
* A key is always a string (a scalar) while a value may be a
906-
* scalar, an object, or an array.
912+
* scalar, an object, or an array. A colon must appear between
913+
* each key and value.
907914
*
908915
* @param[in] buf The buffer to parse.
909916
* @param[in,out] start The index at which to begin.
@@ -916,6 +923,7 @@ static void skipObjectScalars( const char * buf,
916923
size_t max )
917924
{
918925
size_t i;
926+
bool_ comma;
919927

920928
assert( ( buf != NULL ) && ( start != NULL ) && ( max > 0U ) );
921929

@@ -938,18 +946,25 @@ static void skipObjectScalars( const char * buf,
938946
i++;
939947
skipSpace( buf, &i, max );
940948

949+
if( ( i < max ) && isOpenBracket_( buf[ i ] ) )
950+
{
951+
*start = i;
952+
break;
953+
}
954+
941955
if( skipAnyScalar( buf, &i, max ) != true )
942956
{
943957
break;
944958
}
945959

946-
if( skipSpaceAndComma( buf, &i, max ) != true )
960+
comma = skipSpaceAndComma( buf, &i, max );
961+
*start = i;
962+
963+
if( comma != true )
947964
{
948965
break;
949966
}
950967
}
951-
952-
*start = i;
953968
}
954969

955970
/**
@@ -965,7 +980,7 @@ static void skipScalars( const char * buf,
965980
size_t max,
966981
char mode )
967982
{
968-
assert( ( mode == '[' ) || ( mode == '{' ) );
983+
assert( isOpenBracket_( mode ) );
969984

970985
skipSpace( buf, start, max );
971986

@@ -1028,15 +1043,21 @@ static JSONStatus_t skipCollection( const char * buf,
10281043
}
10291044

10301045
stack[ depth ] = c;
1046+
skipScalars( buf, &i, max, stack[ depth ] );
10311047
break;
10321048

10331049
case '}':
10341050
case ']':
10351051

1036-
if( depth > 0 )
1052+
if( ( depth > 0 ) && isMatchingBracket_( stack[ depth ], c ) )
10371053
{
10381054
depth--;
1039-
( void ) skipSpaceAndComma( buf, &i, max );
1055+
1056+
if( skipSpaceAndComma( buf, &i, max ) == true )
1057+
{
1058+
skipScalars( buf, &i, max, stack[ depth ] );
1059+
}
1060+
10401061
break;
10411062
}
10421063

@@ -1052,8 +1073,6 @@ static JSONStatus_t skipCollection( const char * buf,
10521073
{
10531074
break;
10541075
}
1055-
1056-
skipScalars( buf, &i, max, stack[ depth ] );
10571076
}
10581077

10591078
if( ret == JSONSuccess )

test/unit-test/core_json_utest.c

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,15 @@
123123
"\":{\"" SECOND_QUERY_KEY "\" : \"" COMPLETE_QUERY_KEY_ANSWER "\",}}"
124124
#define TRAILING_COMMA_AFTER_VALUE_LENGTH ( sizeof( TRAILING_COMMA_AFTER_VALUE ) - 1 )
125125

126+
#define MISSING_COMMA_AFTER_VALUE "{\"foo\":{}\"bar\":\"abc\"}"
127+
#define MISSING_COMMA_AFTER_VALUE_LENGTH ( sizeof( MISSING_COMMA_AFTER_VALUE ) - 1 )
128+
129+
#define MISSING_VALUE_AFTER_KEY "{\"foo\":{\"bar\":}}"
130+
#define MISSING_VALUE_AFTER_KEY_LENGTH ( sizeof( MISSING_VALUE_AFTER_KEY ) - 1 )
131+
132+
#define MISMATCHED_BRACKETS "{\"foo\":{\"bar\":\"xyz\"]}"
133+
#define MISMATCHED_BRACKETS_LENGTH ( sizeof( MISMATCHED_BRACKETS ) - 1 )
134+
126135
#define INCORRECT_OBJECT_SEPARATOR "{\"foo\": \"bar\"; \"bar\": \"foo\"}"
127136
#define INCORRECT_OBJECT_SEPARATOR_LENGTH ( sizeof( INCORRECT_OBJECT_SEPARATOR ) - 1 )
128137

@@ -542,10 +551,26 @@ void test_JSON_Validate_Illegal_Documents( void )
542551
CUT_AFTER_COMMA_SEPARATOR_LENGTH );
543552
TEST_ASSERT_EQUAL( JSONIllegalDocument, jsonStatus );
544553

554+
jsonStatus = JSON_Validate( CUT_AFTER_KEY,
555+
CUT_AFTER_KEY_LENGTH );
556+
TEST_ASSERT_EQUAL( JSONIllegalDocument, jsonStatus );
557+
545558
jsonStatus = JSON_Validate( TRAILING_COMMA_AFTER_VALUE,
546559
TRAILING_COMMA_AFTER_VALUE_LENGTH );
547560
TEST_ASSERT_EQUAL( JSONIllegalDocument, jsonStatus );
548561

562+
jsonStatus = JSON_Validate( MISSING_COMMA_AFTER_VALUE,
563+
MISSING_COMMA_AFTER_VALUE_LENGTH );
564+
TEST_ASSERT_EQUAL( JSONIllegalDocument, jsonStatus );
565+
566+
jsonStatus = JSON_Validate( MISSING_VALUE_AFTER_KEY,
567+
MISSING_VALUE_AFTER_KEY_LENGTH );
568+
TEST_ASSERT_EQUAL( JSONIllegalDocument, jsonStatus );
569+
570+
jsonStatus = JSON_Validate( MISMATCHED_BRACKETS,
571+
MISMATCHED_BRACKETS_LENGTH );
572+
TEST_ASSERT_EQUAL( JSONIllegalDocument, jsonStatus );
573+
549574
jsonStatus = JSON_Validate( NUL_ESCAPE, NUL_ESCAPE_LENGTH );
550575
TEST_ASSERT_EQUAL( JSONIllegalDocument, jsonStatus );
551576

@@ -717,10 +742,6 @@ void test_JSON_Validate_Partial_Documents( void )
717742
jsonStatus = JSON_Validate( CUT_AFTER_OBJECT_START_MARKER,
718743
CUT_AFTER_OBJECT_START_MARKER_LENGTH );
719744
TEST_ASSERT_EQUAL( JSONPartial, jsonStatus );
720-
721-
jsonStatus = JSON_Validate( CUT_AFTER_KEY,
722-
CUT_AFTER_KEY_LENGTH );
723-
TEST_ASSERT_EQUAL( JSONPartial, jsonStatus );
724745
}
725746

726747
/**

0 commit comments

Comments
 (0)