From 2c101190e8fd20eb050f7e99243f874c30f3ea3a Mon Sep 17 00:00:00 2001 From: nobu Date: Mon, 4 Nov 2013 01:08:21 +0000 Subject: eval_intern.h: avoid undefined behavior of setjmp * eval_intern.h (TH_EXEC_TAG, TH_JUMP_TAG): get rid of undefined behavior of setjmp() in rhs of assignment expression. [ISO/IEC 9899:1999] 7.13.1.1 git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@43522 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- eval_intern.h | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) (limited to 'eval_intern.h') diff --git a/eval_intern.h b/eval_intern.h index 190ef9195c..b945848a7a 100644 --- a/eval_intern.h +++ b/eval_intern.h @@ -108,14 +108,33 @@ extern int select_large_fdset(int, fd_set *, fd_set *, fd_set *, struct timeval #define PUSH_TAG() TH_PUSH_TAG(GET_THREAD()) #define POP_TAG() TH_POP_TAG() -#define TH_EXEC_TAG() ruby_setjmp(_th->tag->buf) +/* clear th->state, and return the value */ +static inline int +ruby_threadptr_tag_state(rb_thread_t *th) +{ + int state = th->state; + th->state = 0; + return state; +} + +NORETURN(static inline void ruby_threadptr_tag_jump(rb_thread_t *, int)); +static inline void +ruby_threadptr_tag_jump(rb_thread_t *th, int st) +{ + ruby_longjmp(th->tag->buf, (th->state = st)); +} + +/* + setjmp() in assignment expression rhs is undefined behavior + [ISO/IEC 9899:1999] 7.13.1.1 +*/ +#define TH_EXEC_TAG() \ + (ruby_setjmp(_th->tag->buf) ? ruby_threadptr_tag_state(_th) : 0) #define EXEC_TAG() \ TH_EXEC_TAG() -#define TH_JUMP_TAG(th, st) do { \ - ruby_longjmp((th)->tag->buf,(st)); \ -} while (0) +#define TH_JUMP_TAG(th, st) ruby_threadptr_tag_jump(th, st) #define JUMP_TAG(st) TH_JUMP_TAG(GET_THREAD(), (st)) -- cgit v1.2.3