Skip to content

Commit ed10809

Browse files
authored
Merge branch 'diffblue:develop' into develop
2 parents 540b219 + f9a7807 commit ed10809

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+1247
-209
lines changed

.github/workflows/coverage.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ jobs:
6666
echo "lcov_excl_line = UNREACHABLE" > ~/.lcovrc
6767
cmake --build build --target coverage -- -j${{env.linux-vcpus}}
6868
- name: Upload coverage statistics to Codecov
69-
uses: codecov/codecov-action@v4
69+
uses: codecov/codecov-action@v5
7070
with:
7171
token: ${{ secrets.CODECOV_TOKEN }}
7272
files: build/html/coverage.info

.github/workflows/release-packages.yaml

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,77 @@ env:
66

77
name: Upload additional release assets
88
jobs:
9+
ubuntu-24_04-package:
10+
runs-on: ubuntu-24.04
11+
env:
12+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
13+
steps:
14+
- uses: actions/checkout@v4
15+
with:
16+
submodules: recursive
17+
- name: Fetch dependencies
18+
run: |
19+
sudo apt-get update
20+
sudo apt-get install --no-install-recommends -y g++ gdb flex bison cmake ninja-build maven jq libxml2-utils dpkg-dev ccache z3
21+
- name: Confirm z3 solver is available and log the version installed
22+
run: z3 --version
23+
- name: Download cvc-5 from the releases page and make sure it can be deployed
24+
run: |
25+
wget https://github.com/cvc5/cvc5/releases/download/cvc5-${{env.cvc5-version}}/cvc5-Linux-static.zip
26+
unzip -j -d /usr/local/bin cvc5-Linux-static.zip cvc5-Linux-static/bin/cvc5
27+
rm cvc5-Linux-static.zip
28+
cvc5 --version
29+
- name: Prepare ccache
30+
uses: actions/cache@v4
31+
with:
32+
save-always: true
33+
path: .ccache
34+
key: ${{ runner.os }}-24.04-Release-${{ github.ref }}-${{ github.sha }}-RELEASEPKG
35+
restore-keys:
36+
${{ runner.os }}-24.04-Release-${{ github.ref }}
37+
${{ runner.os }}-24.04-Release
38+
- name: ccache environment
39+
run: |
40+
echo "CCACHE_BASEDIR=$PWD" >> $GITHUB_ENV
41+
echo "CCACHE_DIR=$PWD/.ccache" >> $GITHUB_ENV
42+
- name: Configure CMake
43+
run: cmake -S . -Bbuild -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=/usr/bin/gcc -DCMAKE_CXX_COMPILER=/usr/bin/g++ -Dsat_impl="minisat2;cadical"
44+
- name: Zero ccache stats and limit in size
45+
run: ccache -z --max-size=500M
46+
- name: Build using Ninja
47+
run: ninja -C build -j4
48+
- name: Print ccache stats
49+
run: ccache -s
50+
- name: Run CTest
51+
run: cd build; ctest . -V -L CORE -C Release -j4
52+
- name: Create packages
53+
id: create_packages
54+
run: |
55+
cd build
56+
ninja package
57+
deb_package_name="$(ls *.deb)"
58+
echo "deb_package=./build/$deb_package_name" >> $GITHUB_OUTPUT
59+
echo "deb_package_name=ubuntu-24.04-$deb_package_name" >> $GITHUB_OUTPUT
60+
- name: Get release info
61+
id: get_release_info
62+
uses: bruceadams/[email protected]
63+
- name: Upload binary packages
64+
uses: actions/upload-release-asset@v1
65+
with:
66+
upload_url: ${{ steps.get_release_info.outputs.upload_url }}
67+
asset_path: ${{ steps.create_packages.outputs.deb_package }}
68+
asset_name: ${{ steps.create_packages.outputs.deb_package_name }}
69+
asset_content_type: application/x-deb
70+
- name: Slack notification of CI status
71+
uses: rtCamp/action-slack-notify@v2
72+
if: success() || failure()
73+
env:
74+
SLACK_CHANNEL: aws-cbmc
75+
SLACK_COLOR: ${{ job.status }}
76+
SLACK_USERNAME: Github Actions CI bot
77+
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }}
78+
SLACK_MESSAGE: "${{ job.status == 'success' && 'Ubuntu 24.04 package built and uploaded successfully' || 'Ubuntu 24.04 package build failed' }}"
79+
980
ubuntu-22_04-package:
1081
runs-on: ubuntu-22.04
1182
env:

