mirror of
https://github.com/tobast/libunwind-eh_elf.git
synced 2024-11-25 00:27:39 +01:00
Fix undefined behavior in dwarf_eval_expr
The dwarf_eval_expr routine uses macros push, pop, and pick to manipulate the DWARF expression stack. When these macros are nested, e.g. in the implementation of DW_OP_dup: push (pick (0)); the combination can lead to unfortunate results. In particular, when substituting into: do { if (tos >= MAX_EXPR_STACK_SIZE) { Debug (1, "Stack overflow\n"); return -UNW_EINVAL; } stack[tos++] = (x); } while (0) a value of "x" that makes use of "tos" (as instances of the pick or pop macros do), the resulting expression will both use and modify tos without an intervening sequence point, which is undefined behavior according to the C standard. And in fact with current GCC on PowerPC, this leads to a miscompilation of the DW_OP_dup implementation. This patch fixes the problem by assigning "x" to a temporary variable before modifying tos. Signed-off-by: Ulrich Weigand <uweigand@de.ibm.com>
This commit is contained in:
parent
85ce920cff
commit
5710c98fbf
1 changed files with 2 additions and 1 deletions
|
@ -212,12 +212,13 @@ dwarf_eval_expr (struct dwarf_cursor *c, unw_word_t *addr, unw_word_t len,
|
||||||
})
|
})
|
||||||
# define push(x) \
|
# define push(x) \
|
||||||
do { \
|
do { \
|
||||||
|
unw_word_t _x = (x); \
|
||||||
if (tos >= MAX_EXPR_STACK_SIZE) \
|
if (tos >= MAX_EXPR_STACK_SIZE) \
|
||||||
{ \
|
{ \
|
||||||
Debug (1, "Stack overflow\n"); \
|
Debug (1, "Stack overflow\n"); \
|
||||||
return -UNW_EINVAL; \
|
return -UNW_EINVAL; \
|
||||||
} \
|
} \
|
||||||
stack[tos++] = (x); \
|
stack[tos++] = _x; \
|
||||||
} while (0)
|
} while (0)
|
||||||
# define pick(n) \
|
# define pick(n) \
|
||||||
({ \
|
({ \
|
||||||
|
|
Loading…
Reference in a new issue