loop_invariants.patch 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. diff --git a/source/core_json.c b/source/core_json.c
  2. index a01c393..ad48f28 100644
  3. --- a/source/core_json.c
  4. +++ b/source/core_json.c
  5. @@ -63,6 +63,21 @@ typedef union
  6. #define isCurlyOpen_( x ) ( ( x ) == '{' )
  7. #define isCurlyClose_( x ) ( ( x ) == '}' )
  8. +/**
  9. + * Renaming all loop-contract clauses from CBMC for readability.
  10. + * For more information about loop contracts in CBMC, see
  11. + * https://diffblue.github.io/cbmc/contracts-user.html.
  12. + */
  13. +#ifdef CBMC
  14. + #define loopInvariant(...) __CPROVER_loop_invariant(__VA_ARGS__)
  15. + #define decreases(...) __CPROVER_decreases(__VA_ARGS__)
  16. + #define assigns(...) __CPROVER_assigns(__VA_ARGS__)
  17. +#else
  18. + #define loopInvariant(...)
  19. + #define decreases(...)
  20. + #define assigns(...)
  21. +#endif
  22. +
  23. /**
  24. * @brief Advance buffer index beyond whitespace.
  25. *
  26. @@ -79,6 +94,9 @@ static void skipSpace( const char * buf,
  27. coreJSON_ASSERT( ( buf != NULL ) && ( start != NULL ) && ( max > 0U ) );
  28. for( i = *start; i < max; i++ )
  29. + assigns( i )
  30. + loopInvariant( *start <= i && i <= max )
  31. + decreases( max - i )
  32. {
  33. if( !isspace_( buf[ i ] ) )
  34. {
  35. @@ -103,6 +121,13 @@ static size_t countHighBits( uint8_t c )
  36. size_t i = 0;
  37. while( ( n & 0x80U ) != 0U )
  38. + assigns( i, n )
  39. + loopInvariant (
  40. + ( 0U <= i ) && ( i <= 8U )
  41. + && ( n == ( c & ( 0xFF >> i ) ) << i )
  42. + && ( ( ( c >> ( 8U - i ) ) + 1U ) == ( 1U << i ) )
  43. + )
  44. + decreases( 8U - i )
  45. {
  46. i++;
  47. n = ( n & 0x7FU ) << 1U;
  48. @@ -211,6 +236,13 @@ static bool skipUTF8MultiByte( const char * buf,
  49. /* The bit count is 1 greater than the number of bytes,
  50. * e.g., when j is 2, we skip one more byte. */
  51. for( j = bitCount - 1U; j > 0U; j-- )
  52. + assigns( j, i, value, c.c )
  53. + loopInvariant(
  54. + ( 0 <= j ) && ( j <= bitCount - 1 )
  55. + && ( *start <= i ) && ( i <= max )
  56. + && ( ( i == max ) ==> ( j > 0 ) )
  57. + )
  58. + decreases( j )
  59. {
  60. i++;
  61. @@ -343,6 +375,12 @@ static bool skipOneHexEscape( const char * buf,
  62. if( ( end > i ) && ( end < max ) && ( buf[ i ] == '\\' ) && ( buf[ i + 1U ] == 'u' ) )
  63. {
  64. for( i += 2U; i < end; i++ )
  65. + assigns( value, i )
  66. + loopInvariant(
  67. + ( *start + 2U <= i ) && ( i <= end ) &&
  68. + ( 0U <= value ) && ( value < ( 1U << ( 4U * ( i - ( 2U + *start ) ) ) ) )
  69. + )
  70. + decreases( end - i )
  71. {
  72. uint8_t n = hexToInt( buf[ i ] );
  73. @@ -505,6 +543,9 @@ static bool skipString( const char * buf,
  74. i++;
  75. while( i < max )
  76. + assigns( i )
  77. + loopInvariant( *start + 1U <= i && i <= max )
  78. + decreases( max - i )
  79. {
  80. if( buf[ i ] == '"' )
  81. {
  82. @@ -563,6 +604,9 @@ static bool strnEq( const char * a,
  83. coreJSON_ASSERT( ( a != NULL ) && ( b != NULL ) );
  84. for( i = 0; i < n; i++ )
  85. + assigns( i )
  86. + loopInvariant( i <= n )
  87. + decreases( n - i )
  88. {
  89. if( a[ i ] != b[ i ] )
  90. {
  91. @@ -678,6 +722,9 @@ static bool skipDigits( const char * buf,
  92. saveStart = *start;
  93. for( i = *start; i < max; i++ )
  94. + assigns( value, i )
  95. + loopInvariant( *start <= i && i <= max )
  96. + decreases( max - i )
  97. {
  98. if( !isdigit_( buf[ i ] ) )
  99. {
  100. @@ -928,6 +975,9 @@ static bool skipArrayScalars( const char * buf,
  101. i = *start;
  102. while( i < max )
  103. + assigns( i )
  104. + loopInvariant( *start <= i && i <= max )
  105. + decreases( max - i )
  106. {
  107. if( skipAnyScalar( buf, &i, max ) != true )
  108. {
  109. @@ -982,6 +1032,13 @@ static bool skipObjectScalars( const char * buf,
  110. i = *start;
  111. while( i < max )
  112. + assigns( i, *start, comma )
  113. + loopInvariant(
  114. + i >= *start
  115. + && __CPROVER_loop_entry( i ) <= i && i <= max
  116. + && __CPROVER_loop_entry( *start ) <= *start && *start <= max
  117. + )
  118. + decreases( max - i )
  119. {
  120. if( skipString( buf, &i, max ) != true )
  121. {
  122. @@ -1109,6 +1166,14 @@ static JSONStatus_t skipCollection( const char * buf,
  123. i = *start;
  124. while( i < max )
  125. + assigns( i, depth, c, ret, __CPROVER_object_whole( stack ) )
  126. + loopInvariant(
  127. + -1 <= depth && depth <= JSON_MAX_DEPTH
  128. + && *start <= i && i <= max
  129. + && ( ( ret == JSONSuccess ) ==> i >= *start + 2U )
  130. + && ( ret == JSONSuccess || ret == JSONPartial || ret == JSONIllegalDocument || ret == JSONMaxDepthExceeded )
  131. + )
  132. + decreases( max - i )
  133. {
  134. c = buf[ i ];
  135. i++;
  136. @@ -1144,6 +1209,7 @@ static JSONStatus_t skipCollection( const char * buf,
  137. if( skipSpaceAndComma( buf, &i, max ) == true )
  138. {
  139. + __CPROVER_assume( isOpenBracket_(stack[depth]));
  140. if( skipScalars( buf, &i, max, stack[ depth ] ) != true )
  141. {
  142. ret = JSONIllegalDocument;
  143. @@ -1406,6 +1472,9 @@ static bool objectSearch( const char * buf,
  144. skipSpace( buf, &i, max );
  145. while( i < max )
  146. + assigns( i, key, keyLength, value, valueLength )
  147. + loopInvariant( __CPROVER_loop_entry( i ) <= i && i <= max )
  148. + decreases( max - i )
  149. {
  150. if( nextKeyValuePair( buf, &i, max, &key, &keyLength,
  151. &value, &valueLength ) != true )
  152. @@ -1473,6 +1542,9 @@ static bool arraySearch( const char * buf,
  153. skipSpace( buf, &i, max );
  154. while( i < max )
  155. + assigns( i, currentIndex, value, valueLength )
  156. + loopInvariant( __CPROVER_loop_entry( i ) <= i && i <= max && currentIndex < i )
  157. + decreases( max - i )
  158. {
  159. if( nextValue( buf, &i, max, &value, &valueLength ) != true )
  160. {
  161. @@ -1538,6 +1610,9 @@ static bool skipQueryPart( const char * buf,
  162. while( ( i < max ) &&
  163. !isSeparator_( buf[ i ] ) &&
  164. !isSquareOpen_( buf[ i ] ) )
  165. + assigns( i )
  166. + loopInvariant( i <= max )
  167. + decreases( max - i )
  168. {
  169. i++;
  170. }
  171. @@ -1584,6 +1659,17 @@ static JSONStatus_t multiSearch( const char * buf,
  172. coreJSON_ASSERT( ( max > 0U ) && ( queryLength > 0U ) );
  173. while( i < queryLength )
  174. + assigns( i, start, queryStart, value, length )
  175. + loopInvariant(
  176. + 0U <= start && start < max
  177. + && 0U < length && length <= max
  178. + && start + length <= max
  179. + && ( ( i == queryLength && ret == JSONSuccess && buf[ start ] == '"' ) ==> length >= 2U )
  180. + && 0U <= value && value < max
  181. + && 0U <= i && i <= queryLength
  182. + && 0U <= queryStart && queryStart <= queryLength
  183. + )
  184. + decreases( queryLength - i )
  185. {
  186. bool found = false;