Skip to content

Commit 8d216b5

Browse files
authored
Restructure function contracts for readability (#142)
* Restructure function contracts for readability Signed-off-by: Felipe R. Monteiro <[email protected]> * Update lexicon list Signed-off-by: Felipe R. Monteiro <[email protected]> * Update contracts Signed-off-by: Felipe R. Monteiro <[email protected]> * Avoid code duplication Signed-off-by: Felipe R. Monteiro <[email protected]> * Upgrade CBMC version in CI Signed-off-by: Felipe R. Monteiro <[email protected]> --------- Signed-off-by: Felipe R. Monteiro <[email protected]>
1 parent 7b24709 commit 8d216b5

File tree

10 files changed

+451
-138
lines changed

10 files changed

+451
-138
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ jobs:
120120
- name: Set up CBMC runner
121121
uses: FreeRTOS/CI-CD-Github-Actions/set_up_cbmc_runner@main
122122
with:
123-
cbmc_version: "5.73.0"
123+
cbmc_version: "latest"
124124
cadical_tag: "latest"
125125
kissat_tag: "latest"
126126
- name: Run CBMC

lexicon.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ dc
2020
defgroup
2121
df
2222
dfff
23+
diffblue
2324
ecma
2425
ef
2526
endcode
@@ -43,6 +44,7 @@ ifndef
4344
inc
4445
ingroup
4546
int
47+
io
4648
iot
4749
iso
4850
json

test/cbmc/include/core_json_contracts.h

Lines changed: 176 additions & 133 deletions
Large diffs are not rendered by default.

test/cbmc/proofs/JSON_SearchConst/Makefile

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ HARNESS_FILE= $(PROOF_UID)_harness
77

88
USE_DYNAMIC_FRAMES = 1
99

10-
CBMC_OBJECT_BITS = 12
10+
CBMC_OBJECT_BITS = 11
1111

1212
UNWINDSET += multiSearch.0:$(CBMC_MAX_QUERYKEYLENGTH)
1313
UNWINDSET += skipQueryPart.0:$(CBMC_MAX_QUERYKEYLENGTH)
@@ -20,6 +20,8 @@ USE_FUNCTION_CONTRACTS += skipDigits
2020
USE_FUNCTION_CONTRACTS += skipSpace
2121
USE_FUNCTION_CONTRACTS += skipString
2222

23+
USE_EXTERNAL_SAT_SOLVER ?= --external-sat-solver cadical
24+
2325
include ../Makefile-json.common
2426

2527
# Substitution command to pass to sed for patching core_json.c. The

test/cbmc/proofs/JSON_Validate/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ UNWINDSET += skipSpace.0:$(CBMC_MAX_BUFSIZE)
1414
USE_FUNCTION_CONTRACTS += skipAnyScalar
1515
USE_FUNCTION_CONTRACTS += skipCollection
1616

17+
USE_EXTERNAL_SAT_SOLVER ?= --external-sat-solver cadical
18+
1719
include ../Makefile-json.common
1820

1921
# Substitution command to pass to sed for patching core_json.c. The

test/cbmc/proofs/Makefile-json.common

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,14 @@ endif
1616
INCLUDES += -I$(CBMC_ROOT)/include
1717

1818
PROOF_SOURCES += $(PROOFDIR)/$(HARNESS_FILE).c
19+
PROOF_SOURCES += $(PROOF_SOURCE)/core_json_contracts.c
1920

2021
PROJECT_SOURCES += $(PROOFDIR)/core_json.c
2122

2223
CHECKFLAGS += --pointer-primitive-check
2324

25+
CBMCFLAGS += --slice-formula
26+
2427
include ../Makefile.common
2528

2629
cleanclean: veryclean

test/cbmc/proofs/objectSearch/Makefile

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ HARNESS_FILE= $(PROOF_UID)_harness
99

1010
USE_DYNAMIC_FRAMES = 1
1111

12-
CBMC_OBJECT_BITS = 12
12+
CBMC_OBJECT_BITS = 11
1313

1414
UNWINDSET += objectSearch.0:$(CBMC_MAX_BUFSIZE)
1515
UNWINDSET += strnEq.0:$(CBMC_MAX_BUFSIZE)
@@ -19,6 +19,8 @@ USE_FUNCTION_CONTRACTS += skipCollection
1919
USE_FUNCTION_CONTRACTS += skipSpace
2020
USE_FUNCTION_CONTRACTS += skipString
2121

22+
USE_EXTERNAL_SAT_SOLVER ?= --external-sat-solver cadical
23+
2224
include ../Makefile-json.common
2325

2426
# Substitution command to pass to sed for patching core_json.c. The

test/cbmc/proofs/skipObjectScalars/Makefile

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,16 @@ HARNESS_FILE= $(PROOF_UID)_harness
99

1010
USE_DYNAMIC_FRAMES = 1
1111

12-
CBMC_OBJECT_BITS = 12
12+
CBMC_OBJECT_BITS = 11
1313

1414
UNWINDSET += skipObjectScalars.0:$(CBMC_MAX_BUFSIZE)
1515

1616
USE_FUNCTION_CONTRACTS += skipSpace
1717
USE_FUNCTION_CONTRACTS += skipAnyScalar
1818
USE_FUNCTION_CONTRACTS += skipString
1919

20+
USE_EXTERNAL_SAT_SOLVER ?= --external-sat-solver cadical
21+
2022
include ../Makefile-json.common
2123

2224
# Substitution command to pass to sed for patching core_json.c. The

test/cbmc/proofs/skipScalars/Makefile

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ HARNESS_FILE= $(PROOF_UID)_harness
77

88
USE_DYNAMIC_FRAMES = 1
99

10-
CBMC_OBJECT_BITS = 12
10+
CBMC_OBJECT_BITS = 11
1111

1212
UNWINDSET += skipArrayScalars.0:$(CBMC_MAX_BUFSIZE)
1313

@@ -16,6 +16,8 @@ USE_FUNCTION_CONTRACTS += skipObjectScalars
1616
USE_FUNCTION_CONTRACTS += skipSpace
1717
USE_FUNCTION_CONTRACTS += skipString
1818

19+
USE_EXTERNAL_SAT_SOLVER ?= --external-sat-solver cadical
20+
1921
include ../Makefile-json.common
2022

2123
# Substitution command to pass to sed for patching core_json.c. The
Lines changed: 255 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,255 @@
1+
/*
2+
* coreJSON v3.2.0
3+
* Copyright (C) 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
4+
*
5+
* SPDX-License-Identifier: MIT
6+
*
7+
* Permission is hereby granted, free of charge, to any person obtaining a copy of
8+
* this software and associated documentation files (the "Software"), to deal in
9+
* the Software without restriction, including without limitation the rights to
10+
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
11+
* the Software, and to permit persons to whom the Software is furnished to do so,
12+
* subject to the following conditions:
13+
*
14+
* The above copyright notice and this permission notice shall be included in all
15+
* copies or substantial portions of the Software.
16+
*
17+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
19+
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
20+
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21+
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22+
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23+
*/
24+
25+
#ifndef CORE_JSON_CONTRACTS_C_
26+
#define CORE_JSON_CONTRACTS_C_
27+
28+
#include "core_json_contracts.h"
29+
30+
/**
31+
* When to use `&` vs `&&`:
32+
* Prefer `cond1 & cond2` when `cond2` can be evaluated without errors without knowing that `cond1` holds: e.g. `( 0 < i ) & ( i < j )`.
33+
*
34+
* Use `cond1 && cond2` when `cond1` must be established first to ensure that `cond2` can be evaluated without error: e.g.
35+
* `( allocated( p, size ) & ( 0 < i & i < size ) ) && p[i] > 0`.
36+
*/
37+
38+
/* Valid allocated buffer up to size max. */
39+
bool isValidBoundedBuffer( char * buf,
40+
size_t max )
41+
{
42+
return ( 0 < max && max < CBMC_MAX_BUFSIZE )
43+
& ( allocated( buf, max ) );
44+
}
45+
46+
/* Valid allocated buffer up to size max and allocated start index. */
47+
bool isValidBoundedBufferWithStartIndex( char * buf,
48+
size_t max,
49+
size_t * start )
50+
{
51+
return isValidBoundedBuffer( buf, max )
52+
& ( allocated( start, sizeof( *start ) ) );
53+
}
54+
55+
/* Invariant for index in the buffer. */
56+
bool isValidStart( size_t start,
57+
size_t old_start,
58+
size_t max )
59+
{
60+
return ( start >= old_start ) &&
61+
( ( old_start < max ) ? ( start <= max ) : ( start == old_start ) );
62+
}
63+
64+
bool JSON_SearchConstPreconditions( char * buf,
65+
size_t max,
66+
char * query,
67+
size_t queryLength,
68+
char ** outValue,
69+
size_t * outValueLength,
70+
JSONTypes_t * outType )
71+
{
72+
return ( max < CBMC_MAX_BUFSIZE )
73+
& ( queryLength < CBMC_MAX_QUERYKEYLENGTH )
74+
& ( buf == NULL || allocated( buf, max ) )
75+
& ( query == NULL || allocated( query, queryLength ) )
76+
& ( outValue == NULL || allocated( outValue, sizeof( *outValue ) ) )
77+
& ( outValueLength == NULL || allocated( outValueLength, sizeof( *outValueLength ) ) )
78+
& ( outType == NULL || allocated( outType, sizeof( *outType ) ) );
79+
}
80+
81+
bool JSON_SearchConstPostconditions( JSONStatus_t result,
82+
char * buf,
83+
char ** outValue,
84+
size_t * outValueLength,
85+
size_t max )
86+
{
87+
bool validity = isJSONSearchEnum( result );
88+
89+
if( validity && ( result == JSONSuccess ) )
90+
{
91+
char * endOfValue = *outValue + *outValueLength;
92+
char * endOfBuf = buf + max;
93+
validity = pointer_in_range( buf, endOfValue, endOfBuf );
94+
}
95+
96+
return validity;
97+
}
98+
99+
bool JSON_IteratePreconditions( char * buf,
100+
size_t max,
101+
size_t * start,
102+
size_t * next,
103+
JSONPair_t * outPair )
104+
{
105+
return ( 0 < max && max < CBMC_MAX_BUFSIZE )
106+
& ( buf == NULL || allocated( buf, max ) )
107+
& ( start == NULL || allocated( start, sizeof( *start ) ) )
108+
& ( next == NULL || allocated( next, sizeof( *next ) ) )
109+
& ( outPair == NULL || allocated( outPair, sizeof( *outPair ) ) )
110+
& IMPLIES( outPair != NULL, ( ( outPair->keyLength == 0 && outPair->key == NULL ) || allocated( outPair->key, outPair->keyLength ) ) )
111+
& IMPLIES( outPair != NULL, ( ( outPair->valueLength == 0 && outPair->value == NULL ) || allocated( outPair->value, outPair->valueLength ) ) );
112+
}
113+
114+
bool JSON_IteratePostconditions( JSONStatus_t result,
115+
char * buf,
116+
size_t max,
117+
JSONPair_t * outPair )
118+
{
119+
bool validity = isJSONIterateEnum( result );
120+
121+
if( validity && ( result == JSONSuccess ) )
122+
{
123+
validity = IMPLIES( ( outPair->key != NULL ), ( ( outPair->key > buf ) && ( ( outPair->key + outPair->keyLength ) < ( buf + max ) ) ) )
124+
& IMPLIES( ( outPair->key != NULL ), ( ( outPair->key + outPair->keyLength ) < outPair->value ) )
125+
& ( ( outPair->value > buf ) && ( ( outPair->value + outPair->valueLength ) <= ( buf + max ) ) )
126+
& ( isJSONTypesEnum( outPair->jsonType ) );
127+
}
128+
129+
return validity;
130+
}
131+
132+
JSONStatus_t JSON_ValidatePreconditions( char * buf,
133+
size_t max )
134+
{
135+
return ( max < CBMC_MAX_BUFSIZE )
136+
& ( buf == NULL || allocated( buf, max ) );
137+
}
138+
139+
bool arraySearchPreconditions( char * buf,
140+
size_t max,
141+
size_t * outValue,
142+
size_t * outValueLength )
143+
{
144+
return ( isValidBoundedBuffer( buf, max ) )
145+
& ( allocated( outValue, sizeof( *outValue ) ) )
146+
& ( allocated( outValueLength, sizeof( *outValueLength ) ) )
147+
& ( *outValueLength <= max );
148+
}
149+
150+
bool arraySearchPostconditions( bool result,
151+
char * buf,
152+
size_t max,
153+
size_t * outValue,
154+
size_t * outValueLength,
155+
size_t old_outValue,
156+
size_t old_outValueLength )
157+
{
158+
bool validity = true;
159+
160+
if( result )
161+
{
162+
validity = ( 0 <= *outValue && *outValue < max ) &&
163+
( 0 < *outValueLength && *outValueLength <= max - *outValue ) &&
164+
IMPLIES( buf[ *outValue ] == '"', ( 2 <= *outValueLength && *outValueLength <= max - *outValue ) );
165+
}
166+
else
167+
{
168+
validity = ( *outValue == old_outValue ) &&
169+
( *outValueLength == old_outValueLength );
170+
}
171+
172+
return validity;
173+
}
174+
175+
bool objectSearchPreconditions( char * buf,
176+
size_t max,
177+
const char * query,
178+
size_t queryLength,
179+
size_t * outValue,
180+
size_t * outValueLength )
181+
{
182+
return arraySearchPreconditions( buf, max, outValue, outValueLength )
183+
& ( queryLength < CBMC_MAX_QUERYKEYLENGTH )
184+
& ( allocated( query, queryLength ) );
185+
}
186+
187+
bool skipPostconditions( bool result,
188+
char * buf,
189+
size_t * start,
190+
size_t old_start,
191+
size_t max,
192+
size_t gap )
193+
{
194+
bool validity = isValidStart( *start, old_start, max ) &&
195+
IMPLIES( result, ( old_start < max ) && ( *start > old_start + gap ) );
196+
197+
return validity;
198+
}
199+
200+
bool skipCollectionPostconditions( JSONStatus_t result,
201+
char * buf,
202+
size_t * start,
203+
size_t old_start,
204+
size_t max )
205+
{
206+
bool validity = isSkipCollectionEnum( result ) &&
207+
skipPostconditions( ( result == JSONSuccess ), buf, start, old_start, max, 1 );
208+
209+
return validity;
210+
}
211+
212+
bool skipScalarsPreconditions( char * buf,
213+
size_t * start,
214+
size_t max,
215+
char mode )
216+
{
217+
return ( ( mode == '{' ) || ( mode == '[' ) )
218+
& isValidBoundedBufferWithStartIndex( buf, max, start );
219+
}
220+
221+
bool skipAnyScalarPostconditions( bool result,
222+
char * buf,
223+
size_t * start,
224+
size_t old_start,
225+
size_t max )
226+
{
227+
bool validity = skipPostconditions( result, buf, start, old_start, max, 0 ) &&
228+
IMPLIES( ( result && ( buf[ old_start ] == '"' ) ), *start >= old_start + 2 );
229+
230+
return validity;
231+
}
232+
233+
bool skipDigitsPreconditions( char * buf,
234+
size_t * start,
235+
size_t max,
236+
int32_t * outValue )
237+
{
238+
return ( outValue == NULL || allocated( outValue, sizeof( *outValue ) ) )
239+
& isValidBoundedBufferWithStartIndex( buf, max, start );
240+
}
241+
242+
bool skipDigitsPostconditions( bool result,
243+
char * buf,
244+
size_t * start,
245+
size_t old_start,
246+
size_t max,
247+
size_t gap )
248+
{
249+
bool validity = skipPostconditions( result, buf, start, old_start, max, 0 ) &&
250+
IMPLIES( result, ( ( ( buf[ old_start ] ) >= '0' ) && ( ( buf[ old_start ] ) <= '9' ) ) );
251+
252+
return validity;
253+
}
254+
255+
#endif /* ifndef CORE_JSON_CONTRACTS_C_ */

0 commit comments

Comments
 (0)