Proofs for code that relies on unsigned integer overflow? - frama-c

How should I approach proving the correctness of code like the following, which, to avoid some inefficiency, relies on modular arithmetic?
#include <stdint.h>
uint32_t my_add(uint32_t a, uint32_t b) {
uint32_t r = a + b;
if (r < a)
return UINT32_MAX;
return r;
}
I've experimented with WP's "int" model, but, if I understand correctly, that model configures the semantics of logical integers in POs, not the formal models of C code. For example, the WP and RTE plugins still require and inject overflow assertion POs for the unsigned addition above when using the "int" model.
In cases like this, can I add annotations stipulating a logical model for a statement or basic block, so I could tell Frama-C how a particular compiler actually interprets a statement? If so, I could use other verification techniques for things like defined-but-often-defect-inducing behaviors like unsigned wrap-around, compiler-defined behaviors, nonstandard behaviors (inline assy?), etc., and then prove correctness for the surrounding code. I'm picturing something similar to (but more powerful than) the "assert fix" used to inform some static analyzers that certain properties hold when they can't derive the properties for themselves.
I'm working with Frama-C Fluorine-20130601, for reference, with alt-ergo 95.1.

I'm working with Frama-C Fluorine-20130601
Glad to see that you found a way to use the latest version.
Here are some random bits of information that, although they do not completely answer your question, do not fit in a StackOverflow comment:
Jessie has:
#pragma JessieIntegerModel(modulo)
The above pragma makes it consider that all overflows (both the undefined signed ones and the defined unsigned ones) wrap around (in the same of signed overflows, in 2's complement arithmetic). The generated proof obligations are much harder, because they contain additional modulo operations everywhere. Of automated theorem provers, typically only Simplify is able to do something with them.
In Fluorine, RTE does not warn about a + b by default:
$ frama-c -rte t.c -then -print
[kernel] preprocessing with "gcc -C -E -I. t.c"
[rte] annotating function my_add
/* Generated by Frama-C */
typedef unsigned int uint32_t;
uint32_t my_add(uint32_t a, uint32_t b)
{
uint32_t __retres;
uint32_t r;
r = a + b;
if (r < a) {
__retres = 4294967295U;
goto return_label;
}
__retres = r;
return_label: return __retres;
}
RTE can be made to warn about the unsigned addition with option -warn-unsigned-overflow:
$ frama-c -warn-unsigned-overflow -rte t.c -then -print
[kernel] preprocessing with "gcc -C -E -I. t.c"
[rte] annotating function my_add
/* Generated by Frama-C */
typedef unsigned int uint32_t;
uint32_t my_add(uint32_t a, uint32_t b)
{
uint32_t __retres;
uint32_t r;
/*# assert rte: unsigned_overflow: 0 ≤ a+b; */
/*# assert rte: unsigned_overflow: a+b ≤ 4294967295; */
r = a + b;
…
But that's precisely the opposite of what you want so I don't see why you would do that.

You didn't provide the exact command line that you have been using. I guess this is frama-c -wp -wp-rte file.c -pp-annot. In that case, indeed, all assertions that RTE can possibly emit are generated. You can however have a finer control over that, by instructing frama-c to first generate only the categories of RTE that you're interested in (be careful that they are controlled by two kinds of options: the ones of frama-c -rte-help and the -warn-{signed,unsigned}-{overflow,downcast} defined in the kernel), and then launch wp on the result. This is done by frama-c -rte -pp-annot file.c -then -wp By default, rte does not consider unsigned overflow to be an error, so that with the above command line, I'm able to prove that your function respects the following specification:
/*#
behavior no_overflow:
assumes a + b <= UINT32_MAX;
ensures \result == a+b;
behavior saturate:
assumes a+b > UINT32_MAX;
ensures \result == UINT32_MAX;
*/
uint32_t my_add(uint32_t a,uint32_t b);

Related

Verifying no unsigned integer wrap-around

Frama-c appears to allow unsigned integer math to wrap-around while it assumes that signed integer math won't overflow, and this is required to later be proven with the -wp-rte flag. (I am personally using Frama-C 20.0 Calcium.) I would like to somehow create an assurance/requirement that some calculation/property doesn't overflow. A simplified version of the issue I am trying to handle is:
#include <stdint.h>
struct example_struct {
unsigned int a;
unsigned int b;
};
/*#
predicate valid_example_struct_one{L}(struct example_struct ex_struct) =
ex_struct.a * ex_struct.b <= UINT_MAX;
*/
Obviously, the above predicate is always true due to wrap-around on unsigned integer math. I would like to be able to cast a, and b to be integer type that won't overflow, or somehow specify it can't overflow using another method. The following seems to somewhat work:
/*#
predicate valid_example_struct_two{L}(struct example_struct ex_struct) =
1 <= UINT_MAX / ex_struct.a / ex_struct.b;
*/
However, I'm not sure the above is really equivalent as it struggles to prove (notice the swapped a, and b):
1 <= UINT_MAX / ex_struct.b / ex_struct.a;
if I ask it to with the input being told up hold up to the predicate valid_example_struct_two. Does anyone have suggestions for saying that a * b is less than UINT_MAX (without doing wrap-around)?
Your predicate
/*#
predicate valid_example_struct_one{L}(struct example_struct ex_struct) =
ex_struct.a * ex_struct.b <= UINT_MAX;
*/
is not "always true due to wrap-around on unsigned integer math". As mentioned in the ACSL manual, all arithmetic operations in ACSL are done in the integer (or real) type, i.e. without wrap-around. It is thus the canonical way to express the absence of arithmetic overflow, and the one that is used by RTE and Eva when emitting related alarms.
That said, RTE is perfectly capable to emit assertion for unsigned overflow, but this has to be activated explicitly with the kernel option -warn-unsigned-overflow (see Frama-C user manual, section 6.3. The reason this option is not activated by default is that, contrarily to e.g. signed overflows, unsigned overflows have a perfectly defined semantics in C.

Frama-c : Trouble understanding WP memory models

I'm looking for WP options/model that could allow me to prove basic C memory manipulations like :
memcpy : I've tried to prove this simple code :
struct header_src{
char t1;
char t2;
char t3;
char t4;
};
struct header_dest{
short t1;
short t2;
};
/*# requires 0<=n<=UINT_MAX;
# requires \valid(dest);
# requires \valid_read(src);
# assigns (dest)[0..n-1] \from (src)[0..n-1];
# assigns \result \from dest;
# ensures dest[0..n] == src[0..n];
# ensures \result == dest;
*/
void* Frama_C_memcpy(char *dest, const char *src, uint32_t n);
int main(void)
{
struct header_src p_header_src;
struct header_dest p_header_dest;
p_header_src.t1 = 'e';
p_header_src.t2 = 'b';
p_header_src.t3 = 'c';
p_header_src.t4 = 'd';
p_header_dest.t1 = 0x0000;
p_header_dest.t2 = 0x0000;
//# assert \valid(&p_header_dest);
Frama_C_memcpy((char*)&p_header_dest, (char*)&p_header_src, sizeof(struct header_src));
//# assert p_header_dest.t1 == 0x6265;
//# assert p_header_dest.t2 == 0x6463;
}
but the two last assert weren't verified by WP (with default prover Alt-Ergo). It can be proved thanks to Value analysis, but I mostly want to be able to prove the code not using abstract interpretation.
Cast pointer to int : Since I'm programming embedded code, I want to be able to specify something like:
#define MEMORY_ADDR 0x08000000
#define SOME_SIZE 10
struct some_struct {
uint8_t field1[SOME_SIZE];
uint32_t field2[SOME_SIZE];
}
// [...]
// some function body {
struct some_struct *p = (some_struct*)MEMORY_ADDR;
if(p == NULL) {
// Handle error
} else {
// Do something
}
// } body end
I've looked a little bit at WP's documentation and it seems that the version of frama-c that I use (Magnesium-20151002) has several memory model (Hoare, Typed , +cast, +ref, ...) but none of the given example were proved with any of the model above. It is explicitly said in the documentation that Typed model does not handle pointer-to-int casts. I've a lot of trouble to understand what's really going on under the hood with each wp-model. It would really help me if I was able to verify at least post-conditions of the memcpy function. Plus, I have seen this issue about void pointer that apparently are not very well handled by WP at least in the Magnesium version. I didn't tried another version of frama-c yet, but I think that newer version handle void pointer in a better way.
Thank you very much in advance for your suggestions !
memcpy
Reasoning about the result of memcpy (or Frama_C_memcpy) is out of range of the current WP plugin. The only memory model that would work in your case is Bytes (page 13 of the manual for Chlorine), but it is not implemented.
Independently, please note that your postcondition from Frama_C_memcpy is not what you want here. You are asserting the equality of the sets dest[0..n] and src[0..n]. First, you should stop at n-1. Second, and more importantly, this is far too weak, and is in fact not sufficient to prove the two assertions in the caller. What you want is a quantification on all bytes. See e.g. the predicate memcmp in Frama-C's stdlib, or the variant \forall int i; 0 <= i < n -> dest[i] == src[i];
By the way, this postcondition holds only if dest and src are properly separated, which your function does not require. Otherwise, you should write dest[i] == \at (src[i], Pre). And your requires are also too weak for another reason, as you only require the first character to be valid, not the n first ones.
Cast pointer to int
Basically, all current models implemented in WP are unable to reason on codes in which the memory is accessed with multiple incompatible types (through the use of unions or pointer casts). In some cases, such as Typed, the cast is detected syntactically, and a warning is issued to warn that the code cannot be analyzed. The Typed+Cast model is a variant of Typed in which some casts are accepted. The analysis is correct only if the pointer is re-cast into its original type before being used. The idea is to allow using some libc functions that require a cast to void*, but not much more.
Your example is again a bit different, because it is likely that MEMORY_ADDR is always addressed with type some_stuct. Would it be acceptable to change the code slightly, and change your function as taking a pointer to this type? This way, you would "hide" the cast to MEMORY_ADDR inside a function that would remain unproven.
I tried this example in the latest version of Frama-C (of course the format is modified a little bit).
for the memcpy case
Assertion 2 fails but assertion 3 is successfully proved (basically because the failure of assertion 2 leads to a False assumption, which proves everything).
So in fact both assertion cannot be proved, same as your problem.
This conclusion is sound because the memory models used in the wp plugin (as far as I know) has no assumption on the relation between fields in a struct, i.e. in header_src the first two fields are 8 bit chars, but they may not be nestedly organized in the physical memory like char[2]. Instead, there may be paddings between them (refer to wiki for detailed description). So when you try to copy bits in such a struct to another struct, Frama-C becomes completely confused and has no idea what you are doing.
As far as I am concerned, Frama-C does not support any approach to precisely control the memory layout, e.g. gcc's PACKED which forces the compiler to remove paddings.
I am facing the same problem, and the (not elegant at all) solution is, use arrays instead. Arrays are always nested, so if you try to copy a char[4] to a short[2], I think the assertion can be proved.
for the Cast pointer to int case
With memory model Typed+cast, the current version I am using (Chlorine-20180501) supports casting between pointers and uint64_t. You may want to try this version.
Moreover, it is strongly suggested to call Z3 and CVC4 through why3, whose performance is certainly better than Alt-Ergo.

Frama-C generates confusing assertions about pointer comparison

I'm getting assertions that don't make sense to me.
Code:
struct s {
int pred;
};
/*# assigns \result \from \nothing;
ensures \valid(\result);
*/
struct s *get(void);
int main(void)
{
return !get()->pred;
}
Frama-C output:
$ frama-c -val frama-ptr.c
[...]
frama-ptr.c:12:[kernel] warning: pointer comparison.
assert \pointer_comparable((void *)0, (void *)tmp->pred);
(tmp from get())
Am I doing something wrong or is it a bug in Frama-C?
This is not really a bug, although this behavior is not really satisfactory either. I recommend that you observe the analysis in the GUI (frama-c-gui -val frama-ptr.c), in particular the value of tmp->pred at line 12 in the Values tab.
Value before:
∈
{{ garbled mix of &{alloced_return_get}
(origin: Library function {c/ptrcmp.c:12}) }}
This is a very imprecise value, that has been generated because the return value of function get is a pointer. The Eva plugin generates a dummy variable (alloced_return_get), and fills it with dummy contents (garbled mix of &{alloced_return_get}). Even though the field pred is an integer, the analyzer assumes that (imprecise) pointers can also be present. This is why an alarm for pointer comparison is emitted.
There are at least two ways to avoid this:
use option -val-warn-undefined-pointer-comparison pointer, so that pointer comparison alarms are emitted only on comparisons involving lvalues with pointer type. The contents of the field pred will remain imprecise, though.
add a proper body to function get, possibly written using malloc, so that the field pred receives a more accurate value.
On a more general note, the Eva/Value plugin requires precise specifications for functions without a body; see section 7.2 of the manual. For functions that return pointers, you won't be able to write satisfactory specifications: you need to write allocates clauses, and those are currently not handled by Eva/Value. Thus, I suggest that you write a body for get.

Is "\NearestEven" available in frama-c Aluminium-20160501?

The ACSL implementation (Version 1.11 Implementation in Aluminium-20160501) lists \NearestEven as a rounding mode (page 23). However, it doesn't appear to be still available at runtime. When I ran the following code:
/*# requires 0x1p-967 <= C <= 0x1p970;
# ensures \result == \round_double(\NearestEven, (x+y)/2) ;
# */
double average(double C, double x, double y) {
if (C <= abs(x))
return x/2+y/2;
else
return (x+y)/2;
}
using the following command: frama-c -wp -wp-rte -wp-prover coq avg.c, I get: [wp] user error: Builtin \NearestEven not defined. None of the other rounding modes was available either.
Any suggestions?
The manual you refer to indicates what is supported by Frama-C's kernel. This does not imply that all plugins (or even any plugin) know how to deal with such a construction. In your particular case, WP indeed does not support \NearestEven.
With -wp-model +float, you might be able to work on a goal such as \result == (double)((x+y)/2), which will very probably use nearest even for the rounding involved by the cast to double (but I have to admit that the paragraph on Float arithmetic model in WP's manual is a bit succinct). This will of course not work if you want to use another rounding mode, for which I think only the Jessie plugin, if there is a version compatible with Aluminium somewhere, will be able to do something.
Note that for handling such proofs, you'll need to resort to Gappa and/or Coq. The prover used in WP by default (Alt-Ergo) is unlikely to discharge much proof obligations related to floating-point computations.

How can I perform 64-bit division with a 32-bit divide instruction?

This is (AFAIK) a specific question within this general topic.
Here's the situation:
I have an embedded system (a video game console) based on a 32-bit RISC microcontroller (a variant of NEC's V810). I want to write a fixed-point math library. I read this article, but the accompanying source code is written in 386 assembly, so it's neither directly usable nor easily modifiable.
The V810 has built-in integer multiply/divide, but I want to use the 18.14 format mentioned in the above article. This requires dividing a 64-bit int by a 32-bit int, and the V810 only does (signed or unsigned) 32-bit/32-bit division (which produces a 32-bit quotient and a 32-bit remainder).
So, my question is: how do I simulate a 64-bit/32-bit divide with a 32-bit/32-bit one (to allow for the pre-shifting of the dividend)? Or, to look at the problem from another way, what's the best way to divide an 18.14 fixed-point by another using standard 32-bit arithmetic/logic operations? ("best" meaning fastest, smallest, or both).
Algebra, (V810) assembly, and pseudo-code are all fine. I will be calling the code from C.
Thanks in advance!
EDIT: Somehow I missed this question... However, it will still need some modification to be super-efficient (it has to be faster than the floating-point div provided by the v810, though it may already be...), so feel free to do my work for me in exchange for reputation points ;) (and credit in my library documentation, of course).
GCC has such a routine for many processors, named _divdi3 (usually implemented using a common divmod call). Here's one. Some Unix kernels have an implementation too, e.g. FreeBSD.
If your dividend is unsigned 64 bits, your divisor is unsigned 32 bits, the architecture is i386 (x86), the div assembly instruction can help you with some preparation:
#include <stdint.h>
/* Returns *a % b, and sets *a = *a_old / b; */
uint32_t UInt64DivAndGetMod(uint64_t *a, uint32_t b) {
#ifdef __i386__ /* u64 / u32 division with little i386 machine code. */
uint32_t upper = ((uint32_t*)a)[1], r;
((uint32_t*)a)[1] = 0;
if (upper >= b) {
((uint32_t*)a)[1] = upper / b;
upper %= b;
}
__asm__("divl %2" : "=a" (((uint32_t*)a)[0]), "=d" (r) :
"rm" (b), "0" (((uint32_t*)a)[0]), "1" (upper));
return r;
#else
const uint64_t q = *a / b; /* Calls __udivdi3 in libgcc. */
const uint32_t r = *a - b * q; /* `r = *a % b' would use __umoddi3. */
*a = q;
return r;
#endif
}
If the line above with __udivdi3 doesn't compile for you, use the __div64_32 function from the Linux kernel: https://github.com/torvalds/linux/blob/master/lib/div64.c

Resources