diff options
author | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2013-11-04 01:08:21 +0000 |
---|---|---|
committer | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2013-11-04 01:08:21 +0000 |
commit | 2c101190e8fd20eb050f7e99243f874c30f3ea3a (patch) | |
tree | daf0dbbae2dec8fd168d69400c39044367392403 | |
parent | 3566a762d2cc23807a6539940679b6f0edbe637b (diff) |
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
-rw-r--r-- | ChangeLog | 6 | ||||
-rw-r--r-- | eval_intern.h | 27 |
2 files changed, 29 insertions, 4 deletions
@@ -1,3 +1,9 @@ +Mon Nov 4 10:08:17 2013 Nobuyoshi Nakada <nobu@ruby-lang.org> + + * 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 + Sun Nov 3 23:06:51 2013 Tanaka Akira <akr@fsij.org> * sample/test.rb: Make temporary file names unique. 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)) |