diff options
author | Jari Aalto <jari.aalto@cante.net> | 1997-06-05 14:59:13 +0000 |
---|---|---|
committer | Jari Aalto <jari.aalto@cante.net> | 2009-09-12 16:46:50 +0000 |
commit | d166f048818e10cf3799aa24a174fb22835f1acc (patch) | |
tree | 1ca27f9243900f8b236d0cde6a3862002aea9e19 /unwind_prot.c | |
parent | ccc6cda312fea9f0468ee65b8f368e9653e1380b (diff) | |
download | bash-d166f048818e10cf3799aa24a174fb22835f1acc.tar.gz |
Imported from ../bash-2.01.tar.gz.
Diffstat (limited to 'unwind_prot.c')
-rw-r--r-- | unwind_prot.c | 62 |
1 files changed, 47 insertions, 15 deletions
diff --git a/unwind_prot.c b/unwind_prot.c index dac5e044..17144dc7 100644 --- a/unwind_prot.c +++ b/unwind_prot.c @@ -27,6 +27,8 @@ Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "config.h" #include "bashtypes.h" +#include "bashansi.h" + #if defined (HAVE_UNISTD_H) # include <unistd.h> #endif @@ -44,10 +46,21 @@ typedef struct _uwp { char *arg; } UNWIND_ELT; -static void - unwind_frame_discard_internal (), unwind_frame_run_internal (), - add_unwind_protect_internal (), remove_unwind_protect_internal (), - run_unwind_protects_internal (), without_interrupts (); +/* Structure describing a saved variable and the value to restore it to. + If a cleanup function is set to restore_variable, the `arg' pointer + points to this. */ +typedef struct { + int *variable; + char *desired_setting; + int size; +} SAVED_VAR; + +static void unwind_frame_discard_internal (), unwind_frame_run_internal (); +static void add_unwind_protect_internal (), remove_unwind_protect_internal (); +static void run_unwind_protects_internal (), without_interrupts (); + +static void restore_variable (); +static void discard_saved_var (); static UNWIND_ELT *unwind_protect_list = (UNWIND_ELT *)NULL; @@ -147,11 +160,14 @@ add_unwind_protect_internal (cleanup, arg) static void remove_unwind_protect_internal () { - UNWIND_ELT *elt = unwind_protect_list; + UNWIND_ELT *elt; + elt = unwind_protect_list; if (elt) { unwind_protect_list = unwind_protect_list->next; + if (elt->cleanup && elt->cleanup == (Function *)restore_variable) + discard_saved_var ((SAVED_VAR *)elt->arg); free (elt); } } @@ -164,7 +180,7 @@ run_unwind_protects_internal () while (elt) { /* This function can be run at strange times, like when unwinding - the entire world of unwind protects. Thus, we may come across + the entire world of unwind protects. Thus, we may come across an element which is simply a label for a catch frame. Don't call the non-existant function. */ if (elt->cleanup) @@ -186,11 +202,16 @@ unwind_frame_discard_internal (tag) while (elt = unwind_protect_list) { unwind_protect_list = unwind_protect_list->next; - if (!elt->cleanup && (STREQ (elt->arg, tag))) + if (elt->cleanup == 0 && (STREQ (elt->arg, tag))) { free (elt); break; } + else if (elt->cleanup && elt->cleanup == (Function *)restore_variable) + { + discard_saved_var ((SAVED_VAR *)elt->arg); + free (elt); + } else free (elt); } @@ -225,12 +246,14 @@ unwind_frame_run_internal (tag) } } -/* Structure describing a saved variable and the value to restore it to. */ -typedef struct { - int *variable; - char *desired_setting; - int size; -} SAVED_VAR; +static void +discard_saved_var (sv) + SAVED_VAR *sv; +{ + if (sv->size != sizeof (int)) + free (sv->desired_setting); + free (sv); +} /* Restore the value of a variable, based on the contents of SV. If sv->size is greater than sizeof (int), sv->desired_setting points to @@ -242,7 +265,7 @@ restore_variable (sv) { if (sv->size != sizeof (int)) { - bcopy ((char *)sv->desired_setting, (char *)sv->variable, sv->size); + FASTCOPY ((char *)sv->desired_setting, (char *)sv->variable, sv->size); free (sv->desired_setting); } else @@ -267,8 +290,17 @@ unwind_protect_var (var, value, size) s->variable = var; if (size != sizeof (int)) { + /* There is a problem here when VALUE is 0. This tries to copy the + first SIZE bytes starting at memory location 0 into + s->desired_setting. There is no guarantee that these bytes are + 0, or make a valid null pointer. We can try to bzero the space, + or just save it as 0 (or (void *)0). If we do the latter, make + sure restore_variable is changed to understand it. */ s->desired_setting = (char *)xmalloc (size); - bcopy (value, (char *)s->desired_setting, size); + if (value == 0) + bzero ((char *)s->desired_setting, size); + else + FASTCOPY (value, (char *)s->desired_setting, size); } else s->desired_setting = value; |