CHANGELOG

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,23 @@
1+
# CBMC 6.4.1
2+
3+
This patch release addresses a hard-coding of C semantics in the back-end for pointer subtraction (via #8497).
4+
5+
## Bug Fixes
6+
* fix `update_bit` lowering by @kroening in https://github.com/diffblue/cbmc/pull/8496
7+
* Pointer subtraction in back-end: no need for bounds checking by @tautschnig in https://github.com/diffblue/cbmc/pull/8497
8+
* remove duplicate SATCHECK_* defines by @kroening in https://github.com/diffblue/cbmc/pull/8501
9+
* simplify bitxnor by @kroening in https://github.com/diffblue/cbmc/pull/8506
10+
* Reword documentation of __CPROVER_{r,w,rw}_ok by @tautschnig in https://github.com/diffblue/cbmc/pull/8472
11+
* simplify x^0 and x^1 by @kroening in https://github.com/diffblue/cbmc/pull/8509
12+
* add multi-ary constructor for `mult_exprt` by @kroening in https://github.com/diffblue/cbmc/pull/8510
13+
* Format bit-vectors with `[` ... `]` vector notation by @kroening in https://github.com/diffblue/cbmc/pull/8514
14+
* add range_type to `from_integer`/`to_integer` by @kroening in https://github.com/diffblue/cbmc/pull/8520
15+
* Bump codecov/codecov-action from 4 to 5 by @dependabot in https://github.com/diffblue/cbmc/pull/8507
16+
* CONTRACTS: add doc for loop assigns inference by @qinheping in https://github.com/diffblue/cbmc/pull/8516
17+
* Cadical with preprocessor and local search by @kroening in https://github.com/diffblue/cbmc/pull/8502
18+
19+
**Full Changelog**: https://github.com/diffblue/cbmc/compare/cbmc-6.4.0...cbmc-6.4.1
20+
121
# CBMC 6.4.0
222

323
This release improves upon automated assigns-clause inference for loop invariants, which should make manually adding assigns clauses to loops less frequent.

doc/cprover-manual/memory-primitives.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -233,11 +233,11 @@ number of bytes:
233233
- `_Bool __CPROVER_w_ok(const void *p, size_t size)`
234234
235235
At present, both primitives are equivalent as all memory in CBMC is considered
236-
both readable and writeable. If `p` is the null pointer, the primitives return
237-
false. If `p` is valid, the primitives return true if the memory segment
238-
starting at the pointer has at least the given size, and false otherwise. If `p`
239-
is neither null nor valid, the semantics is unspecified. It is valid to apply
240-
the primitive to pointers that point to within a memory object. For example:
236+
both readable and writeable. The primitives return true if `p` points to a live
237+
object and the object that `p` points into extends to at least `size` more
238+
bytes. Else, an assertion encompassing the primitive will be reported to fail.
239+
Do not use these primitives in assumptions when `p` can be not valid as such use
240+
can yield spurious verification results.
241241
242242
```C
243243
char *p = malloc(10);
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
enum my_enum
2+
{
3+
A = 1,
4+
B = 2
5+
};
6+
int my_array[10];
7+
8+
int main()
9+
{
10+
// should fail
11+
(enum my_enum)3;
12+
13+
// should fail
14+
my_array[(enum my_enum)4] = 10;
15+
16+
return 0;
17+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE
2+
enum_lhs.c
3+
--enum-range-check
4+
^\[main\.enum-range-check\.2\] line 14 enum range check in \(enum my_enum\)4: FAILURE$
5+
^EXIT=10$
6+
^SIGNAL=0$
7+
--
8+
--

src/ansi-c/goto-conversion/goto_check_c.cpp

Lines changed: 38 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -157,11 +157,13 @@ class goto_check_ct
157157
/// guard.
158158
/// \param expr: the expression to be checked
159159
/// \param guard: the condition for when the check should be made
160-
void check_rec(const exprt &expr, const guardt &guard);
160+
/// \param is_assigned: the expression is assigned to
161+
void check_rec(const exprt &expr, const guardt &guard, bool is_assigned);
161162

162163
/// Initiate the recursively analysis of \p expr with its `guard' set to TRUE.
163164
/// \param expr: the expression to be checked
164-
void check(const exprt &expr);
165+
/// \param is_assigned: the expression is assigned to
166+
void check(const exprt &expr, bool is_assigned);
165167

166168
struct conditiont
167169
{
@@ -183,7 +185,7 @@ class goto_check_ct
183185
void float_div_by_zero_check(const div_exprt &, const guardt &);
184186
void mod_by_zero_check(const mod_exprt &, const guardt &);
185187
void mod_overflow_check(const mod_exprt &, const guardt &);
186-
void enum_range_check(const exprt &, const guardt &);
188+
void enum_range_check(const exprt &, const guardt &, bool is_assigned);
187189
void undefined_shift_check(const shift_exprt &, const guardt &);
188190
void pointer_rel_check(const binary_exprt &, const guardt &);
189191
void pointer_overflow_check(const exprt &, const guardt &);
@@ -537,11 +539,17 @@ void goto_check_ct::float_div_by_zero_check(
537539
guard);
538540
}
539541

540-
void goto_check_ct::enum_range_check(const exprt &expr, const guardt &guard)
542+
void goto_check_ct::enum_range_check(
543+
const exprt &expr,
544+
const guardt &guard,
545+
bool is_assigned)
541546
{
542547
if(!enable_enum_range_check)
543548
return;
544549

550+
if(is_assigned)
551+
return; // not in range yet
552+
545553
// we might be looking at a lowered enum_is_in_range_exprt, skip over these
546554
const auto &pragmas = expr.source_location().get_pragmas();
547555
for(const auto &d : pragmas)
@@ -1807,13 +1815,13 @@ void goto_check_ct::check_rec_address(const exprt &expr, const guardt &guard)
18071815

18081816
if(expr.id() == ID_dereference)
18091817
{
1810-
check_rec(to_dereference_expr(expr).pointer(), guard);
1818+
check_rec(to_dereference_expr(expr).pointer(), guard, false);
18111819
}
18121820
else if(expr.id() == ID_index)
18131821
{
18141822
const index_exprt &index_expr = to_index_expr(expr);
18151823
check_rec_address(index_expr.array(), guard);
1816-
check_rec(index_expr.index(), guard);
1824+
check_rec(index_expr.index(), guard, false);
18171825
}
18181826
else
18191827
{
@@ -1843,7 +1851,7 @@ void goto_check_ct::check_rec_logical_op(const exprt &expr, const guardt &guard)
18431851
return guard(implication(conjunction(constraints), expr));
18441852
};
18451853

1846-
check_rec(op, new_guard);
1854+
check_rec(op, new_guard, false);
18471855

18481856
constraints.push_back(expr.id() == ID_or ? boolean_negate(op) : op);
18491857
}
@@ -1855,20 +1863,20 @@ void goto_check_ct::check_rec_if(const if_exprt &if_expr, const guardt &guard)
18551863
if_expr.cond().is_boolean(),
18561864
"first argument of if must be boolean, but got " + if_expr.cond().pretty());
18571865

