Skip to content

Commit 6e47d5a

Browse files
committed
C library: model currently supported behaviour of longjmp
We require (yet to be built) instrumentation to handle longjmp (and its variants). Therefore: 1) The only possible return value of `setjmp` (and its variants) is 0 for it can never be reached via longjmp (or its variants). 2) Fail an assertion when invoking longjmp to ensure we do not produce unsound verification results when longjmp is reachable on some path. Enable all related regression tests.
1 parent 3552cfb commit 6e47d5a

File tree

11 files changed

+128
-28
lines changed

11 files changed

+128
-28
lines changed
Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
#include <assert.h>
21
#include <setjmp.h>
32

3+
static jmp_buf env;
4+
45
int main()
56
{
6-
_longjmp();
7-
assert(0);
7+
_longjmp(env, 1);
8+
__CPROVER_assert(0, "unreachable");
89
return 0;
910
}
Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1-
KNOWNBUG
1+
CORE
22
main.c
33
--pointer-check --bounds-check
4-
^EXIT=0$
4+
^\[_longjmp.assertion.1\] line 12 _longjmp requires instrumentation: FAILURE$
5+
^\[main.assertion.1\] line 8 unreachable: SUCCESS$
6+
^VERIFICATION FAILED$
7+
^EXIT=10$
58
^SIGNAL=0$
6-
^VERIFICATION SUCCESSFUL$
79
--
810
^warning: ignoring
Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
#include <assert.h>
21
#include <setjmp.h>
32

3+
static jmp_buf env;
4+
45
int main()
56
{
6-
longjmp();
7-
assert(0);
7+
longjmp(env, 1);
8+
__CPROVER_assert(0, "unreachable");
89
return 0;
910
}
Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1-
KNOWNBUG
1+
CORE
22
main.c
33
--pointer-check --bounds-check
4-
^EXIT=0$
4+
^\[longjmp.assertion.1\] line 12 longjmp requires instrumentation: FAILURE$
5+
^\[main.assertion.1\] line 8 unreachable: SUCCESS$
6+
^VERIFICATION FAILED$
7+
^EXIT=10$
58
^SIGNAL=0$
6-
^VERIFICATION SUCCESSFUL$
79
--
810
^warning: ignoring
Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
1-
#include <assert.h>
21
#include <setjmp.h>
32

3+
static jmp_buf env;
4+
45
int main()
56
{
6-
setjmp();
7-
assert(0);
7+
if(setjmp(env))
8+
__CPROVER_assert(0, "reached via longjmp");
9+
else
10+
__CPROVER_assert(0, "setjmp called directly");
811
return 0;
912
}
Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1-
KNOWNBUG
1+
CORE
22
main.c
33
--pointer-check --bounds-check
4-
^EXIT=0$
4+
^\[main.assertion.1\] line 8 reached via longjmp: SUCCESS$
5+
^\[main.assertion.2\] line 10 setjmp called directly: FAILURE$
6+
^VERIFICATION FAILED$
7+
^EXIT=10$
58
^SIGNAL=0$
6-
^VERIFICATION SUCCESSFUL$
79
--
810
^warning: ignoring
Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
#include <assert.h>
21
#include <setjmp.h>
32

3+
static sigjmp_buf env;
4+
45
int main()
56
{
6-
siglongjmp();
7-
assert(0);
7+
siglongjmp(env, 1);
8+
__CPROVER_assert(0, "unreachable");
89
return 0;
910
}
Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1-
KNOWNBUG
1+
CORE unix
22
main.c
33
--pointer-check --bounds-check
4-
^EXIT=0$
4+
^\[siglongjmp.assertion.1\] line 14 siglongjmp requires instrumentation: FAILURE$
5+
^\[main.assertion.1\] line 8 unreachable: SUCCESS$
6+
^VERIFICATION FAILED$
7+
^EXIT=10$
58
^SIGNAL=0$
6-
^VERIFICATION SUCCESSFUL$
79
--
810
^warning: ignoring
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#include <setjmp.h>
2+
3+
static sigjmp_buf env;
4+
5+
int main()
6+
{
7+
if(sigsetjmp(env, 0))
8+
__CPROVER_assert(0, "reached via siglongjmp");
9+
else
10+
__CPROVER_assert(0, "sigsetjmp called directly");
11+
return 0;
12+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
CORE unix
2+
main.c
3+
--pointer-check --bounds-check
4+
^\[main.assertion.1\] line 8 reached via siglongjmp: SUCCESS$
5+
^\[main.assertion.2\] line 10 sigsetjmp called directly: FAILURE$
6+
^VERIFICATION FAILED$
7+
^EXIT=10$
8+
^SIGNAL=0$
9+
--
10+
^warning: ignoring

src/ansi-c/library/setjmp.c

Lines changed: 68 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ inline void longjmp(jmp_buf env, int val)
1111
// does not return
1212
(void)env;
1313
(void)val;
14+
__CPROVER_assert(0, "longjmp requires instrumentation");
1415
__CPROVER_assume(0);
1516
}
1617

