Skip to content

Commit 10c26b8

Browse files
authored
Correctly detect missing key in a key-value pair (#167)
* Correctly detect missing key in a key-value pair The following invalid JSON document would be classified as valid JSON without this change: ``` { "key1":"val1", { "key2":"val2" } } ``` The issue was reported here - #165. Signed-off-by: Gaurav Aggarwal <[email protected]> * Update complexity threshold to 12 Signed-off-by: Gaurav Aggarwal <[email protected]> * Fix memory estimates and formatting checks Signed-off-by: Gaurav Aggarwal <[email protected]> * Fix CBMC proofs Signed-off-by: Gaurav Aggarwal <[email protected]> --------- Signed-off-by: Gaurav Aggarwal <[email protected]>
1 parent fdfe306 commit 10c26b8

File tree

6 files changed

+57
-12
lines changed

6 files changed

+57
-12
lines changed

.github/workflows/ci.yml

+1
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ jobs:
4444
uses: FreeRTOS/CI-CD-Github-Actions/complexity@main
4545
with:
4646
path: ./
47+
horrid_threshold: 12
4748

4849
doxygen:
4950
runs-on: ubuntu-latest

docs/doxygen/include/size_table.md

+4-4
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,12 @@
99
</tr>
1010
<tr>
1111
<td>core_json.c</td>
12-
<td><center>2.9K</center></td>
13-
<td><center>2.4K</center></td>
12+
<td><center>3.1K</center></td>
13+
<td><center>2.5K</center></td>
1414
</tr>
1515
<tr>
1616
<td><b>Total estimates</b></td>
17-
<td><b><center>2.9K</center></b></td>
18-
<td><b><center>2.4K</center></b></td>
17+
<td><b><center>3.1K</center></b></td>
18+
<td><b><center>2.5K</center></b></td>
1919
</tr>
2020
</table>

loop_invariants.patch

+1-1
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ index 901b2e1..8bdd89c 100644
123123
{
124124
if( skipAnyScalar( buf, &i, max ) != true )
125125
{
126-
@@ -986,6 +1037,13 @@ static void skipObjectScalars( const char * buf,
126+
@@ -986,6 +1037,13 @@ static bool skipObjectScalars( const char * buf,
127127
i = *start;
128128

129129
while( i < max )

source/core_json.c

+28-5
Original file line numberDiff line numberDiff line change
@@ -971,14 +971,18 @@ static void skipArrayScalars( const char * buf,
971971
* @param[in,out] start The index at which to begin.
972972
* @param[in] max The size of the buffer.
973973
*
974+
* @return true if a valid scalar key-value pairs were present;
975+
* false otherwise.
976+
*
974977
* @note Stops advance if a value is an object or array.
975978
*/
976-
static void skipObjectScalars( const char * buf,
979+
static bool skipObjectScalars( const char * buf,
977980
size_t * start,
978981
size_t max )
979982
{
980983
size_t i = 0U;
981984
bool comma = false;
985+
bool ret = true;
982986

983987
coreJSON_ASSERT( ( buf != NULL ) && ( start != NULL ) && ( max > 0U ) );
984988

@@ -988,13 +992,15 @@ static void skipObjectScalars( const char * buf,
988992
{
989993
if( skipString( buf, &i, max ) != true )
990994
{
995+
ret = false;
991996
break;
992997
}
993998

994999
skipSpace( buf, &i, max );
9951000

9961001
if( ( i < max ) && ( buf[ i ] != ':' ) )
9971002
{
1003+
ret = false;
9981004
break;
9991005
}
10001006

@@ -1009,6 +1015,7 @@ static void skipObjectScalars( const char * buf,
10091015

10101016
if( skipAnyScalar( buf, &i, max ) != true )
10111017
{
1018+
ret = false;
10121019
break;
10131020
}
10141021

@@ -1020,6 +1027,8 @@ static void skipObjectScalars( const char * buf,
10201027
break;
10211028
}
10221029
}
1030+
1031+
return ret;
10231032
}
10241033

10251034
/**
@@ -1029,13 +1038,17 @@ static void skipObjectScalars( const char * buf,
10291038
* @param[in,out] start The index at which to begin.
10301039
* @param[in] max The size of the buffer.
10311040
* @param[in] mode The first character of an array '[' or object '{'.
1041+
*
1042+
* @return true if a valid scalers were present;
1043+
* false otherwise.
10321044
*/
1033-
static void skipScalars( const char * buf,
1045+
static bool skipScalars( const char * buf,
10341046
size_t * start,
10351047
size_t max,
10361048
char mode )
10371049
{
10381050
bool modeIsOpenBracket = ( bool ) isOpenBracket_( mode );
1051+
bool ret = true;
10391052

10401053
/* assert function may be implemented in macro using a # or ## operator.
10411054
* Using a local variable here to prevent macro replacement is subjected
@@ -1053,8 +1066,10 @@ static void skipScalars( const char * buf,
10531066
}
10541067
else
10551068
{
1056-
skipObjectScalars( buf, start, max );
1069+
ret = skipObjectScalars( buf, start, max );
10571070
}
1071+
1072+
return ret;
10581073
}
10591074

10601075
/**
@@ -1106,7 +1121,12 @@ static JSONStatus_t skipCollection( const char * buf,
11061121
}
11071122

11081123
stack[ depth ] = c;
1109-
skipScalars( buf, &i, max, stack[ depth ] );
1124+
1125+
if( skipScalars( buf, &i, max, stack[ depth ] ) != true )
1126+
{
1127+
ret = JSONIllegalDocument;
1128+
}
1129+
11101130
break;
11111131

11121132
case '}':
@@ -1120,7 +1140,10 @@ static JSONStatus_t skipCollection( const char * buf,
11201140
if( ( skipSpaceAndComma( buf, &i, max ) == true ) &&
11211141
isOpenBracket_( stack[ depth ] ) )
11221142
{
1123-
skipScalars( buf, &i, max, stack[ depth ] );
1143+
if( skipScalars( buf, &i, max, stack[ depth ] ) != true )
1144+
{
1145+
ret = JSONIllegalDocument;
1146+
}
11241147
}
11251148

11261149
break;

test/cbmc/include/core_json_contracts.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,7 @@ assigns( *start )
261261
ensures( skipCollectionPostconditions( result, buf, start, old( *start ), max ) )
262262
;
263263

264-
void skipScalars( const char * buf,
264+
bool skipScalars( const char * buf,
265265
size_t * start,
266266
size_t max,
267267
char mode )
@@ -270,7 +270,7 @@ assigns( *start )
270270
ensures( isValidStart( *start, old( *start ), max ) )
271271
;
272272

273-
void skipObjectScalars( const char * buf,
273+
bool skipObjectScalars( const char * buf,
274274
size_t * start,
275275
size_t max )
276276
requires( isValidBufferWithStartIndex( buf, max, start ) )

test/unit-test/core_json_utest.c

+21
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,15 @@
168168
#define MISSING_VALUE_AFTER_KEY "{\"foo\":{\"bar\":}}"
169169
#define MISSING_VALUE_AFTER_KEY_LENGTH ( sizeof( MISSING_VALUE_AFTER_KEY ) - 1 )
170170

171+
#define MISSING_KEY "{\"foo\":\"bar\", {\"abc\":\"xyz\"}}"
172+
#define MISSING_KEY_LENGTH ( sizeof( MISSING_KEY ) - 1 )
173+
174+
#define MISSING_VALUE "{\"foo\":{\"abc\":\"xyz\"}, \"bar\":}"
175+
#define MISSING_VALUE_LENGTH ( sizeof( MISSING_VALUE ) - 1 )
176+
177+
#define MISSING_SEPERATOR "{\"foo\" \"bar\"}"
178+
#define MISSING_SEPERATOR_LENGTH ( sizeof( MISSING_SEPERATOR ) - 1 )
179+
171180
#define MISMATCHED_BRACKETS "{\"foo\":{\"bar\":\"xyz\"]}"
172181
#define MISMATCHED_BRACKETS_LENGTH ( sizeof( MISMATCHED_BRACKETS ) - 1 )
173182

@@ -619,6 +628,18 @@ void test_JSON_Validate_Illegal_Documents( void )
619628
MISSING_VALUE_AFTER_KEY_LENGTH );
620629
TEST_ASSERT_EQUAL( JSONIllegalDocument, jsonStatus );
621630

631+
jsonStatus = JSON_Validate( MISSING_KEY,
632+
MISSING_KEY_LENGTH );
633+
TEST_ASSERT_EQUAL( JSONIllegalDocument, jsonStatus );
634+
635+
jsonStatus = JSON_Validate( MISSING_VALUE,
636+
MISSING_VALUE_LENGTH );
637+
TEST_ASSERT_EQUAL( JSONIllegalDocument, jsonStatus );
638+
639+
jsonStatus = JSON_Validate( MISSING_SEPERATOR,
640+
MISSING_SEPERATOR_LENGTH );
641+
TEST_ASSERT_EQUAL( JSONIllegalDocument, jsonStatus );
642+
622643
jsonStatus = JSON_Validate( MISMATCHED_BRACKETS,
623644
MISMATCHED_BRACKETS_LENGTH );
624645
TEST_ASSERT_EQUAL( JSONIllegalDocument, jsonStatus );

0 commit comments

Comments
 (0)