1858-
check_rec(if_expr.cond(), guard);
1866+
check_rec(if_expr.cond(), guard, false);
18591867

18601868
{
18611869
auto new_guard = [&guard, &if_expr](exprt expr) {
18621870
return guard(implication(if_expr.cond(), std::move(expr)));
18631871
};
1864-
check_rec(if_expr.true_case(), new_guard);
1872+
check_rec(if_expr.true_case(), new_guard, false);
18651873
}
18661874

18671875
{
18681876
auto new_guard = [&guard, &if_expr](exprt expr) {
18691877
return guard(implication(not_exprt(if_expr.cond()), std::move(expr)));
18701878
};
1871-
check_rec(if_expr.false_case(), new_guard);
1879+
check_rec(if_expr.false_case(), new_guard, false);
18721880
}
18731881
}
18741882

@@ -1878,7 +1886,7 @@ bool goto_check_ct::check_rec_member(
18781886
{
18791887
const dereference_exprt &deref = to_dereference_expr(member.struct_op());
18801888

1881-
check_rec(deref.pointer(), guard);
1889+
check_rec(deref.pointer(), guard, false);
18821890

18831891
// avoid building the following expressions when pointer_validity_check
18841892
// would return immediately anyway
@@ -1969,7 +1977,10 @@ void goto_check_ct::check_rec_arithmetic_op(
19691977
}
19701978
}
19711979

1972-
void goto_check_ct::check_rec(const exprt &expr, const guardt &guard)
1980+
void goto_check_ct::check_rec(
1981+
const exprt &expr,
1982+
const guardt &guard,
1983+
bool is_assigned)
19731984
{
19741985
if(expr.id() == ID_exists || expr.id() == ID_forall)
19751986
{
@@ -1980,7 +1991,7 @@ void goto_check_ct::check_rec(const exprt &expr, const guardt &guard)
19801991
return guard(forall_exprt(quantifier_expr.symbol(), expr));
19811992
};
19821993

1983-
check_rec(quantifier_expr.where(), new_guard);
1994+
check_rec(quantifier_expr.where(), new_guard, false);
19841995
return;
19851996
}
19861997
else if(expr.id() == ID_address_of)
@@ -2007,10 +2018,10 @@ void goto_check_ct::check_rec(const exprt &expr, const guardt &guard)
20072018
}
20082019

