This is the mail archive of the
elfutils-devel@sourceware.org
mailing list for the elfutils project.
FYI unwinder unwinder limits
- From: Jan Kratochvil <jan dot kratochvil at redhat dot com>
- To: elfutils-devel at lists dot fedorahosted dot org
- Date: Sun, 27 Oct 2013 18:00:15 +0100
- Subject: FYI unwinder unwinder limits
Hi Mark,
just implemented the discussed simple execution limits.
The diff here is made with -b|--ignore-space-change.
Jan
diff --git a/libdwfl/frame_unwind.c b/libdwfl/frame_unwind.c
index a875e98..94213e5 100644
--- a/libdwfl/frame_unwind.c
+++ b/libdwfl/frame_unwind.c
@@ -36,6 +36,13 @@
#include "../libdw/dwarf.h"
#include <sys/ptrace.h>
+/* Maximum number of DWARF expression stack slots before returning an error. */
+#define DWARF_EXPR_STACK_MAX 0x100
+
+/* Maximum number of DWARF expression executed operations before returning an
+ error. */
+#define DWARF_EXPR_STEPS_MAX 0x1000
+
#ifndef MAX
# define MAX(a, b) ((a) > (b) ? (a) : (b))
#endif
@@ -90,7 +97,6 @@ bra_compar (const void *key_voidp, const void *elem_voidp)
/* If FRAME is NULL is are computing CFI frame base. In such case another
DW_OP_call_frame_cfa is no longer permitted. */
-/* FIXME: Handle bytecode deadlocks and overflows. */
static bool
expr_eval (Dwfl_Frame *state, Dwarf_Frame *frame, const Dwarf_Op *ops,
@@ -108,6 +114,11 @@ expr_eval (Dwfl_Frame *state, Dwarf_Frame *frame, const Dwarf_Op *ops,
bool
push (Dwarf_Addr val)
{
+ if (stack_used >= DWARF_EXPR_STACK_MAX)
+ {
+ __libdwfl_seterrno (DWFL_E_INVALID_DWARF);
+ return false;
+ }
if (stack_used == stack_allocated)
{
stack_allocated = MAX (stack_allocated * 2, 32);
@@ -137,7 +148,14 @@ expr_eval (Dwfl_Frame *state, Dwarf_Frame *frame, const Dwarf_Op *ops,
Dwarf_Addr val1, val2;
bool is_location = false;
+ size_t steps_count = 0;
for (const Dwarf_Op *op = ops; op < ops + nops; op++)
+ {
+ if (++steps_count > DWARF_EXPR_STEPS_MAX)
+ {
+ __libdwfl_seterrno (DWFL_E_INVALID_DWARF);
+ return false;
+ }
switch (op->atom)
{
/* DW_OP_* order matches libgcc/unwind-dw2.c execute_stack_op: */
@@ -447,6 +465,7 @@ expr_eval (Dwfl_Frame *state, Dwarf_Frame *frame, const Dwarf_Op *ops,
__libdwfl_seterrno (DWFL_E_INVALID_DWARF);
return false;
}
+ }
if (! pop (result))
{
free (stack);