Open
Description
I'm observing that wrapping a function operating on a buffer by another function which merely 'frames' it to operate on a slice of the buffer, leads to very slow proof times.
Here is a simple example, where the sub-function bumps a bound on the sub buffer. This is a minimal version of an example arising in practice when verifying the Number Theoretic Transform (pq-code-package/mlkem-native#371).
// file: frame_harness.c
// instructions
//
// goto-cc frame_slowness.c --function harness -o a.out
// goto-instrument --dfcc harness --replace-call-with-contract bump_A_to_B --enforce-contract bump_slice_A_to_B a.out b.out
// cbmc b.out --bitwuzla
#include <stdint.h>
#define A 12
#define B 42
#define SZ 256
void bump_A_to_B(int8_t *x, int sz)
__CPROVER_requires(__CPROVER_is_fresh(x, 2 * sz))
__CPROVER_requires(__CPROVER_forall {
int idx;
0 <= idx && idx <= 2 * sz - 1 ==> x[idx] <= A
})
__CPROVER_assigns(__CPROVER_object_upto(x, 2 * sz))
__CPROVER_ensures(__CPROVER_forall {
int idx;
0 <= idx && idx <= 2 * sz - 1 ==> x[idx] <= B
});
void bump_slice_A_to_B(int8_t *x, int len, int start, int sz)
__CPROVER_requires(2 <= len && len <= SZ && (len & 1) == 0)
__CPROVER_requires(0 <= start && start < len)
__CPROVER_requires(1 <= sz && sz <= len / 2 && start + 2 * sz <= len)
__CPROVER_requires(__CPROVER_is_fresh(x, len))
__CPROVER_requires(__CPROVER_forall {
int i0;
0 <= i0 && i0 <= start - 1 ==> x[i0] <= B
})
__CPROVER_requires(__CPROVER_forall {
int i1;
start <= i1 && i1 <= len - 1 ==> x[i1] <= A
})
__CPROVER_assigns(__CPROVER_object_upto(x, len))
__CPROVER_ensures(__CPROVER_forall {
int i0;
0 <= i0 && i0 <= start + 2 * sz - 1 ==> x[i0] <= B
})
__CPROVER_ensures(__CPROVER_forall {
int i1;
start + 2 * sz <= i1 && i1 <= len - 1 ==> x[i1] <= A
})
{
bump_A_to_B(x + start, sz);
}
void harness(void) {
int8_t *x;
int len, start, sz;
bump_slice_A_to_B(x, len, start, sz);
}
I was expecting the proof to be almost instantaneous, but for SZ==256
, which is the value I am working with in practice, I have not yet seen it terminate.
The issue is the same between Z3 and Bitwuzla.
CBMC Version 6.3.1