20092020
for(const auto &op : expr.operands())
2010-
check_rec(op, guard);
2021+
check_rec(op, guard, false);
20112022

20122023
if(expr.type().id() == ID_c_enum_tag)
2013-
enum_range_check(expr, guard);
2024+
enum_range_check(expr, guard, is_assigned);
20142025

20152026
if(expr.id() == ID_index)
20162027
{
@@ -2059,9 +2070,9 @@ void goto_check_ct::check_rec(const exprt &expr, const guardt &guard)
20592070
}
20602071
}
20612072

2062-
void goto_check_ct::check(const exprt &expr)
2073+
void goto_check_ct::check(const exprt &expr, bool is_assigned)
20632074
{
2064-
check_rec(expr, identity);
2075+
check_rec(expr, identity, is_assigned);
20652076
}
20662077

20672078
void goto_check_ct::memory_leak_check(const irep_idt &function_id)
@@ -2151,7 +2162,7 @@ void goto_check_ct::goto_check(
21512162

21522163
if(i.has_condition())
21532164
{
2154-
check(i.condition());
2165+
check(i.condition(), false);
21552166
}
21562167

21572168
// magic ERROR label?
@@ -2184,45 +2195,32 @@ void goto_check_ct::goto_check(
21842195

21852196
if(statement == ID_expression)
21862197
{
2187-
check(code);
2198+
check(code, false);
21882199
}
21892200
else if(statement == ID_printf)
21902201
{
21912202
for(const auto &op : code.operands())
2192-
check(op);
2203+
check(op, false);
21932204
}
21942205
}
21952206
else if(i.is_assign())
21962207
{
21972208
const exprt &assign_lhs = i.assign_lhs();
21982209
const exprt &assign_rhs = i.assign_rhs();
21992210

2200-
// Disable enum range checks for left-hand sides as their values are yet
2201-
// to be set (by this assignment).
2202-
{
2203-
flag_overridet resetter(i.source_location());
2204-
resetter.disable_flag(enable_enum_range_check, "enum_range_check");
2205-
check(assign_lhs);
2206-
}
2207-
2208-
check(assign_rhs);
2211+
check(assign_lhs, true);
2212+
check(assign_rhs, false);
22092213

22102214
// the LHS might invalidate any assertion
22112215
invalidate(assign_lhs);
22122216
}
22132217
else if(i.is_function_call())
22142218
{
2215-
// Disable enum range checks for left-hand sides as their values are yet
2216-
// to be set (by this function call).
2217-
{
2218-
flag_overridet resetter(i.source_location());
2219-
resetter.disable_flag(enable_enum_range_check, "enum_range_check");
2220-
check(i.call_lhs());
2221-
}
2222-
check(i.call_function());
2219+
check(i.call_lhs(), true);
2220+
check(i.call_function(), false);
22232221

22242222
for(const auto &arg : i.call_arguments())
2225-
check(arg);
2223+
check(arg, false);
22262224

22272225
check_shadow_memory_api_calls(i);
22282226

@@ -2231,7 +2229,7 @@ void goto_check_ct::goto_check(
22312229
}
22322230
else if(i.is_set_return_value())
22332231
{
2234-
check(i.return_value());
2232+
check(i.return_value(), false);
22352233
// the return value invalidate any assertion
22362234
invalidate(i.return_value());
22372235
}
@@ -2342,7 +2340,7 @@ void goto_check_ct::check_shadow_memory_api_calls(
23422340
{
23432341
const exprt &expr = i.call_arguments()[0];
23442342
PRECONDITION(expr.type().id() == ID_pointer);
2345-
check(dereference_exprt(expr));
2343+
check(dereference_exprt(expr), false);
23462344
}
23472345
}
23482346

0 commit comments

Comments
 (0)