Skip to content

Commit 1e3712c

Browse files
committed
Shifts of non-integers and left shifts of negative integers are undefined
6.5.7 of C11: "Each of the operands shall have integer type." Paragraph 4: "If E1 has a signed type and nonnegative value, and E1 x 2^E2 is representable in the result type, then that is the resulting value; otherwise, the behavior is undefined."
1 parent 6bb3872 commit 1e3712c

File tree

3 files changed

+44
-0
lines changed

3 files changed

+44
-0
lines changed
+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
int main()
2+
{
3+
unsigned char x;
4+
unsigned r=x << ((sizeof(unsigned)-1)*8);
5+
r=x << ((sizeof(unsigned)-1)*8-1);
6+
r=(unsigned)x << ((sizeof(unsigned)-1)*8);
7+
8+
int s=-1 << ((sizeof(int)-1)*8);
9+
s=-256 << ((sizeof(int)-1)*8);
10+
return 0;
11+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
CORE
2+
main.c
3+
--undefined-shift-check
4+
^SIGNAL=0$
5+
^\[.*\] shift operand is negative in .*: FAILURE$
6+
^\*\* 1 of 2 failed
7+
^VERIFICATION FAILED$
8+
--
9+
^warning: ignoring

src/analyses/goto_check.cpp

+24
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,30 @@ void goto_checkt::undefined_shift_check(
286286
expr.find_source_location(),
287287
expr,
288288
guard);
289+
290+
if(op_type.id()==ID_signedbv && expr.id()==ID_shl)
291+
{
292+
binary_relation_exprt inequality(
293+
expr.op(), ID_ge, from_integer(0, op_type));
294+
295+
add_guarded_claim(
296+
inequality,
297+
"shift operand is negative",
298+
"undefined-shift",
299+
expr.find_source_location(),
300+
expr,
301+
guard);
302+
}
303+
}
304+
else
305+
{
306+
add_guarded_claim(
307+
false_exprt(),
308+
"shift of non-integer type",
309+
"undefined-shift",
310+
expr.find_source_location(),
311+
expr,
312+
guard);
289313
}
290314
}
291315

0 commit comments

Comments
 (0)