aboutsummaryrefslogtreecommitdiff
path: root/gdb/guile/guile-internal.h
diff options
context:
space:
mode:
authorTom Tromey <tromey@adacore.com>2019-04-24 06:50:01 -0600
committerTom Tromey <tromey@adacore.com>2019-04-25 12:59:35 -0600
commit680d7fd5fcff860a31021845389d4dfeb7b42e3c (patch)
tree0065f8d560b3148a3a3dceb5e3e34ab724cc7cba /gdb/guile/guile-internal.h
parentc6fdd8b2052baa9b7a27d4d34f109c9622b53509 (diff)
downloadfsf-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.h38
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);