Skip to content

Commit 3037204

Browse files
tautschnigDaniel Kroening
authored and
Daniel Kroening
committed
Make overflow expressions available in C/C++ language front-ends
This enables testing for arithmetic overflow without generating an arithmetic overflow.
1 parent 1ff7f38 commit 3037204

File tree

5 files changed

+80
-4
lines changed

5 files changed

+80
-4
lines changed

doc/cprover-manual/api.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,22 @@ float __CPROVER_fabsf(float x);
112112
113113
These functions return the absolute value of the given argument.
114114
115+
#### \_\_CPROVER\_overflow\_minus, \_\_CPROVER\_overflow\_mult, \_\_CPROVER\_overflow\_plus, \_\_CPROVER\_overflow\_shl, \_\_CPROVER\_overflow\_unary\_minus
116+
117+
```C
118+
__CPROVER_bool __CPROVER_overflow_minus();
119+
__CPROVER_bool __CPROVER_overflow_mult();
120+
__CPROVER_bool __CPROVER_overflow_plus();
121+
__CPROVER_bool __CPROVER_overflow_shl();
122+
__CPROVER_bool __CPROVER_overflow_unary_minus();
123+
```
124+
125+
These functions take two (`__CPROVER_overflow_unary_minus` only takes one)
126+
arguments of any numeric type. They return true, if, and only if, the named
127+
operation would overflow when applied to the arguments. For example,
128+
`__CPROVER_overflow_plus(x, y)` returns true if `x + y` would result in an
129+
arithmetic overflow.
130+
115131
#### \_\_CPROVER\_array\_equal, \_\_CPROVER\_array\_copy, \_\_CPROVER\_array\_set
116132

117133
```C

src/ansi-c/c_typecheck_expr.cpp

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2811,6 +2811,46 @@ exprt c_typecheck_baset::do_special_functions(
28112811

28122812
return expr;
28132813
}
2814+
else if(
2815+
identifier == CPROVER_PREFIX "overflow_minus" ||
2816+
identifier == CPROVER_PREFIX "overflow_mult" ||
2817+
identifier == CPROVER_PREFIX "overflow_plus" ||
2818+
identifier == CPROVER_PREFIX "overflow_shl" ||
2819+
identifier == CPROVER_PREFIX "overflow_unary_minus")
2820+
{
2821+
exprt overflow{identifier, typet{}, exprt::operandst{expr.arguments()}};
2822+
overflow.add_source_location() = f_op.source_location();
2823+
2824+
if(identifier == CPROVER_PREFIX "overflow_minus")
2825+
{
2826+
overflow.id(ID_minus);
2827+
typecheck_expr_binary_arithmetic(overflow);
2828+
}
2829+
else if(identifier == CPROVER_PREFIX "overflow_mult")
2830+
{
2831+
overflow.id(ID_mult);
2832+
typecheck_expr_binary_arithmetic(overflow);
2833+
}
2834+
else if(identifier == CPROVER_PREFIX "overflow_plus")
2835+
{
2836+
overflow.id(ID_plus);
2837+
typecheck_expr_binary_arithmetic(overflow);
2838+
}
2839+
else if(identifier == CPROVER_PREFIX "overflow_shl")
2840+
{
2841+
overflow.id(ID_shl);
2842+
typecheck_expr_shifts(to_shift_expr(overflow));
2843+
}
2844+
else if(identifier == CPROVER_PREFIX "overflow_unary_minus")
2845+
{
2846+
overflow.id(ID_unary_minus);
2847+
typecheck_expr_unary_arithmetic(overflow);
2848+
}
2849+
2850+
overflow.id("overflow-" + overflow.id_string());
2851+
overflow.type() = bool_typet{};
2852+
return overflow;
2853+
}
28142854
else
28152855
return nil_exprt();
28162856
}

src/ansi-c/cprover_builtin_headers.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,3 +98,9 @@ void __CPROVER_k_induction_hint(unsigned min, unsigned max,
9898
// format string-related
9999
int __CPROVER_scanf(const char *, ...);
100100

101+
// detect overflow
102+
__CPROVER_bool __CPROVER_overflow_minus();
103+
__CPROVER_bool __CPROVER_overflow_mult();
104+
__CPROVER_bool __CPROVER_overflow_plus();
105+
__CPROVER_bool __CPROVER_overflow_shl();
106+
__CPROVER_bool __CPROVER_overflow_unary_minus();

src/ansi-c/expr2c.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3793,11 +3793,13 @@ std::string expr2ct::convert_with_precedence(
37933793
else if(src.id()==ID_cond)
37943794
return convert_cond(src, precedence);
37953795

3796-
else if(src.id()==ID_overflow_unary_minus ||
3797-
src.id()==ID_overflow_minus ||
3798-
src.id()==ID_overflow_mult ||
3799-
src.id()==ID_overflow_plus)
3796+
else if(
3797+
src.id() == ID_overflow_unary_minus || src.id() == ID_overflow_minus ||
3798+
src.id() == ID_overflow_mult || src.id() == ID_overflow_plus ||
3799+
src.id() == ID_overflow_shl)
3800+
{
38003801
return convert_overflow(src, precedence);
3802+
}
38013803

38023804
else if(src.id()==ID_unknown)
38033805
return "*";

src/ansi-c/library/cprover.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,4 +150,16 @@ __CPROVER_bool __CPROVER_get_may(const void *, const char *);
150150
#define __CPROVER_danger_number_of_vars 1
151151
#define __CPROVER_danger_number_of_consts 1
152152

153+
// detect overflow
154+
// NOLINTNEXTLINE(build/deprecated)
155+
__CPROVER_bool __CPROVER_overflow_minus();
156+
// NOLINTNEXTLINE(build/deprecated)
157+
__CPROVER_bool __CPROVER_overflow_mult();
158+
// NOLINTNEXTLINE(build/deprecated)
159+
__CPROVER_bool __CPROVER_overflow_plus();
160+
// NOLINTNEXTLINE(build/deprecated)
161+
__CPROVER_bool __CPROVER_overflow_shl();
162+
// NOLINTNEXTLINE(build/deprecated)
163+
__CPROVER_bool __CPROVER_overflow_unary_minus();
164+
153165
#endif // CPROVER_ANSI_C_LIBRARY_CPROVER_H

0 commit comments

Comments
 (0)