diff options
author | Mark Wielaard <mjw@redhat.com> | 2016-02-13 19:44:59 +0100 |
---|---|---|
committer | Mark Wielaard <mjw@redhat.com> | 2016-02-22 12:12:45 +0100 |
commit | 107ad57b031e9f57f25403dfcf9fa7151deda73c (patch) | |
tree | b122e306aa972e277f5775f0c315427ac1c23dc6 | |
parent | e93e6f9279c34820bed6af17e6df51e1dcb6a8e0 (diff) | |
download | elfutils-107ad57b031e9f57f25403dfcf9fa7151deda73c.tar.gz |
libdwfl: Don't crash on out of memory when frame unwinding.
new_unwound didn't check whether malloc was successful. Check that we
could allocate memory before use and return DWFL_E_NOMEM otherwise.
Signed-off-by: Mark Wielaard <mjw@redhat.com>
-rw-r--r-- | libdwfl/ChangeLog | 6 | ||||
-rw-r--r-- | libdwfl/frame_unwind.c | 23 |
2 files changed, 24 insertions, 5 deletions
diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog index cc8eec7d..903c0cc7 100644 --- a/libdwfl/ChangeLog +++ b/libdwfl/ChangeLog @@ -1,3 +1,9 @@ +2016-02-13 Mark Wielaard <mjw@redhat.com> + + * frame_unwind.c (new_unwound): Check and return unwound. + (handle_cfi): Check new_unwound was able to allocate new memory + before use. Return DWFL_E_NOMEM otherwise. + 2016-02-11 Mark Wielaard <mjw@redhat.com> * relocate.c (relocate_section): Check result of all gelf_get* calls. diff --git a/libdwfl/frame_unwind.c b/libdwfl/frame_unwind.c index 0e470b97..a885446f 100644 --- a/libdwfl/frame_unwind.c +++ b/libdwfl/frame_unwind.c @@ -1,5 +1,5 @@ /* Get previous frame state for an existing frame state. - Copyright (C) 2013, 2014 Red Hat, Inc. + Copyright (C) 2013, 2014, 2016 Red Hat, Inc. This file is part of elfutils. This file is free software; you can redistribute it and/or modify @@ -511,7 +511,7 @@ expr_eval (Dwfl_Frame *state, Dwarf_Frame *frame, const Dwarf_Op *ops, #undef pop } -static void +static Dwfl_Frame * new_unwound (Dwfl_Frame *state) { assert (state->unwound == NULL); @@ -522,6 +522,8 @@ new_unwound (Dwfl_Frame *state) assert (nregs > 0); Dwfl_Frame *unwound; unwound = malloc (sizeof (*unwound) + sizeof (*unwound->regs) * nregs); + if (unlikely (unwound == NULL)) + return NULL; state->unwound = unwound; unwound->thread = thread; unwound->unwound = NULL; @@ -529,6 +531,7 @@ new_unwound (Dwfl_Frame *state) unwound->initial_frame = false; unwound->pc_state = DWFL_FRAME_STATE_ERROR; memset (unwound->regs_set, 0, sizeof (unwound->regs_set)); + return unwound; } /* The logic is to call __libdwfl_seterrno for any CFI bytecode interpretation @@ -545,8 +548,14 @@ handle_cfi (Dwfl_Frame *state, Dwarf_Addr pc, Dwarf_CFI *cfi, Dwarf_Addr bias) __libdwfl_seterrno (DWFL_E_LIBDW); return; } - new_unwound (state); - Dwfl_Frame *unwound = state->unwound; + + Dwfl_Frame *unwound = new_unwound (state); + if (unwound == NULL) + { + __libdwfl_seterrno (DWFL_E_NOMEM); + return; + } + unwound->signal_frame = frame->fde->cie->signal_frame; Dwfl_Thread *thread = state->thread; Dwfl_Process *process = thread->process; @@ -730,7 +739,11 @@ __libdwfl_frame_unwind (Dwfl_Frame *state) Dwfl_Thread *thread = state->thread; Dwfl_Process *process = thread->process; Ebl *ebl = process->ebl; - new_unwound (state); + if (new_unwound (state) == NULL) + { + __libdwfl_seterrno (DWFL_E_NOMEM); + return; + } state->unwound->pc_state = DWFL_FRAME_STATE_PC_UNDEFINED; // &Dwfl_Frame.signal_frame cannot be passed as it is a bitfield. bool signal_frame = false; |