From: Indu Bhagat Date: Wed, 21 Jan 2026 20:00:22 +0000 (-0800) Subject: gas: sframe: graceful handling of bogus sleb128 input X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5ab662c071120811fb081f6a013303f74b34594d;p=thirdparty%2Fbinutils-gdb.git gas: sframe: graceful handling of bogus sleb128 input Currently, sframe_xlate_escape_sleb128_to_offsetT () uses a gas_assert to sanity check that a DWARF sleb128 value was successfully read from a single-byte buffer. However, if the byte provided has the highest bit set (e.g., bogus input of 0x80), the value of 'read' variable will be 0, triggering an assertion failure. This concern was raised during the review of SFrame-V3 patches https://inbox.sourceware.org/binutils/807b5641-87c2-4109-9d33-bb8fa28ed5ef@suse.com/T/#u Change the internal API sframe_xlate_escape_sleb128_to_offsetT () to return an error code. Callers now check for SFRAME_XLATE_ERR_INVAL and proceed to a warning/exit path rather than aborting. gas/ * gen-sframe.c (sframe_xlate_escape_sleb128_to_offsetT): Return int status. Handle read failure gracefully. (sframe_xlate_do_escape_cfa_expr): Check returned error code of read_sleb128_to_int64 and jump to warn_and_exit on error. (sframe_xlate_do_escape_expr): Likewise. --- diff --git a/gas/gen-sframe.c b/gas/gen-sframe.c index 90c8aeb12cc..61674021df9 100644 --- a/gas/gen-sframe.c +++ b/gas/gen-sframe.c @@ -1693,13 +1693,14 @@ sframe_xlate_do_gnu_window_save (struct sframe_xlate_ctx *xlate_ctx, return SFRAME_XLATE_ERR_NOTREPRESENTED; /* Not represented. */ } -/* Translate a DWARF sleb128 offset in the CFI escape data E to an offsetT. */ +/* Translate a DWARF sleb128 offset in the CFI escape data E to an offsetT. + Update the value in OFFSET if success (and return SFRAME_XLATE_OK). + Return SFRAME_XLATE_ERR_INVAL if error. */ -static offsetT -sframe_xlate_escape_sleb128_to_offsetT (const struct cfi_escape_data *e) +static int +sframe_xlate_escape_sleb128_to_offsetT (const struct cfi_escape_data *e, + offsetT *offset) { - offsetT offset; - gas_assert (e->type == CFI_ESC_byte || e->type == CFI_ESC_sleb128); /* Read the offset. */ if (e->type == CFI_ESC_byte) @@ -1713,14 +1714,17 @@ sframe_xlate_escape_sleb128_to_offsetT (const struct cfi_escape_data *e) const unsigned char *buf_end = buf_start + 1; int64_t value = 0; size_t read = read_sleb128_to_int64 (buf_start, buf_end, &value); - gas_assert (read); - offset = (offsetT) value; + /* In case of bogus input (highest bit erroneously set, e.g., 0x80), + gracefully exit. */ + if (!read) + return SFRAME_XLATE_ERR_INVAL; + *offset = (offsetT) value; } else /* offset must be CFI_ESC_sleb128. */ - offset = e->exp.X_add_number; + *offset = e->exp.X_add_number; - return offset; + return SFRAME_XLATE_OK; } /* Handle DW_CFA_def_cfa_expression in .cfi_escape. @@ -1742,7 +1746,7 @@ sframe_xlate_do_escape_cfa_expr (struct sframe_xlate_ctx *xlate_ctx, const struct cfi_escape_data *e_offset = NULL; int err = SFRAME_XLATE_OK; unsigned int opcode1, opcode2; - offsetT offset; + offsetT offset = 0; unsigned int reg = SFRAME_FRE_REG_INVALID; unsigned int i = 0; bool x86_cfa_deref_p = false; @@ -1781,6 +1785,10 @@ sframe_xlate_do_escape_cfa_expr (struct sframe_xlate_ctx *xlate_ctx, goto warn_and_exit; #undef CFI_ESC_NUM_EXP + err = sframe_xlate_escape_sleb128_to_offsetT (e_offset, &offset); + if (err == SFRAME_XLATE_ERR_INVAL) + goto warn_and_exit; + opcode1 = items[1]; opcode2 = items[3]; /* DW_OP_breg6 is rbp. FIXME - this stub can be enhanced to handle more @@ -1793,8 +1801,6 @@ sframe_xlate_do_escape_cfa_expr (struct sframe_xlate_ctx *xlate_ctx, reg = SFRAME_CFA_FP_REG; } - offset = sframe_xlate_escape_sleb128_to_offsetT (e_offset); - struct sframe_row_entry *cur_fre = xlate_ctx->cur_fre; gas_assert (cur_fre); @@ -1839,7 +1845,7 @@ sframe_xlate_do_escape_expr (struct sframe_xlate_ctx *xlate_ctx, const struct cfi_escape_data *e = cfi_insn->u.esc; const struct cfi_escape_data *e_offset = NULL; int err = SFRAME_XLATE_OK; - offsetT offset; + offsetT offset = 0; unsigned int i = 0; /* Check roughly for an expression @@ -1876,6 +1882,10 @@ sframe_xlate_do_escape_expr (struct sframe_xlate_ctx *xlate_ctx, goto warn_and_exit; #undef CFI_ESC_NUM_EXP + err = sframe_xlate_escape_sleb128_to_offsetT (e_offset, &offset); + if (err == SFRAME_XLATE_ERR_INVAL) + goto warn_and_exit; + /* reg operand to DW_CFA_expression is ULEB128. For the purpose at hand, however, the register value will be less than 128 (CFI_ESC_NUM_EXP set to 4). See an extended comment in sframe_xlate_do_escape_expr for why @@ -1894,8 +1904,6 @@ sframe_xlate_do_escape_expr (struct sframe_xlate_ctx *xlate_ctx, fp_base_reg = SFRAME_CFA_FP_REG; } - offset = sframe_xlate_escape_sleb128_to_offsetT (e_offset); - struct sframe_row_entry *cur_fre = xlate_ctx->cur_fre; gas_assert (cur_fre);