Closed
Description
CBMC version: 5.48.0
Operating system: Ubuntu 20.04.3
Exact command line resulting in the issue: cbmc main.c
What behaviour did you expect: VERIFICATION SUCCESSFUL
What happened instead: Timeout
The following test approximates the output of the Kani verifier (https://github.com/model-checking/rmc) which uses __CPROVER_overflow_mult
to detect unsigned integer wraparound. This test results in a timeout with CBMC.
Switching the implementation to using a wider integer to detect the wraparound (using -DUSE_LARGER_WIDTH
) results in the test being fast to verify with CBMC.
#include <stdint.h>
#include <stdlib.h>
#include <stdbool.h>
#include <assert.h>
struct rectangle {
uint64_t width;
uint64_t height;
};
bool can_hold(struct rectangle self, struct rectangle other) {
return self.width > other.width && self.height > other.height;
}
bool stretch(struct rectangle self, uint64_t factor, struct rectangle *result) {
#ifdef USE_LARGER_WIDTH
__uint128_t w = (__uint128_t) self.width * (__uint128_t) factor;
if (0xffffffffffffffff < w) {
return false;
}
__uint128_t h = (__uint128_t) self.height * (__uint128_t) factor;
if (0xffffffffffffffff < h) {
return false;
}
#else // simulate kani output
if (__CPROVER_overflow_mult(self.width, factor)) {
return false;
}
if (__CPROVER_overflow_mult(self.height, factor)) {
return false;
}
uint64_t w = self.width * factor;
uint64_t h = self.height * factor;
#endif
result->width = w;
result->height = h;
return true;
}
uint64_t nondet_uint64_t();
int main() {
struct rectangle original = { nondet_uint64_t(), nondet_uint64_t() };
uint64_t factor = nondet_uint64_t();
__CPROVER_assume(0 != original.width);
__CPROVER_assume(0 != original.height);
__CPROVER_assume(1 < factor);
struct rectangle result = { nondet_uint64_t(), nondet_uint64_t() };
if (stretch(original, factor, &result)) {
assert(can_hold(result, original));
}
return 0;
}