From 50f2e553ce21a2901e9f935650018289c11fcc39 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Tue, 11 Sep 2012 16:50:28 -0700 Subject: [PATCH] Avoid _setjmp/_longjmp problems with local nonvolatile variables. If a nonvolatile local variable is written before a _longjmp to the frame containing the variable, and is read after the _longjmp, the value read is indeterminate. Some local variables of type 'struct handler' and 'struct catchtag' are used in this way, so mark each of their slots as volatile if the slot can be set before _longjmp and read afterwards. * lisp.h (struct handler): var and chosen_clause are now volatile. (struct catchtag): val, next, and pdlcount are now volatile. --- src/ChangeLog | 10 ++++++++++ src/lisp.h | 21 ++++++++++++++------- 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/src/ChangeLog b/src/ChangeLog index 74a12b94b08..f4cae50d8ed 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,5 +1,15 @@ 2012-09-11 Paul Eggert + Avoid _setjmp/_longjmp problems with local nonvolatile variables. + If a nonvolatile local variable is written before a _longjmp to + the frame containing the variable, and is read after the _longjmp, + the value read is indeterminate. Some local variables of type + 'struct handler' and 'struct catchtag' are used in this way, so + mark each of their slots as volatile if the slot can be set before + _longjmp and read afterwards. + * lisp.h (struct handler): var and chosen_clause are now volatile. + (struct catchtag): val, next, and pdlcount are now volatile. + * bidi.c (bidi_push_it, bidi_pop_it): * fns.c (copy_hash_table): * image.c (define_image_type): diff --git a/src/lisp.h b/src/lisp.h index ae9b3422534..ca22ca81228 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -2001,7 +2001,10 @@ extern ptrdiff_t specpdl_size; #define SPECPDL_INDEX() (specpdl_ptr - specpdl) -/* Everything needed to describe an active condition case. */ +/* Everything needed to describe an active condition case. + + Members are volatile if their values need to survive _longjmp when + a 'struct handler' is a local variable. */ struct handler { /* The handler clauses and variable from the condition-case form. */ @@ -2012,10 +2015,12 @@ struct handler error: handle all conditions, and errors can run the debugger or display a backtrace. */ Lisp_Object handler; - Lisp_Object var; + + Lisp_Object volatile var; + /* Fsignal stores here the condition-case clause that applies, and Fcondition_case thus knows which clause to run. */ - Lisp_Object chosen_clause; + Lisp_Object volatile chosen_clause; /* Used to effect the longjump out to the handler. */ struct catchtag *tag; @@ -2041,19 +2046,21 @@ struct handler of the catch form. All the other members are concerned with restoring the interpreter - state. */ + state. + Members are volatile if their values need to survive _longjmp when + a 'struct catchtag' is a local variable. */ struct catchtag { Lisp_Object tag; - Lisp_Object val; - struct catchtag *next; + Lisp_Object volatile val; + struct catchtag *volatile next; struct gcpro *gcpro; jmp_buf jmp; struct backtrace *backlist; struct handler *handlerlist; EMACS_INT lisp_eval_depth; - ptrdiff_t pdlcount; + ptrdiff_t volatile pdlcount; int poll_suppress_count; int interrupt_input_blocked; struct byte_stack *byte_stack; -- 2.39.2