@@ -26,11 +27,14 @@ inline void _longjmp(jmp_buf env, int val)
2627
// does not return
2728
(void)env;
2829
(void)val;
30+
__CPROVER_assert(0, "_longjmp requires instrumentation");
2931
__CPROVER_assume(0);
3032
}
3133

3234
/* FUNCTION: siglongjmp */
3335

36+
#ifndef _WIN32
37+
3438
#ifndef __CPROVER_SETJMP_H_INCLUDED
3539
#include <setjmp.h>
3640
#define __CPROVER_SETJMP_H_INCLUDED
@@ -41,22 +45,82 @@ inline void siglongjmp(sigjmp_buf env, int val)
4145
// does not return
4246
(void)env;
4347
(void)val;
48+
__CPROVER_assert(0, "siglongjmp requires instrumentation");
4449
__CPROVER_assume(0);
4550
}
4651

52+
#endif
53+
4754
/* FUNCTION: setjmp */
4855

4956
#ifndef __CPROVER_SETJMP_H_INCLUDED
5057
#include <setjmp.h>
5158
#define __CPROVER_SETJMP_H_INCLUDED
5259
#endif
5360

54-
int __VERIFIER_nondet_int();
61+
#undef setjmp
5562

5663
inline int setjmp(jmp_buf env)
5764
{
58-
// store PC
59-
int retval=__VERIFIER_nondet_int();
6065
(void)env;
61-
return retval;
66+
// returns via longjmp require instrumentation; only such returns would
67+
// return a non-zero value
68+
return 0;
69+
}
70+
71+
/* FUNCTION: _setjmp */
72+
73+
#ifndef __CPROVER_SETJMP_H_INCLUDED
74+
#include <setjmp.h>
75+
#define __CPROVER_SETJMP_H_INCLUDED
76+
#endif
77+
78+
inline int _setjmp(jmp_buf env)
79+
{
80+
(void)env;
81+
// returns via longjmp require instrumentation; only such returns would
82+
// return a non-zero value
83+
return 0;
84+
}
85+
86+
/* FUNCTION: sigsetjmp */
87+
88+
#ifndef _WIN32
89+
90+
#ifndef __CPROVER_SETJMP_H_INCLUDED
91+
# include <setjmp.h>
92+
# define __CPROVER_SETJMP_H_INCLUDED
93+
#endif
94+
95+
#undef sigsetjmp
96+
97+
inline int sigsetjmp(sigjmp_buf env, int savesigs)
98+
{
99+
(void)env;
100+
(void)savesigs;
101+
// returns via siglongjmp require instrumentation; only such returns would
102+
// return a non-zero value
103+
return 0;
104+
}
105+
106+
#endif
107+
108+
/* FUNCTION: __sigsetjmp */
109+
110+
#ifndef _WIN32
111+
112+
#ifndef __CPROVER_SETJMP_H_INCLUDED
113+
# include <setjmp.h>
114+
# define __CPROVER_SETJMP_H_INCLUDED
115+
#endif
116+
117+
inline int __sigsetjmp(sigjmp_buf env, int savesigs)
118+
{
119+
(void)env;
120+
(void)savesigs;
121+
// returns via siglongjmp require instrumentation; only such returns would
122+
// return a non-zero value
123+
return 0;
62124
}
125+
126+
#endif

0 commit comments

Comments
 (0)