diff options
author | Tom Tromey <tromey@adacore.com> | 2019-04-24 06:50:01 -0600 |
---|---|---|
committer | Tom Tromey <tromey@adacore.com> | 2019-04-25 12:59:35 -0600 |
commit | 680d7fd5fcff860a31021845389d4dfeb7b42e3c (patch) | |
tree | 0065f8d560b3148a3a3dceb5e3e34ab724cc7cba /gdb/guile/guile-internal.h | |
parent | c6fdd8b2052baa9b7a27d4d34f109c9622b53509 (diff) | |
download | fsf-binutils-gdb-680d7fd5fcff860a31021845389d4dfeb7b42e3c.zip fsf-binutils-gdb-680d7fd5fcff860a31021845389d4dfeb7b42e3c.tar.gz fsf-binutils-gdb-680d7fd5fcff860a31021845389d4dfeb7b42e3c.tar.bz2 |
Avoid undefined behavior in Guile exception handling
The Guile code will longjmp (via scm_throw) when an object requiring
destruction is on the stack. This is undefined behavior.
This changes this code to run any destructors in inner scopes, and to
pass a POD to gdbscm_throw_gdb_exception.
gdb/ChangeLog
2019-04-25 Tom Tromey <tromey@adacore.com>
* guile/scm-exception.c (gdbscm_scm_from_gdb_exception)
(gdbscm_throw_gdb_exception): Take a gdbscm_gdb_exception.
* guile/scm-block.c, guile/scm-breakpoint.c, guile/scm-cmd.c,
guile/scm-disasm.c, guile/scm-frame.c, guile/scm-lazy-string.c,
guile/scm-math.c, guile/scm-param.c, guile/scm-ports.c,
guile/scm-symbol.c, guile/scm-symtab.c, guile/scm-type.c,
guile/scm-value.c: Use unpack.
* guile/guile-internal.h (gdbscm_scm_from_gdb_exception): Take a
gdbscm_gdb_exception.
(gdbscm_throw_gdb_exception): Likewise.
(struct gdbscm_gdb_exception): New.
(unpack): New function.
(gdbscm_wrap): Use unpack.
Diffstat (limited to 'gdb/guile/guile-internal.h')
-rw-r--r-- | gdb/guile/guile-internal.h | 38 |
1 files changed, 35 insertions, 3 deletions
diff --git a/gdb/guile/guile-internal.h b/gdb/guile/guile-internal.h index a3e02ab..8ea8706 100644 --- a/gdb/guile/guile-internal.h +++ b/gdb/guile/guile-internal.h @@ -353,9 +353,11 @@ extern void gdbscm_misc_error (const char *subr, int arg_pos, extern void gdbscm_throw (SCM exception) ATTRIBUTE_NORETURN; -extern SCM gdbscm_scm_from_gdb_exception (struct gdb_exception exception); +struct gdbscm_gdb_exception; +extern SCM gdbscm_scm_from_gdb_exception + (const gdbscm_gdb_exception &exception); -extern void gdbscm_throw_gdb_exception (struct gdb_exception exception) +extern void gdbscm_throw_gdb_exception (gdbscm_gdb_exception exception) ATTRIBUTE_NORETURN; extern void gdbscm_print_exception_with_stack (SCM port, SCM stack, @@ -650,6 +652,33 @@ extern void gdbscm_initialize_values (void); with a TRY/CATCH, because the dtors won't otherwise be run when a Guile exceptions is thrown. */ +/* This is a destructor-less clone of gdb_exception. */ + +struct gdbscm_gdb_exception +{ + enum return_reason reason; + enum errors error; + /* The message is xmalloc'd. */ + char *message; +}; + +/* Return a gdbscm_gdb_exception representing EXC. */ + +inline gdbscm_gdb_exception +unpack (const gdb_exception &exc) +{ + gdbscm_gdb_exception result; + result.reason = exc.reason; + result.error = exc.error; + if (exc.message == nullptr) + result.message = nullptr; + else + result.message = xstrdup (exc.message->c_str ()); + /* The message should be NULL iff the reason is zero. */ + gdb_assert ((result.reason == 0) == (result.message == nullptr)); + return result; +} + /* Use this after a TRY/CATCH to throw the appropriate Scheme exception if a GDB error occurred. */ @@ -676,6 +705,7 @@ SCM gdbscm_wrap (Function &&func, Args &&... args) { SCM result = SCM_BOOL_F; + gdbscm_gdb_exception exc {}; try { @@ -683,9 +713,11 @@ gdbscm_wrap (Function &&func, Args &&... args) } catch (const gdb_exception &except) { - GDBSCM_HANDLE_GDB_EXCEPTION (except); + exc = unpack (except); } + GDBSCM_HANDLE_GDB_EXCEPTION (exc); + if (gdbscm_is_exception (result)) gdbscm_throw (result); |