Skip to content

Unexpected timeout using __CPROVER_overflow_mult #6607

Closed
@nchong-at-aws

Description

@nchong-at-aws

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;
}

Metadata

Metadata

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions