From 170d87cd674b12e4f3cc41480bb949e12548c858 Mon Sep 17 00:00:00 2001 From: Gaurav Aggarwal Date: Thu, 18 Jul 2024 13:48:16 +0000 Subject: [PATCH 1/6] Treat empty JSON object as valid Without this change, the following valid JSON document will be evaluated as invalid: ``` { "foo": {} } ``` This issue was reported here - https://github.com/FreeRTOS/coreJSON/issues/168 Signed-off-by: Gaurav Aggarwal --- source/core_json.c | 9 ++++++++- test/unit-test/core_json_utest.c | 7 +++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/source/core_json.c b/source/core_json.c index a47dcc49..18d9e768 100644 --- a/source/core_json.c +++ b/source/core_json.c @@ -980,13 +980,14 @@ static bool skipObjectScalars( const char * buf, size_t * start, size_t max ) { - size_t i = 0U; + size_t i = 0U, origStart = 0U; bool comma = false; bool ret = true; coreJSON_ASSERT( ( buf != NULL ) && ( start != NULL ) && ( max > 0U ) ); i = *start; + origStart = *start; while( i < max ) { @@ -1028,6 +1029,12 @@ static bool skipObjectScalars( const char * buf, } } + /* An empty JSON object is valid. */ + if( i == origStart ) + { + ret = true; + } + return ret; } diff --git a/test/unit-test/core_json_utest.c b/test/unit-test/core_json_utest.c index c5107562..8a74f399 100644 --- a/test/unit-test/core_json_utest.c +++ b/test/unit-test/core_json_utest.c @@ -146,6 +146,9 @@ "\":{\"" SECOND_QUERY_KEY "\" : \"" COMPLETE_QUERY_KEY_ANSWER "\"}} " #define JSON_DOC_LEGAL_TRAILING_SPACE_LENGTH ( sizeof( JSON_DOC_LEGAL_TRAILING_SPACE ) - 1 ) +#define JSON_DOC_LEGAL_EMPTY_OBJECT "{\"foo\":{}}" +#define JSON_DOC_LEGAL_EMPTY_OBJECT_LENGTH ( sizeof( JSON_DOC_LEGAL_EMPTY_OBJECT ) - 1 ) + /* A single scalar is still considered a valid JSON document. */ #define SINGLE_SCALAR "\"l33t\"" #define SINGLE_SCALAR_LENGTH ( sizeof( SINGLE_SCALAR ) - 1 ) @@ -564,6 +567,10 @@ void test_JSON_Validate_Legal_Documents( void ) JSON_DOC_LEGAL_TRAILING_SPACE_LENGTH ); TEST_ASSERT_EQUAL( JSONSuccess, jsonStatus ); + jsonStatus = JSON_Validate( JSON_DOC_LEGAL_EMPTY_OBJECT, + JSON_DOC_LEGAL_EMPTY_OBJECT_LENGTH ); + TEST_ASSERT_EQUAL( JSONSuccess, jsonStatus ); + jsonStatus = JSON_Validate( JSON_DOC_MULTIPLE_VALID_ESCAPES, JSON_DOC_MULTIPLE_VALID_ESCAPES_LENGTH ); TEST_ASSERT_EQUAL( JSONSuccess, jsonStatus ); From 37a4ca80c9916e0122af0ae700e681da8c838aa9 Mon Sep 17 00:00:00 2001 From: Gaurav Aggarwal Date: Thu, 18 Jul 2024 13:54:50 +0000 Subject: [PATCH 2/6] Fix formatting Signed-off-by: Gaurav Aggarwal --- test/unit-test/core_json_utest.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit-test/core_json_utest.c b/test/unit-test/core_json_utest.c index 8a74f399..38e37902 100644 --- a/test/unit-test/core_json_utest.c +++ b/test/unit-test/core_json_utest.c @@ -147,7 +147,7 @@ #define JSON_DOC_LEGAL_TRAILING_SPACE_LENGTH ( sizeof( JSON_DOC_LEGAL_TRAILING_SPACE ) - 1 ) #define JSON_DOC_LEGAL_EMPTY_OBJECT "{\"foo\":{}}" -#define JSON_DOC_LEGAL_EMPTY_OBJECT_LENGTH ( sizeof( JSON_DOC_LEGAL_EMPTY_OBJECT ) - 1 ) +#define JSON_DOC_LEGAL_EMPTY_OBJECT_LENGTH ( sizeof( JSON_DOC_LEGAL_EMPTY_OBJECT ) - 1 ) /* A single scalar is still considered a valid JSON document. */ #define SINGLE_SCALAR "\"l33t\"" From d0130a229e669eba9c8567480824895b446c1363 Mon Sep 17 00:00:00 2001 From: Gaurav Aggarwal Date: Thu, 18 Jul 2024 14:24:12 +0000 Subject: [PATCH 3/6] Fix CBMC proof failure Signed-off-by: Gaurav Aggarwal --- loop_invariants.patch | 84 ++++++++++++++++++++----------------------- 1 file changed, 38 insertions(+), 46 deletions(-) diff --git a/loop_invariants.patch b/loop_invariants.patch index f6a76b1d..a8a05fb7 100644 --- a/loop_invariants.patch +++ b/loop_invariants.patch @@ -1,32 +1,32 @@ diff --git a/source/core_json.c b/source/core_json.c -index 901b2e1..8bdd89c 100644 +index 18d9e76..0197de9 100644 --- a/source/core_json.c +++ b/source/core_json.c -@@ -62,6 +62,21 @@ typedef union +@@ -61,6 +61,21 @@ typedef union #define isSquareOpen_( x ) ( ( x ) == '[' ) #define isSquareClose_( x ) ( ( x ) == ']' ) - + +/** + * Renaming all loop-contract clauses from CBMC for readability. + * For more information about loop contracts in CBMC, see + * https://diffblue.github.io/cbmc/contracts-user.html. + */ +#ifdef CBMC -+#define loopInvariant(...) __CPROVER_loop_invariant(__VA_ARGS__) -+#define decreases(...) __CPROVER_decreases(__VA_ARGS__) -+#define assigns(...) __CPROVER_assigns(__VA_ARGS__) ++ #define loopInvariant(...) __CPROVER_loop_invariant(__VA_ARGS__) ++ #define decreases(...) __CPROVER_decreases(__VA_ARGS__) ++ #define assigns(...) __CPROVER_assigns(__VA_ARGS__) +#else -+#define loopInvariant(...) -+#define decreases(...) -+#define assigns(...) ++ #define loopInvariant(...) ++ #define decreases(...) ++ #define assigns(...) +#endif + /** * @brief Advance buffer index beyond whitespace. * -@@ -78,6 +93,9 @@ static void skipSpace( const char * buf, +@@ -77,6 +92,9 @@ static void skipSpace( const char * buf, coreJSON_ASSERT( ( buf != NULL ) && ( start != NULL ) && ( max > 0U ) ); - + for( i = *start; i < max; i++ ) + assigns( i ) + loopInvariant( *start <= i && i <= max ) @@ -34,9 +34,9 @@ index 901b2e1..8bdd89c 100644 { if( !isspace_( buf[ i ] ) ) { -@@ -102,6 +120,13 @@ static size_t countHighBits( uint8_t c ) +@@ -101,6 +119,13 @@ static size_t countHighBits( uint8_t c ) size_t i = 0; - + while( ( n & 0x80U ) != 0U ) + assigns( i, n ) + loopInvariant ( @@ -48,7 +48,7 @@ index 901b2e1..8bdd89c 100644 { i++; n = ( n & 0x7FU ) << 1U; -@@ -210,6 +235,13 @@ static bool skipUTF8MultiByte( const char * buf, +@@ -209,6 +234,13 @@ static bool skipUTF8MultiByte( const char * buf, /* The bit count is 1 greater than the number of bytes, * e.g., when j is 2, we skip one more byte. */ for( j = bitCount - 1U; j > 0U; j-- ) @@ -61,8 +61,8 @@ index 901b2e1..8bdd89c 100644 + decreases( j ) { i++; - -@@ -345,6 +377,12 @@ static bool skipOneHexEscape( const char * buf, + +@@ -344,6 +376,12 @@ static bool skipOneHexEscape( const char * buf, if( ( end < max ) && ( buf[ i ] == '\\' ) && ( buf[ i + 1U ] == 'u' ) ) { for( i += 2U; i < end; i++ ) @@ -74,10 +74,10 @@ index 901b2e1..8bdd89c 100644 + decreases( end - i ) { uint8_t n = hexToInt( buf[ i ] ); - -@@ -522,6 +560,9 @@ static bool skipString( const char * buf, + +@@ -521,6 +559,9 @@ static bool skipString( const char * buf, i++; - + while( i < max ) + assigns( i ) + loopInvariant( *start + 1U <= i && i <= max ) @@ -85,9 +85,9 @@ index 901b2e1..8bdd89c 100644 { if( buf[ i ] == '"' ) { -@@ -580,6 +621,9 @@ static bool strnEq( const char * a, +@@ -579,6 +620,9 @@ static bool strnEq( const char * a, coreJSON_ASSERT( ( a != NULL ) && ( b != NULL ) ); - + for( i = 0; i < n; i++ ) + assigns( i ) + loopInvariant( i <= n ) @@ -95,17 +95,9 @@ index 901b2e1..8bdd89c 100644 { if( a[ i ] != b[ i ] ) { -@@ -681,6 +725,7 @@ static bool skipAnyLiteral( const char * buf, - * false otherwise. - */ - #define MAX_FACTOR ( MAX_INDEX_VALUE / 10 ) -+ - static bool skipDigits( const char * buf, - size_t * start, - size_t max, -@@ -695,6 +740,9 @@ static bool skipDigits( const char * buf, +@@ -694,6 +738,9 @@ static bool skipDigits( const char * buf, saveStart = *start; - + for( i = *start; i < max; i++ ) + assigns( value, i ) + loopInvariant( *start <= i && i <= max ) @@ -113,9 +105,9 @@ index 901b2e1..8bdd89c 100644 { if( !isdigit_( buf[ i ] ) ) { -@@ -944,6 +992,9 @@ static void skipArrayScalars( const char * buf, +@@ -943,6 +990,9 @@ static void skipArrayScalars( const char * buf, i = *start; - + while( i < max ) + assigns( i ) + loopInvariant( *start <= i && i <= max ) @@ -123,9 +115,9 @@ index 901b2e1..8bdd89c 100644 { if( skipAnyScalar( buf, &i, max ) != true ) { -@@ -986,6 +1037,13 @@ static bool skipObjectScalars( const char * buf, - i = *start; - +@@ -990,6 +1040,13 @@ static bool skipObjectScalars( const char * buf, + origStart = *start; + while( i < max ) + assigns( i, *start, comma ) + loopInvariant( @@ -137,9 +129,9 @@ index 901b2e1..8bdd89c 100644 { if( skipString( buf, &i, max ) != true ) { -@@ -1082,6 +1140,14 @@ static JSONStatus_t skipCollection( const char * buf, +@@ -1111,6 +1168,14 @@ static JSONStatus_t skipCollection( const char * buf, i = *start; - + while( i < max ) + assigns( i, depth, c, __CPROVER_object_whole( stack ), ret ) + loopInvariant( @@ -152,9 +144,9 @@ index 901b2e1..8bdd89c 100644 { c = buf[ i ]; i++; -@@ -1363,6 +1429,9 @@ static bool objectSearch( const char * buf, +@@ -1400,6 +1465,9 @@ static bool objectSearch( const char * buf, skipSpace( buf, &i, max ); - + while( i < max ) + assigns( i, key, keyLength, value, valueLength ) + loopInvariant( __CPROVER_loop_entry( i ) <= i && i <= max ) @@ -162,9 +154,9 @@ index 901b2e1..8bdd89c 100644 { if( nextKeyValuePair( buf, &i, max, &key, &keyLength, &value, &valueLength ) != true ) -@@ -1430,6 +1499,9 @@ static bool arraySearch( const char * buf, +@@ -1467,6 +1535,9 @@ static bool arraySearch( const char * buf, skipSpace( buf, &i, max ); - + while( i < max ) + assigns( i, currentIndex, value, valueLength ) + loopInvariant( __CPROVER_loop_entry( i ) <= i && i <= max && currentIndex < i ) @@ -172,7 +164,7 @@ index 901b2e1..8bdd89c 100644 { if( nextValue( buf, &i, max, &value, &valueLength ) != true ) { -@@ -1495,6 +1567,9 @@ static bool skipQueryPart( const char * buf, +@@ -1532,6 +1603,9 @@ static bool skipQueryPart( const char * buf, while( ( i < max ) && !isSeparator_( buf[ i ] ) && !isSquareOpen_( buf[ i ] ) ) @@ -182,9 +174,9 @@ index 901b2e1..8bdd89c 100644 { i++; } -@@ -1541,6 +1616,17 @@ static JSONStatus_t multiSearch( const char * buf, +@@ -1578,6 +1652,17 @@ static JSONStatus_t multiSearch( const char * buf, coreJSON_ASSERT( ( max > 0U ) && ( queryLength > 0U ) ); - + while( i < queryLength ) + assigns( i, start, queryStart, value, length ) + loopInvariant( @@ -199,4 +191,4 @@ index 901b2e1..8bdd89c 100644 + decreases( queryLength - i ) { bool found = false; - + From bfb794ccb3b0eb39f40643eb9c26bf5e7bc5676e Mon Sep 17 00:00:00 2001 From: Gaurav Aggarwal Date: Fri, 19 Jul 2024 07:59:14 +0000 Subject: [PATCH 4/6] Update code as per review feedback Signed-off-by: Gaurav Aggarwal --- source/core_json.c | 35 +++++++++++++++++++------------- test/unit-test/core_json_utest.c | 7 +++++++ 2 files changed, 28 insertions(+), 14 deletions(-) diff --git a/source/core_json.c b/source/core_json.c index 18d9e768..d8694f0c 100644 --- a/source/core_json.c +++ b/source/core_json.c @@ -60,6 +60,8 @@ typedef union #define isMatchingBracket_( x, y ) ( isCurlyPair_( x, y ) || isSquarePair_( x, y ) ) #define isSquareOpen_( x ) ( ( x ) == '[' ) #define isSquareClose_( x ) ( ( x ) == ']' ) +#define isCurlyOpen_( x ) ( ( x ) == '{' ) +#define isCurlyClose_( x ) ( ( x ) == '}' ) /** * @brief Advance buffer index beyond whitespace. @@ -980,14 +982,13 @@ static bool skipObjectScalars( const char * buf, size_t * start, size_t max ) { - size_t i = 0U, origStart = 0U; + size_t i = 0U; bool comma = false; bool ret = true; coreJSON_ASSERT( ( buf != NULL ) && ( start != NULL ) && ( max > 0U ) ); i = *start; - origStart = *start; while( i < max ) { @@ -1029,12 +1030,6 @@ static bool skipObjectScalars( const char * buf, } } - /* An empty JSON object is valid. */ - if( i == origStart ) - { - ret = true; - } - return ret; } @@ -1054,6 +1049,7 @@ static bool skipScalars( const char * buf, size_t max, char mode ) { + size_t i = 0U; bool modeIsOpenBracket = ( bool ) isOpenBracket_( mode ); bool ret = true; @@ -1067,13 +1063,24 @@ static bool skipScalars( const char * buf, skipSpace( buf, start, max ); - if( mode == '[' ) - { - skipArrayScalars( buf, start, max ); - } - else + i = *start; + + if( i < max ) { - ret = skipObjectScalars( buf, start, max ); + if( mode == '[' ) + { + if( !isSquareClose_( buf[ i ] ) ) + { + skipArrayScalars( buf, start, max ); + } + } + else + { + if( !isCurlyClose_( buf[ i ] ) ) + { + ret = skipObjectScalars( buf, start, max ); + } + } } return ret; diff --git a/test/unit-test/core_json_utest.c b/test/unit-test/core_json_utest.c index 38e37902..f3c29866 100644 --- a/test/unit-test/core_json_utest.c +++ b/test/unit-test/core_json_utest.c @@ -149,6 +149,9 @@ #define JSON_DOC_LEGAL_EMPTY_OBJECT "{\"foo\":{}}" #define JSON_DOC_LEGAL_EMPTY_OBJECT_LENGTH ( sizeof( JSON_DOC_LEGAL_EMPTY_OBJECT ) - 1 ) +#define JSON_DOC_LEGAL_EMPTY_ARRAY "{\"foo\":[]}" +#define JSON_DOC_LEGAL_EMPTY_ARRAY_LENGTH ( sizeof( JSON_DOC_LEGAL_EMPTY_ARRAY ) - 1 ) + /* A single scalar is still considered a valid JSON document. */ #define SINGLE_SCALAR "\"l33t\"" #define SINGLE_SCALAR_LENGTH ( sizeof( SINGLE_SCALAR ) - 1 ) @@ -571,6 +574,10 @@ void test_JSON_Validate_Legal_Documents( void ) JSON_DOC_LEGAL_EMPTY_OBJECT_LENGTH ); TEST_ASSERT_EQUAL( JSONSuccess, jsonStatus ); + jsonStatus = JSON_Validate( JSON_DOC_LEGAL_EMPTY_ARRAY, + JSON_DOC_LEGAL_EMPTY_ARRAY_LENGTH ); + TEST_ASSERT_EQUAL( JSONSuccess, jsonStatus ); + jsonStatus = JSON_Validate( JSON_DOC_MULTIPLE_VALID_ESCAPES, JSON_DOC_MULTIPLE_VALID_ESCAPES_LENGTH ); TEST_ASSERT_EQUAL( JSONSuccess, jsonStatus ); From 25423f00ea20b461596cc7aedcc28a85e5f0f21c Mon Sep 17 00:00:00 2001 From: Gaurav Aggarwal Date: Fri, 19 Jul 2024 08:03:58 +0000 Subject: [PATCH 5/6] Fix memory statistics Signed-off-by: Gaurav Aggarwal --- docs/doxygen/include/size_table.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/doxygen/include/size_table.md b/docs/doxygen/include/size_table.md index 6872985a..dbc91357 100644 --- a/docs/doxygen/include/size_table.md +++ b/docs/doxygen/include/size_table.md @@ -9,12 +9,12 @@ core_json.c -
3.1K
+
3.0K
2.5K
Total estimates -
3.1K
+
3.0K
2.5K
From 4cc90322f1a2c1bf414138127f78ba0938ba7d3f Mon Sep 17 00:00:00 2001 From: Gaurav Aggarwal Date: Fri, 19 Jul 2024 11:07:47 +0000 Subject: [PATCH 6/6] Fix CBMC Proofs Signed-off-by: Gaurav Aggarwal --- loop_invariants.patch | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/loop_invariants.patch b/loop_invariants.patch index a8a05fb7..581f1dfd 100644 --- a/loop_invariants.patch +++ b/loop_invariants.patch @@ -1,10 +1,10 @@ diff --git a/source/core_json.c b/source/core_json.c -index 18d9e76..0197de9 100644 +index d8694f0..761c44b 100644 --- a/source/core_json.c +++ b/source/core_json.c -@@ -61,6 +61,21 @@ typedef union - #define isSquareOpen_( x ) ( ( x ) == '[' ) - #define isSquareClose_( x ) ( ( x ) == ']' ) +@@ -63,6 +63,21 @@ typedef union + #define isCurlyOpen_( x ) ( ( x ) == '{' ) + #define isCurlyClose_( x ) ( ( x ) == '}' ) +/** + * Renaming all loop-contract clauses from CBMC for readability. @@ -24,7 +24,7 @@ index 18d9e76..0197de9 100644 /** * @brief Advance buffer index beyond whitespace. * -@@ -77,6 +92,9 @@ static void skipSpace( const char * buf, +@@ -79,6 +94,9 @@ static void skipSpace( const char * buf, coreJSON_ASSERT( ( buf != NULL ) && ( start != NULL ) && ( max > 0U ) ); for( i = *start; i < max; i++ ) @@ -34,7 +34,7 @@ index 18d9e76..0197de9 100644 { if( !isspace_( buf[ i ] ) ) { -@@ -101,6 +119,13 @@ static size_t countHighBits( uint8_t c ) +@@ -103,6 +121,13 @@ static size_t countHighBits( uint8_t c ) size_t i = 0; while( ( n & 0x80U ) != 0U ) @@ -48,7 +48,7 @@ index 18d9e76..0197de9 100644 { i++; n = ( n & 0x7FU ) << 1U; -@@ -209,6 +234,13 @@ static bool skipUTF8MultiByte( const char * buf, +@@ -211,6 +236,13 @@ static bool skipUTF8MultiByte( const char * buf, /* The bit count is 1 greater than the number of bytes, * e.g., when j is 2, we skip one more byte. */ for( j = bitCount - 1U; j > 0U; j-- ) @@ -62,7 +62,7 @@ index 18d9e76..0197de9 100644 { i++; -@@ -344,6 +376,12 @@ static bool skipOneHexEscape( const char * buf, +@@ -346,6 +378,12 @@ static bool skipOneHexEscape( const char * buf, if( ( end < max ) && ( buf[ i ] == '\\' ) && ( buf[ i + 1U ] == 'u' ) ) { for( i += 2U; i < end; i++ ) @@ -75,7 +75,7 @@ index 18d9e76..0197de9 100644 { uint8_t n = hexToInt( buf[ i ] ); -@@ -521,6 +559,9 @@ static bool skipString( const char * buf, +@@ -523,6 +561,9 @@ static bool skipString( const char * buf, i++; while( i < max ) @@ -85,7 +85,7 @@ index 18d9e76..0197de9 100644 { if( buf[ i ] == '"' ) { -@@ -579,6 +620,9 @@ static bool strnEq( const char * a, +@@ -581,6 +622,9 @@ static bool strnEq( const char * a, coreJSON_ASSERT( ( a != NULL ) && ( b != NULL ) ); for( i = 0; i < n; i++ ) @@ -95,7 +95,7 @@ index 18d9e76..0197de9 100644 { if( a[ i ] != b[ i ] ) { -@@ -694,6 +738,9 @@ static bool skipDigits( const char * buf, +@@ -696,6 +740,9 @@ static bool skipDigits( const char * buf, saveStart = *start; for( i = *start; i < max; i++ ) @@ -105,7 +105,7 @@ index 18d9e76..0197de9 100644 { if( !isdigit_( buf[ i ] ) ) { -@@ -943,6 +990,9 @@ static void skipArrayScalars( const char * buf, +@@ -945,6 +992,9 @@ static void skipArrayScalars( const char * buf, i = *start; while( i < max ) @@ -115,8 +115,8 @@ index 18d9e76..0197de9 100644 { if( skipAnyScalar( buf, &i, max ) != true ) { -@@ -990,6 +1040,13 @@ static bool skipObjectScalars( const char * buf, - origStart = *start; +@@ -991,6 +1041,13 @@ static bool skipObjectScalars( const char * buf, + i = *start; while( i < max ) + assigns( i, *start, comma ) @@ -129,7 +129,7 @@ index 18d9e76..0197de9 100644 { if( skipString( buf, &i, max ) != true ) { -@@ -1111,6 +1168,14 @@ static JSONStatus_t skipCollection( const char * buf, +@@ -1118,6 +1175,14 @@ static JSONStatus_t skipCollection( const char * buf, i = *start; while( i < max ) @@ -144,7 +144,7 @@ index 18d9e76..0197de9 100644 { c = buf[ i ]; i++; -@@ -1400,6 +1465,9 @@ static bool objectSearch( const char * buf, +@@ -1407,6 +1472,9 @@ static bool objectSearch( const char * buf, skipSpace( buf, &i, max ); while( i < max ) @@ -154,7 +154,7 @@ index 18d9e76..0197de9 100644 { if( nextKeyValuePair( buf, &i, max, &key, &keyLength, &value, &valueLength ) != true ) -@@ -1467,6 +1535,9 @@ static bool arraySearch( const char * buf, +@@ -1474,6 +1542,9 @@ static bool arraySearch( const char * buf, skipSpace( buf, &i, max ); while( i < max ) @@ -164,7 +164,7 @@ index 18d9e76..0197de9 100644 { if( nextValue( buf, &i, max, &value, &valueLength ) != true ) { -@@ -1532,6 +1603,9 @@ static bool skipQueryPart( const char * buf, +@@ -1539,6 +1610,9 @@ static bool skipQueryPart( const char * buf, while( ( i < max ) && !isSeparator_( buf[ i ] ) && !isSquareOpen_( buf[ i ] ) ) @@ -174,7 +174,7 @@ index 18d9e76..0197de9 100644 { i++; } -@@ -1578,6 +1652,17 @@ static JSONStatus_t multiSearch( const char * buf, +@@ -1585,6 +1659,17 @@ static JSONStatus_t multiSearch( const char * buf, coreJSON_ASSERT( ( max > 0U ) && ( queryLength > 0U ) ); while( i < queryLength )