@@ -36,10 +36,19 @@ typedef enum
3636 false = 0
3737} bool_ ;
3838
39- #define isdigit_ ( x ) ( ( x >= '0' ) && ( x <= '9' ) )
40- #define iscntrl_ ( x ) ( ( x >= '\0' ) && ( x < ' ' ) )
39+ /* A compromise to satisfy both MISRA and CBMC */
40+ typedef union
41+ {
42+ char c ;
43+ uint8_t u ;
44+ } char_ ;
45+
46+ #define isdigit_ ( x ) ( ( ( x ) >= '0' ) && ( ( x ) <= '9' ) )
47+ #define iscntrl_ ( x ) ( ( ( x ) >= '\0' ) && ( ( x ) < ' ' ) )
4148/* NB. This is whitespace as defined by the JSON standard (ECMA-404). */
42- #define isspace_ ( x ) ( ( x == ' ' ) || ( x == '\t' ) || ( x == '\n' ) || ( x == '\r' ) )
49+ #define isspace_ ( x ) \
50+ ( ( ( x ) == ' ' ) || ( ( x ) == '\t' ) || \
51+ ( ( x ) == '\n' ) || ( ( x ) == '\r' ) )
4352
4453/**
4554 * @brief Advance buffer index beyond whitespace.
@@ -112,7 +121,7 @@ static bool_ shortestUTF8( size_t length,
112121 bool_ ret = false;
113122 uint32_t min , max ;
114123
115- assert ( ( length >= 2 ) && ( length <= 4 ) );
124+ assert ( ( length >= 2U ) && ( length <= 4U ) );
116125
117126 switch ( length )
118127 {
@@ -171,20 +180,20 @@ static bool_ skipUTF8MultiByte( const char * buf,
171180 bool_ ret = false;
172181 size_t i , bitCount , j ;
173182 uint32_t value = 0 ;
174- uint8_t c ;
183+ char_ c ;
175184
176185 assert ( ( buf != NULL ) && ( start != NULL ) && ( max > 0U ) );
177186
178187 i = * start ;
179188 assert ( i < max );
180- assert ( buf [ i ] < 0 );
189+ assert ( buf [ i ] < '\0' );
181190
182- c = ( 0x80U | ( buf [ i ] & 0x7F ) ) ;
191+ c . c = buf [ i ];
183192
184- if ( ( c > 0xC1U ) && ( c < 0xF5U ) )
193+ if ( ( c . u > 0xC1U ) && ( c . u < 0xF5U ) )
185194 {
186- bitCount = countHighBits ( c );
187- value = ( ( uint32_t ) c ) & ( ( ( uint32_t ) 1 << ( 7U - bitCount ) ) - 1U );
195+ bitCount = countHighBits ( c . u );
196+ value = ( ( uint32_t ) c . u ) & ( ( ( uint32_t ) 1 << ( 7U - bitCount ) ) - 1U );
188197
189198 /* The bit count is 1 greater than the number of bytes,
190199 * e.g., when j is 2, we skip one more byte. */
@@ -197,13 +206,15 @@ static bool_ skipUTF8MultiByte( const char * buf,
197206 break ;
198207 }
199208
209+ c .c = buf [ i ];
210+
200211 /* Additional bytes must match 10xxxxxx. */
201- if ( ( buf [ i ] >= 0 ) || ( ( buf [ i ] & 0x40 ) != 0 ) )
212+ if ( ( c . u & 0xC0U ) != 0x80U )
202213 {
203214 break ;
204215 }
205216
206- value = ( value << 6U ) | ( buf [ i ] & 0x3F );
217+ value = ( value << 6U ) | ( c . u & 0x3FU );
207218 }
208219
209220 if ( ( j == 0U ) && ( shortestUTF8 ( bitCount , value ) == true ) )
@@ -237,7 +248,7 @@ static bool_ skipUTF8( const char * buf,
237248 if ( * start < max )
238249 {
239250 /* an ASCII byte */
240- if ( buf [ * start ] >= 0 )
251+ if ( buf [ * start ] >= '\0' )
241252 {
242253 * start += 1U ;
243254 ret = true;
@@ -256,69 +267,62 @@ static bool_ skipUTF8( const char * buf,
256267 *
257268 * @param[in] c The character to convert.
258269 *
259- * @return the integer value upon success or UINT8_MAX on failure.
270+ * @return the integer value upon success or NOT_A_HEX_CHAR on failure.
260271 */
272+ #define NOT_A_HEX_CHAR ( 0x10U )
261273static uint8_t hexToInt ( char c )
262274{
263- uint8_t n ;
275+ char_ n ;
276+
277+ n .c = c ;
264278
265279 if ( ( c >= 'a' ) && ( c <= 'f' ) )
266280 {
267- n = 10U + ( uint8_t ) ( c - 'a' );
281+ n .c -= 'a' ;
282+ n .u += 10U ;
268283 }
269284 else if ( ( c >= 'A' ) && ( c <= 'F' ) )
270285 {
271- n = 10U + ( uint8_t ) ( c - 'A' );
286+ n .c -= 'A' ;
287+ n .u += 10U ;
272288 }
273289 else if ( isdigit_ ( c ) )
274290 {
275- n = ( uint8_t ) ( c - '0' ) ;
291+ n . c -= '0' ;
276292 }
277293 else
278294 {
279- n = UINT8_MAX ;
295+ n . u = NOT_A_HEX_CHAR ;
280296 }
281297
282- return n ;
298+ return n . u ;
283299}
284300
285301/**
286- * @brief Advance buffer index beyond a \u Unicode escape sequence.
302+ * @brief Advance buffer index beyond a single \u Unicode
303+ * escape sequence and output the value.
287304 *
288305 * @param[in] buf The buffer to parse.
289306 * @param[in,out] start The index at which to begin.
290307 * @param[in] max The size of the buffer.
291- * @param[in] requireLowSurrogate true when a low surrogate is required.
292- *
293- * Surrogate pairs are two escape sequences that together denote
294- * a code point outside the Basic Multilingual Plane. They must
295- * occur as a pair with the first "high" value in [U+D800, U+DBFF],
296- * and the second "low" value in [U+DC00, U+DFFF].
308+ * @param[out] outValue The value of the hex digits.
297309 *
298310 * @return true if a valid escape sequence was present;
299311 * false otherwise.
300312 *
301313 * @note For the sake of security, \u0000 is disallowed.
302314 */
303- #define isHighSurrogate ( x ) ( ( ( x ) >= 0xD800U ) && ( ( x ) <= 0xDBFFU ) )
304- #define isLowSurrogate ( x ) ( ( ( x ) >= 0xDC00U ) && ( ( x ) <= 0xDFFFU ) )
305-
306- /* MISRA Rule 17.2 prohibits recursion due to the
307- * risk of exceeding available stack space. In this
308- * function, recursion is limited to exactly one level;
309- * the recursive call sets the final argument to true
310- * which satisfies the base case. */
311- /* coverity[misra_c_2012_rule_17_2_violation] */
312- static bool_ skipHexEscape ( const char * buf ,
313- size_t * start ,
314- size_t max ,
315- bool_ requireLowSurrogate )
315+ static bool_ skipOneHexEscape ( const char * buf ,
316+ size_t * start ,
317+ size_t max ,
318+ uint16_t * outValue )
316319{
317320 bool_ ret = false;
318321 size_t i , end ;
319322 uint16_t value = 0 ;
320323
321324 assert ( ( buf != NULL ) && ( start != NULL ) && ( max > 0U ) );
325+ assert ( outValue != NULL );
322326
323327 i = * start ;
324328#define HEX_ESCAPE_LENGTH ( 6U ) /* e.g., \u1234 */
@@ -330,37 +334,75 @@ static bool_ skipHexEscape( const char * buf,
330334 {
331335 uint8_t n = hexToInt ( buf [ i ] );
332336
333- if ( n == UINT8_MAX )
337+ if ( n == NOT_A_HEX_CHAR )
334338 {
335339 break ;
336340 }
337341
338342 value = ( value << 4U ) | n ;
339343 }
344+ }
340345
341- if ( ( i == end ) && ( value > 0U ) )
346+ if ( ( i == end ) && ( value > 0U ) )
347+ {
348+ ret = true;
349+ * outValue = value ;
350+ * start = i ;
351+ }
352+
353+ return ret ;
354+ }
355+
356+ /**
357+ * @brief Advance buffer index beyond one or a pair of \u Unicode escape sequences.
358+ *
359+ * @param[in] buf The buffer to parse.
360+ * @param[in,out] start The index at which to begin.
361+ * @param[in] max The size of the buffer.
362+ *
363+ * Surrogate pairs are two escape sequences that together denote
364+ * a code point outside the Basic Multilingual Plane. They must
365+ * occur as a pair with the first "high" value in [U+D800, U+DBFF],
366+ * and the second "low" value in [U+DC00, U+DFFF].
367+ *
368+ * @return true if a valid escape sequence was present;
369+ * false otherwise.
370+ *
371+ * @note For the sake of security, \u0000 is disallowed.
372+ */
373+ #define isHighSurrogate ( x ) ( ( ( x ) >= 0xD800U ) && ( ( x ) <= 0xDBFFU ) )
374+ #define isLowSurrogate ( x ) ( ( ( x ) >= 0xDC00U ) && ( ( x ) <= 0xDFFFU ) )
375+
376+ static bool_ skipHexEscape ( const char * buf ,
377+ size_t * start ,
378+ size_t max )
379+ {
380+ bool_ ret = false;
381+ size_t i ;
382+ uint16_t value ;
383+
384+ assert ( ( buf != NULL ) && ( start != NULL ) && ( max > 0U ) );
385+
386+ i = * start ;
387+
388+ if ( skipOneHexEscape ( buf , & i , max , & value ) == true )
389+ {
390+ if ( isHighSurrogate ( value ) )
342391 {
343- if ( requireLowSurrogate == true )
344- {
345- if ( isLowSurrogate ( value ) )
346- {
347- ret = true;
348- }
349- }
350- else if ( isHighSurrogate ( value ) )
351- {
352- /* low surrogate must follow */
353- ret = skipHexEscape ( buf , & i , max , true );
354- }
355- else if ( isLowSurrogate ( value ) )
356- {
357- /* premature low surrogate */
358- }
359- else
392+ if ( ( skipOneHexEscape ( buf , & i , max , & value ) == true ) &&
393+ ( isLowSurrogate ( value ) ) )
360394 {
361395 ret = true;
362396 }
363397 }
398+ else if ( isLowSurrogate ( value ) )
399+ {
400+ /* premature low surrogate */
401+ }
402+ else
403+ {
404+ ret = true;
405+ }
364406 }
365407
366408 if ( ret == true )
@@ -404,7 +446,7 @@ static bool_ skipEscape( const char * buf,
404446 break ;
405447
406448 case 'u' :
407- ret = skipHexEscape ( buf , & i , max , false );
449+ ret = skipHexEscape ( buf , & i , max );
408450 break ;
409451
410452 case '"' :
@@ -587,7 +629,7 @@ static bool_ skipAnyLiteral( const char * buf,
587629 bool_ ret = false;
588630
589631#define skipLit_ ( x ) \
590- ( skipLiteral( buf, start, max, x , ( sizeof( x ) - 1U ) ) == true )
632+ ( skipLiteral( buf, start, max, ( x ) , ( sizeof( x ) - 1U ) ) == true )
591633
592634 if ( skipLit_ ( "true" ) || skipLit_ ( "false" ) || skipLit_ ( "null" ) )
593635 {
@@ -1262,7 +1304,7 @@ static JSONStatus_t search( char * buf,
12621304 */
12631305JSONStatus_t JSON_Search ( char * buf ,
12641306 size_t max ,
1265- char * queryKey ,
1307+ const char * queryKey ,
12661308 size_t queryKeyLength ,
12671309 char separator ,
12681310 char * * outValue ,
0 commit comments