diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/setjmp/___setjmp.x86-64.s (renamed from src/setjmp/__setjmp.x86-64.s) | 0 | ||||
-rw-r--r-- | src/setjmp/__setjmp.c | 41 | ||||
-rw-r--r-- | src/setjmp/__setjmp_h.c | 3 | ||||
-rw-r--r-- | src/setjmp/_setjmp.h | 58 | ||||
-rw-r--r-- | src/setjmp/longjmp.c | 2 | ||||
-rw-r--r-- | src/setjmp/setjmp.c | 35 |
6 files changed, 111 insertions, 28 deletions
diff --git a/src/setjmp/__setjmp.x86-64.s b/src/setjmp/___setjmp.x86-64.s index 00b139b1..00b139b1 100644 --- a/src/setjmp/__setjmp.x86-64.s +++ b/src/setjmp/___setjmp.x86-64.s diff --git a/src/setjmp/__setjmp.c b/src/setjmp/__setjmp.c new file mode 100644 index 00000000..cbd6a144 --- /dev/null +++ b/src/setjmp/__setjmp.c @@ -0,0 +1,41 @@ +#include <setjmp.h> +#include <string.h> +#include "_setjmp.h" +#include "_safety.h" + +/** save program state **/ + +int __setjmp(jmp_buf env) +{ + int ret = 0; + extern int ___setjmp(jmp_buf); + SIGNAL_SAFE(0); + memset(env, 0, sizeof(jmp_buf)); + ret = ___setjmp(env); + ADD_JMP_BUF(env); + return ret; +} + +CHECK_1(int, 0, __setjmp, jmp_buf) + +/*** +saves the current state of the calling environment +in the TYPEDEF(jmp_buf) ARGUMENT(env). +***/ + +/* +RETURN(0, the environment has been saved by THIS()) +RETURN(NONZERO, the environment has been restored by FUNCTION(longjmp)) + +CONSTRAINT: entire controlling expression of a selection or iteration statement +CONSTRAINT: one operand of a relational or equality operator which is the entire controlling expression of a selction or iteration statement +CONSTRAINT: the operand of a unary ! as the entire controlling expression of a selection or iteration statement +CONSTRAINT: an entire expression statement + +UNSPECIFIED(Whether THIS() is a macro or identifier with external linkage) + +UNDEFINED(A macro definition of THIS() is suppressed in order to access an actual function) +UNDEFINED(A program defines an external identifier named LITERAL(setjmp)) + +STDC(1) +*/ diff --git a/src/setjmp/__setjmp_h.c b/src/setjmp/__setjmp_h.c new file mode 100644 index 00000000..b4d0dcd6 --- /dev/null +++ b/src/setjmp/__setjmp_h.c @@ -0,0 +1,3 @@ +#include "_setjmp.h" + +struct __setjmp_h __setjmp_h; diff --git a/src/setjmp/_setjmp.h b/src/setjmp/_setjmp.h new file mode 100644 index 00000000..1bf19fe6 --- /dev/null +++ b/src/setjmp/_setjmp.h @@ -0,0 +1,58 @@ +#ifndef ___SETJMP_H__ +#define ___SETJMP_H__ + +#include <setjmp.h> +#include "_safety.h" + +struct __valid_jmp_buf { +}; + +extern struct __setjmp_h { + struct valid_jmp_buf { + unsigned long int *buf; + unsigned long int sum; + } *valid; + size_t nvalid; +} __setjmp_h; + + +#ifndef NDEBUG +static inline unsigned long int jmp_sum(jmp_buf env) +{ + long unsigned int ret = 0; + for (size_t i = 0; i < sizeof(jmp_buf) / sizeof(unsigned long int); i++) { + ret ^= env[i]; + } + return ret; +} + +#define ADD_JMP_BUF(__env) do { \ + struct valid_jmp_buf __v = { \ + (unsigned long int *)(__env), \ + jmp_sum(__env), \ + }; \ + ADD_PREV(__v, __setjmp_h.valid, __setjmp_h.nvalid); \ +} while (0) + +#define ASSERT_JMP_BUF(__env) do { \ + int __found = 0; \ + for (size_t __i = 0; __i < __setjmp_h.nvalid; __i++) { \ + if (__setjmp_h.valid[__i].buf == (unsigned long int *)(__env)) { \ + if (jmp_sum(__env) != __setjmp_h.valid[__i].sum) { \ + UNDEFINED("jmp_buf has been modified!"); \ + } \ + __found = 1; \ + break; \ + } \ + } \ + if (!__found) { \ + UNDEFINED("In call to longjmp(): Provided jmp_buf was not returned by a previous call to setjmp()"); \ + } \ +} while (0) + +#else +#define ADD_JMP_BUF(__env) (void)(__env) +#define ASSERT_JMP_BUF(__env) (void)(__env) +#endif + +#endif diff --git a/src/setjmp/longjmp.c b/src/setjmp/longjmp.c index 117910fc..2208aec7 100644 --- a/src/setjmp/longjmp.c +++ b/src/setjmp/longjmp.c @@ -1,4 +1,5 @@ #include <setjmp.h> +#include "_setjmp.h" #include "_safety.h" /** restore calling environment **/ @@ -7,6 +8,7 @@ _Noreturn void longjmp(jmp_buf env, int val) { extern _Noreturn void ___longjmp(jmp_buf); SIGNAL_SAFE(0); + ASSERT_JMP_BUF(env); /* use val if nonzero, otherwise 1 */ env[0] = val ? val : 1; diff --git a/src/setjmp/setjmp.c b/src/setjmp/setjmp.c index 091f0993..3c8a199c 100644 --- a/src/setjmp/setjmp.c +++ b/src/setjmp/setjmp.c @@ -1,37 +1,16 @@ #include <setjmp.h> -#include <string.h> #include "_safety.h" -/** save program state **/ +#undef setjmp -int setjmp(jmp_buf env) +int setjmp(jmp_buf jb) { - extern int ___setjmp(jmp_buf); - SIGNAL_SAFE(0); - memset(env, 0, sizeof(jmp_buf)); - return ___setjmp(env); + (void)jb; + UNDEFINED("The setjmp() macro has been suppressed to access an actual function"); + return 0; } -CHECK_1(int, 0, setjmp, jmp_buf) - -/*** -saves the current state of the calling environment -in the TYPEDEF(jmp_buf) ARGUMENT(env). -***/ - /* -RETURN(0, the environment has been saved by THIS()) -RETURN(NONZERO, the environment has been restored by FUNCTION(longjmp)) - -CONSTRAINT: entire controlling expression of a selection or iteration statement -CONSTRAINT: one operand of a relational or equality operator which is the entire controlling expression of a selction or iteration statement -CONSTRAINT: the operand of a unary ! as the entire controlling expression of a selection or iteration statement -CONSTRAINT: an entire expression statement - -UNSPECIFIED(Whether THIS() is a macro or identifier with external linkage) - -UNDEFINED(A macro definition of THIS() is suppressed in order to access an actual function) -UNDEFINED(A program defines an external identifier named LITERAL(setjmp)) - -STDC(1) +SIGNAL_SAFE(0) +STDC(0) */ |