Description
Using CBMC 5.84 on macOS. I want to prove exactly 1 function is correct with respect to its contracts.
My function (See attached isqrt.c) is about 20 lines of code. For that, CBMC produces 1651 lines of output on stdout, almost all of which is useless noise and has no relation to the code I'm trying to verify.
See attaches isqrt_results.txt for the full output. This is with the default verbosity setting.
What are all the proofs of the "builtin_library" functions for? They dominate the output but have nothing to do with my code as far as I can see.
Ideas.
- When ALL N POs for a function yields SUCCESS, then summarize the output of that function into 1 line ("ALL SUCCESS") rather than N lines of output.
- Group outputs so that the results for the function I have requested appear right at the end of the output, so are still visible on screen when then analysis terminates. Group together results for the declaration and definition of my function (i.e. so that results for my_code.h and my_code.c appear next to each other.)
- Supply a verbosity setting that completely suppresses results for all that "builtin_library" stuff.
See attached isqrt_concise.txt file for an example of what this might look like (I created this with an editor just to see what it would look like.)
isqrt_concise.txt
isqrt_results.txt
Code
#include <stdint.h>
#ifdef CBMC
#else
#define __CPROVER_assigns(...)
#define __CPROVER_decreases(...)
#define __CPROVER_assert(...)
#define __CPROVER_requires(...)
#define __CPROVER_ensures(...)
#define __CPROVER_loop_invariant(...)
#endif
// truncated square root of 2**31-1
#define INT32_ROOT_MAX 46340
int32_t isqrt(int32_t x)
__CPROVER_requires (x >= 0)
__CPROVER_ensures (0 <= __CPROVER_return_value &&
__CPROVER_return_value <= INT32_ROOT_MAX &&
(__CPROVER_return_value * __CPROVER_return_value <= x) &&
(((int64_t) __CPROVER_return_value + 1 ) * ((int64_t) __CPROVER_return_value + 1) > (int64_t) x))
{
int32_t upper, lower, middle;
lower = 0;
upper = INT32_ROOT_MAX + 1;
while(lower + 1 != upper)
__CPROVER_assigns(middle, lower, upper)
__CPROVER_loop_invariant(0 <= lower && lower <= INT32_ROOT_MAX)
__CPROVER_loop_invariant(0 <= upper && upper <= (INT32_ROOT_MAX + 1))
__CPROVER_loop_invariant(lower * lower <= x)
// cast to int64_t here to avoid overflow on *
__CPROVER_loop_invariant((int64_t) upper * (int64_t) upper > (int64_t) x)
__CPROVER_decreases(upper - lower)
{
middle = (lower + upper) / 2;
if((middle * middle) > x)
upper = middle;
else
lower = middle;
}
return lower;
}
void isqrt_harness()
{
int32_t x, y;
y = isqrt(x);
}
Makefile
TARGET=isqrt
all: $(TARGET)
CHECKS=--bounds-check --pointer-check \
--memory-cleanup-check --div-by-zero-check --signed-overflow-check \
--unsigned-overflow-check --pointer-overflow-check --conversion-check \
--undefined-shift-check --enum-range-check --pointer-primitive-check
$(TARGET): $(TARGET)_contracts.goto
cbmc $(CHECKS) --external-sat-solver cadical $<
$(TARGET)_contracts.goto: $(TARGET).goto
goto-instrument $(CHECKS) --dfcc $(TARGET)_harness --apply-loop-contracts --enforce-contract $(TARGET) $< $@
$(TARGET).goto: $(TARGET).c
goto-cc --function $(TARGET)_harness -DCBMC -o $@ $<
clean:
rm -f *.goto