Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: Guinevere Larsen <guinevere@redhat.com>
To: Jielun Wu <firmiana402@gmail.com>, gdb-patches@sourceware.org
Subject: Re: [PATCH][PR gdb/34239][PR gdb/34299] gdb: Check bounds before reading DWARF expression operands
Date: Tue, 23 Jun 2026 15:56:04 -0300	[thread overview]
Message-ID: <c500f8d4-3396-4b6c-b297-65987c98e7c7@redhat.com> (raw)
In-Reply-To: <20260618180158.2893540-1-firmiana402@gmail.com>

On 6/18/26 3:01 PM, Jielun Wu wrote:
> Some DWARF expression opcodes read fixed-width operands or block payloads
> from the expression buffer before checking that the bytes are available.
> With a malformed expression, this can read past the end of the expression
> buffer.
>
> Add helpers that validate fixed-width integer reads and block payload
> skips, and use them in dwarf_expr_context::execute_stack_op.  Also guard
> the nested DW_OP_entry_value parser before reading the following opcode.
>
> Add a DWARF assembler test that exercises truncated operands for these
> opcodes.
>
> Tested on x86_64-linux.
>
> Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=34239
> Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=34299
> ---

Hi! Thanks for working on this!

I'm not too familiar with the dwarf parser, so I can only do a 
superficial review. Most of my comments are questions and nitpicks, I 
don't think you necessarily need to send a new version just from this 
review.

I have tested this and see no regressions, so feel free to add my test 
tag to the git trailers

Tested-By: Guinevere Larsen <guinevere@redhat.com>

>   gdb/dwarf2/expr.c                             | 166 +++++++++------
>   .../gdb.dwarf2/dw2-bad-dwarf-expr-bounds.exp  | 190 ++++++++++++++++++
>   2 files changed, 300 insertions(+), 56 deletions(-)
>   create mode 100644 gdb/testsuite/gdb.dwarf2/dw2-bad-dwarf-expr-bounds.exp
>
> diff --git a/gdb/dwarf2/expr.c b/gdb/dwarf2/expr.c
> index c71d4725b03..ead918388a4 100644
> --- a/gdb/dwarf2/expr.c
> +++ b/gdb/dwarf2/expr.c
> @@ -1370,7 +1370,45 @@ safe_skip_leb128 (const gdb_byte *buf, const gdb_byte *buf_end)
>       error (_("DWARF expression error: ran off end of buffer reading leb128 value"));
>     return buf;
>   }
> -\f
> +
> +/* Helper to skip BYTES bytes or throw an error.  */
> +
> +static const gdb_byte *
> +safe_skip_bytes (const gdb_byte *buf, const gdb_byte *buf_end,
> +		 ULONGEST bytes)
> +{
> +  if (buf > buf_end || bytes > (ULONGEST) (buf_end - buf))
> +    error (_("DWARF expression error: ran off end of buffer reading bytes"));
> +  return buf + bytes;
> +}
> +
> +/* Helper to read a fixed-width unsigned integer or throw an error.  */
> +
> +static const gdb_byte *
> +safe_read_unsigned_integer (const gdb_byte *buf, const gdb_byte *buf_end,
> +			    int len, bfd_endian byte_order, uint64_t *r)
> +{
> +  gdb_assert (len >= 0);
> +
> +  const gdb_byte *data = buf;
> +  buf = safe_skip_bytes (buf, buf_end, len);
> +  *r = extract_unsigned_integer (data, len, byte_order);
> +  return buf;

Oh, ok, it took me a while of thinking but I think I now understand why 
you wrote it like this.

You advance the buffer first to use that as a check that it is possible 
to read that many bytes from the buffer, instead of needing to double up 
on the if condition, right?

If so, I think it would be nice to have a comment explaining it, because 
I went through 2 incorrect explanations before reaching that conclusion.

> +}
> +
> +/* Helper to read a fixed-width signed integer or throw an error.  */
> +
> +static const gdb_byte *
> +safe_read_signed_integer (const gdb_byte *buf, const gdb_byte *buf_end,
> +			  int len, bfd_endian byte_order, int64_t *r)
> +{
> +  gdb_assert (len >= 0);
> +
> +  const gdb_byte *data = buf;
> +  buf = safe_skip_bytes (buf, buf_end, len);
> +  *r = extract_signed_integer (data, len, byte_order);
> +  return buf;
Similar comment as above
> +}
>   
>   /* Check that the current operator is either at the end of an
>      expression, or that it is followed by a composition operator or by
> @@ -1478,7 +1516,7 @@ dwarf_block_to_dwarf_reg_deref (gdb::array_view<const gdb_byte> block,
>         if (buf == NULL)
>   	return -1;
>         if ((int) dwarf_reg != dwarf_reg)
> -       return -1;
> +	return -1;
>       }
>     else
>       return -1;
> @@ -1488,6 +1526,8 @@ dwarf_block_to_dwarf_reg_deref (gdb::array_view<const gdb_byte> block,
>       return -1;
>     if (offset != 0)
>       return -1;
> +  if (buf >= buf_end)
> +    return -1;
>   
>     if (*buf == DW_OP_deref)
>       {
> @@ -1498,7 +1538,7 @@ dwarf_block_to_dwarf_reg_deref (gdb::array_view<const gdb_byte> block,
>       {
>         buf++;
>         if (buf >= buf_end)
> -       return -1;
> +	return -1;
>         *deref_size_return = *buf++;
>       }
>     else
> @@ -1688,9 +1728,10 @@ dwarf_expr_context::execute_stack_op (gdb::array_view<const gdb_byte> expr)
>   	  break;
>   
>   	case DW_OP_addr:
> -	  result = extract_unsigned_integer (op_ptr,
> -					     this->m_addr_size, byte_order);
> -	  op_ptr += this->m_addr_size;
> +	  op_ptr = safe_read_unsigned_integer (op_ptr, op_end,
> +					       this->m_addr_size,
> +					       byte_order, &uoffset);

Why not just send "&result" as the parameter here, instead of &uoffset

Same question for all the occurrences below

> +	  result = uoffset;
>   	  /* Some versions of GCC emit DW_OP_addr before
>   	     DW_OP_GNU_push_tls_address.  In this case the value is an
>   	     index, not an address.  We don't support things like
> @@ -1723,44 +1764,52 @@ dwarf_expr_context::execute_stack_op (gdb::array_view<const gdb_byte> expr)
>   	  break;
>   
>   	case DW_OP_const1u:
> -	  result = extract_unsigned_integer (op_ptr, 1, byte_order);
> +	  op_ptr = safe_read_unsigned_integer (op_ptr, op_end, 1,
> +					       byte_order, &uoffset);
> +	  result = uoffset;
>   	  result_val = value_from_ulongest (address_type, result);
> -	  op_ptr += 1;
>   	  break;
>   	case DW_OP_const1s:
> -	  result = extract_signed_integer (op_ptr, 1, byte_order);
> +	  op_ptr = safe_read_signed_integer (op_ptr, op_end, 1,
> +					     byte_order, &offset);
> +	  result = offset;
>   	  result_val = value_from_ulongest (address_type, result);
> -	  op_ptr += 1;
>   	  break;
>   	case DW_OP_const2u:
> -	  result = extract_unsigned_integer (op_ptr, 2, byte_order);
> +	  op_ptr = safe_read_unsigned_integer (op_ptr, op_end, 2,
> +					       byte_order, &uoffset);
> +	  result = uoffset;
>   	  result_val = value_from_ulongest (address_type, result);
> -	  op_ptr += 2;
>   	  break;
>   	case DW_OP_const2s:
> -	  result = extract_signed_integer (op_ptr, 2, byte_order);
> +	  op_ptr = safe_read_signed_integer (op_ptr, op_end, 2,
> +					     byte_order, &offset);
> +	  result = offset;
>   	  result_val = value_from_ulongest (address_type, result);
> -	  op_ptr += 2;
>   	  break;
>   	case DW_OP_const4u:
> -	  result = extract_unsigned_integer (op_ptr, 4, byte_order);
> +	  op_ptr = safe_read_unsigned_integer (op_ptr, op_end, 4,
> +					       byte_order, &uoffset);
> +	  result = uoffset;
>   	  result_val = value_from_ulongest (address_type, result);
> -	  op_ptr += 4;
>   	  break;
>   	case DW_OP_const4s:
> -	  result = extract_signed_integer (op_ptr, 4, byte_order);
> +	  op_ptr = safe_read_signed_integer (op_ptr, op_end, 4,
> +					     byte_order, &offset);
> +	  result = offset;
>   	  result_val = value_from_ulongest (address_type, result);
> -	  op_ptr += 4;
>   	  break;
>   	case DW_OP_const8u:
> -	  result = extract_unsigned_integer (op_ptr, 8, byte_order);
> +	  op_ptr = safe_read_unsigned_integer (op_ptr, op_end, 8,
> +					       byte_order, &uoffset);
> +	  result = uoffset;
>   	  result_val = value_from_ulongest (address_type, result);
> -	  op_ptr += 8;
>   	  break;
>   	case DW_OP_const8s:
> -	  result = extract_signed_integer (op_ptr, 8, byte_order);
> +	  op_ptr = safe_read_signed_integer (op_ptr, op_end, 8,
> +					     byte_order, &offset);
> +	  result = offset;
>   	  result_val = value_from_ulongest (address_type, result);
> -	  op_ptr += 8;
>   	  break;
>   	case DW_OP_constu:
>   	  op_ptr = safe_read_uleb128 (op_ptr, op_end, &uoffset);
> @@ -1836,12 +1885,10 @@ dwarf_expr_context::execute_stack_op (gdb::array_view<const gdb_byte> expr)
>   	    uint64_t len;
>   
>   	    op_ptr = safe_read_uleb128 (op_ptr, op_end, &len);
> -	    if (op_ptr + len > op_end)
> -	      error (_("DW_OP_implicit_value: too few bytes available."));
>   	    this->m_len = len;
>   	    this->m_data = op_ptr;
>   	    this->m_location = DWARF_VALUE_LITERAL;
> -	    op_ptr += len;
> +	    op_ptr = safe_skip_bytes (op_ptr, op_end, len);
>   	    dwarf_expr_require_composition (op_ptr, op_end,
>   					    "DW_OP_implicit_value");
>   	  }
> @@ -1861,9 +1908,10 @@ dwarf_expr_context::execute_stack_op (gdb::array_view<const gdb_byte> expr)
>   	    int ref_addr_size = this->m_per_cu->ref_addr_size ();
>   
>   	    /* The referred-to DIE of sect_offset kind.  */
> -	    this->m_len = extract_unsigned_integer (op_ptr, ref_addr_size,
> -						  byte_order);
> -	    op_ptr += ref_addr_size;
> +	    op_ptr = safe_read_unsigned_integer (op_ptr, op_end,
> +						 ref_addr_size, byte_order,
> +						 &uoffset);
> +	    this->m_len = uoffset;
Again, why not send "&this->m_len" ?
>   
>   	    /* The byte offset into the data.  */
>   	    op_ptr = safe_read_sleb128 (op_ptr, op_end, &len);
> @@ -1972,7 +2020,9 @@ dwarf_expr_context::execute_stack_op (gdb::array_view<const gdb_byte> expr)
>   	  goto no_push;
>   
>   	case DW_OP_pick:
> -	  offset = *op_ptr++;
> +	  op_ptr = safe_read_unsigned_integer (op_ptr, op_end, 1,
> +					       byte_order, &uoffset);
> +	  offset = uoffset;
>   	  result_val = fetch (offset);
>   	  in_stack_memory = fetch_in_stack_memory (offset);
>   	  break;
> @@ -2016,7 +2066,13 @@ dwarf_expr_context::execute_stack_op (gdb::array_view<const gdb_byte> expr)
>   	case DW_OP_deref_type:
>   	case DW_OP_GNU_deref_type:
>   	  {
> -	    int addr_size = (op == DW_OP_deref ? this->m_addr_size : *op_ptr++);
> +	    int addr_size = this->m_addr_size;
> +	    if (op != DW_OP_deref)
> +	      {
> +		op_ptr = safe_read_unsigned_integer (op_ptr, op_end, 1,
> +						     byte_order, &uoffset);
> +		addr_size = uoffset;

Maybe I'm missing something, but this seems like an incorrect change?

It seems like you should call safe_skip_bytes instead of 
read_unsigned_integer, and assign addr_size to *op_ptr?

> +	      }
>   	    CORE_ADDR addr = fetch_address (0);
>   	    struct type *type;
>   
> @@ -2249,8 +2305,8 @@ dwarf_expr_context::execute_stack_op (gdb::array_view<const gdb_byte> expr)
>   	  break;
>   
>   	case DW_OP_skip:
> -	  offset = extract_signed_integer (op_ptr, 2, byte_order);
> -	  op_ptr += 2;
> +	  op_ptr = safe_read_signed_integer (op_ptr, op_end, 2, byte_order,
> +					     &offset);
>   	  op_ptr += offset;
This should also use safe_skip_bytes
>   	  goto no_push;
>   
> @@ -2258,8 +2314,8 @@ dwarf_expr_context::execute_stack_op (gdb::array_view<const gdb_byte> expr)
>   	  {
>   	    struct value *val;
>   
> -	    offset = extract_signed_integer (op_ptr, 2, byte_order);
> -	    op_ptr += 2;
> +	    op_ptr = safe_read_signed_integer (op_ptr, op_end, 2, byte_order,
> +					       &offset);
>   	    val = fetch (0);
>   	    dwarf_require_integral (val->type ());
>   	    if (value_as_long (val) != 0)
> @@ -2313,18 +2369,18 @@ dwarf_expr_context::execute_stack_op (gdb::array_view<const gdb_byte> expr)
>   
>   	case DW_OP_call2:
>   	  {
> -	    cu_offset cu_off
> -	      = (cu_offset) extract_unsigned_integer (op_ptr, 2, byte_order);
> -	    op_ptr += 2;
> +	    op_ptr = safe_read_unsigned_integer (op_ptr, op_end, 2,
> +						 byte_order, &uoffset);
> +	    cu_offset cu_off = (cu_offset) uoffset;
>   	    this->dwarf_call (cu_off);
>   	  }
>   	  goto no_push;
>   
>   	case DW_OP_call4:
>   	  {
> -	    cu_offset cu_off
> -	      = (cu_offset) extract_unsigned_integer (op_ptr, 4, byte_order);
> -	    op_ptr += 4;
> +	    op_ptr = safe_read_unsigned_integer (op_ptr, op_end, 4,
> +						 byte_order, &uoffset);
> +	    cu_offset cu_off = (cu_offset) uoffset;
>   	    this->dwarf_call (cu_off);
>   	  }
>   	  goto no_push;
> @@ -2334,11 +2390,10 @@ dwarf_expr_context::execute_stack_op (gdb::array_view<const gdb_byte> expr)
>   	    ensure_have_per_cu (this->m_per_cu, "DW_OP_GNU_variable_value");
>   	    int ref_addr_size = this->m_per_cu->ref_addr_size ();
>   
> -	    sect_offset sect_off
> -	      = (sect_offset) extract_unsigned_integer (op_ptr,
> -							ref_addr_size,
> -							byte_order);
> -	    op_ptr += ref_addr_size;
> +	    op_ptr = safe_read_unsigned_integer (op_ptr, op_end,
> +						 ref_addr_size, byte_order,
> +						 &uoffset);
> +	    sect_offset sect_off = (sect_offset) uoffset;
>   	    result_val = sect_variable_value (sect_off, this->m_per_cu,
>   					      this->m_per_objfile);
>   	    result_val = value_cast (address_type, result_val);
> @@ -2353,15 +2408,13 @@ dwarf_expr_context::execute_stack_op (gdb::array_view<const gdb_byte> expr)
>   	    union call_site_parameter_u kind_u;
>   
>   	    op_ptr = safe_read_uleb128 (op_ptr, op_end, &len);
> -	    if (op_ptr + len > op_end)
> -	      error (_("DW_OP_entry_value: too few bytes available."));
> +	    const gdb_byte *expr_ptr = op_ptr;
> +	    op_ptr = safe_skip_bytes (op_ptr, op_end, len);
>   
> -	    auto entry_value_expr = gdb::make_array_view (op_ptr, len);
> +	    auto entry_value_expr = gdb::make_array_view (expr_ptr, len);
>   	    kind_u.dwarf_reg = dwarf_block_to_dwarf_reg (entry_value_expr);
>   	    if (kind_u.dwarf_reg != -1)
>   	      {
> -		op_ptr += len;
> -
>   		if (trivial_entry_value (this->m_frame))
>   		  {
>   		    /* We can assume that DW_OP_entry_value (expr) == expr.
> @@ -2384,7 +2437,6 @@ dwarf_expr_context::execute_stack_op (gdb::array_view<const gdb_byte> expr)
>   	      {
>   		if (deref_size == -1)
>   		  deref_size = this->m_addr_size;
> -		op_ptr += len;
>   
>   		if (trivial_entry_value (this->m_frame))
>   		  {
> @@ -2410,9 +2462,9 @@ dwarf_expr_context::execute_stack_op (gdb::array_view<const gdb_byte> expr)
>   	  {
>   	    union call_site_parameter_u kind_u;
>   
> -	    kind_u.param_cu_off
> -	      = (cu_offset) extract_unsigned_integer (op_ptr, 4, byte_order);
> -	    op_ptr += 4;
> +	    op_ptr = safe_read_unsigned_integer (op_ptr, op_end, 4,
> +						 byte_order, &uoffset);
> +	    kind_u.param_cu_off = (cu_offset) uoffset;
>   	    this->push_dwarf_reg_entry_value (CALL_SITE_PARAMETER_PARAM_OFFSET,
>   					      kind_u,
>   					      -1 /* deref_size */);
> @@ -2429,9 +2481,11 @@ dwarf_expr_context::execute_stack_op (gdb::array_view<const gdb_byte> expr)
>   	    op_ptr = safe_read_uleb128 (op_ptr, op_end, &uoffset);
>   	    cu_offset type_die_cu_off = (cu_offset) uoffset;
>   
> -	    n = *op_ptr++;
> +	    op_ptr = safe_read_unsigned_integer (op_ptr, op_end, 1, byte_order,
> +						 &uoffset);
> +	    n = uoffset;
>   	    data = op_ptr;
> -	    op_ptr += n;
> +	    op_ptr = safe_skip_bytes (op_ptr, op_end, n);
>   
>   	    type = get_base_type (type_die_cu_off);
>   
> diff --git a/gdb/testsuite/gdb.dwarf2/dw2-bad-dwarf-expr-bounds.exp b/gdb/testsuite/gdb.dwarf2/dw2-bad-dwarf-expr-bounds.exp
> new file mode 100644
> index 00000000000..7f5fa22388d
> --- /dev/null
> +++ b/gdb/testsuite/gdb.dwarf2/dw2-bad-dwarf-expr-bounds.exp
> @@ -0,0 +1,190 @@
> +# Copyright 2026 Free Software Foundation, Inc.
> +
> +# This program is free software; you can redistribute it and/or modify
> +# it under the terms of the GNU General Public License as published by
> +# the Free Software Foundation; either version 3 of the License, or
> +# (at your option) any later version.
> +#
> +# This program is distributed in the hope that it will be useful,
> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +# GNU General Public License for more details.
> +#
> +# You should have received a copy of the GNU General Public License
> +# along with this program.  If not, see <http://www.gnu.org/licenses/>.
> +
> +# Test malformed DWARF expressions whose opcodes have truncated operands.
> +
> +load_lib dwarf.exp
> +
> +require dwarf2_support
> +
> +standard_testfile main.c -dw.S
> +
> +set asm_file [standard_output_file $srcfile2]
> +Dwarf::assemble $asm_file {
> +    global srcfile
> +
> +    declare_labels int_label
> +
> +    cu {label cu_label} {
> +	DW_TAG_compile_unit {
> +	    DW_AT_name $srcfile
> +	    DW_AT_language @DW_LANG_C
> +	} {
> +	    int_label: DW_TAG_base_type {
> +		DW_AT_name "int"
> +		DW_AT_encoding @DW_ATE_signed
> +		DW_AT_byte_size 4 DW_FORM_sdata
> +	    }
> +
> +	    foreach {var op} {
> +		truncated_addr DW_OP_addr
> +		truncated_const1u DW_OP_const1u
> +		truncated_const1s DW_OP_const1s
> +		truncated_const2u DW_OP_const2u
> +		truncated_const2s DW_OP_const2s
> +		truncated_const4u DW_OP_const4u
> +		truncated_const4s DW_OP_const4s
> +		truncated_const8u DW_OP_const8u
> +		truncated_const8s DW_OP_const8s
> +		truncated_implicit_pointer DW_OP_implicit_pointer
> +		truncated_gnu_implicit_pointer DW_OP_GNU_implicit_pointer
> +		truncated_pick DW_OP_pick
> +		truncated_deref_size DW_OP_deref_size
> +		truncated_deref_type DW_OP_deref_type
> +		truncated_gnu_deref_type DW_OP_GNU_deref_type
> +		truncated_skip DW_OP_skip
> +		truncated_bra DW_OP_bra
> +		truncated_parameter_ref DW_OP_GNU_parameter_ref
> +	    } {
> +		DW_TAG_variable {
> +		    DW_AT_name $var
> +		    DW_AT_type :$int_label
> +		    DW_AT_location {
> +			_op .byte $Dwarf::_constants($op) $op
> +		    } SPECIAL_expr
> +		}
> +	    }
> +
> +	    DW_TAG_variable {
> +		DW_AT_name "truncated_implicit_value"
> +		DW_AT_type :$int_label
> +		DW_AT_location {
> +		    _op .byte $Dwarf::_constants(DW_OP_implicit_value) \
> +			DW_OP_implicit_value
> +		    _op .uleb128 4 "implicit value length"
> +		    _op .2byte 0 "truncated implicit value bytes"
> +		} SPECIAL_expr
> +	    }
> +
> +	    DW_TAG_variable {
> +		DW_AT_name "truncated_entry_value"
> +		DW_AT_type :$int_label
> +		DW_AT_location {
> +		    _op .byte $Dwarf::_constants(DW_OP_entry_value) \
> +			DW_OP_entry_value
> +		    _op .uleb128 4 "entry value expression length"
> +		    _op .2byte 0 "truncated entry value expression"
> +		} SPECIAL_expr
> +	    }
> +
> +	    DW_TAG_variable {
> +		DW_AT_name "truncated_gnu_entry_value"
> +		DW_AT_type :$int_label
> +		DW_AT_location {
> +		    _op .byte $Dwarf::_constants(DW_OP_GNU_entry_value) \
> +			DW_OP_GNU_entry_value
> +		    _op .uleb128 4 "entry value expression length"
> +		    _op .2byte 0 "truncated entry value expression"
> +		} SPECIAL_expr
> +	    }
> +
> +	    DW_TAG_variable {
> +		DW_AT_name "truncated_const_type_size"
> +		DW_AT_type :$int_label
> +		DW_AT_location {
> +		    _op .byte $Dwarf::_constants(DW_OP_const_type) \
> +			DW_OP_const_type
> +		    _op .uleb128 "$int_label - $cu_label" "type DIE offset"
> +		} SPECIAL_expr
> +	    }
> +
> +	    DW_TAG_variable {
> +		DW_AT_name "truncated_const_type_payload"
> +		DW_AT_type :$int_label
> +		DW_AT_location {
> +		    _op .byte $Dwarf::_constants(DW_OP_const_type) \
> +			DW_OP_const_type
> +		    _op .uleb128 "$int_label - $cu_label" "type DIE offset"
> +		    _op .byte 4 "constant block length"
> +		    _op .2byte 0 "truncated constant block"
> +		} SPECIAL_expr
> +	    }
> +
> +	    DW_TAG_variable {
> +		DW_AT_name "truncated_gnu_const_type_size"
> +		DW_AT_type :$int_label
> +		DW_AT_location {
> +		    _op .byte $Dwarf::_constants(DW_OP_GNU_const_type) \
> +			DW_OP_GNU_const_type
> +		    _op .uleb128 "$int_label - $cu_label" "type DIE offset"
> +		} SPECIAL_expr
> +	    }
> +
> +	    DW_TAG_variable {
> +		DW_AT_name "truncated_gnu_const_type_payload"
> +		DW_AT_type :$int_label
> +		DW_AT_location {
> +		    _op .byte $Dwarf::_constants(DW_OP_GNU_const_type) \
> +			DW_OP_GNU_const_type
> +		    _op .uleb128 "$int_label - $cu_label" "type DIE offset"
> +		    _op .byte 4 "constant block length"
> +		    _op .2byte 0 "truncated constant block"
> +		} SPECIAL_expr
> +	    }
> +	}
> +    }
> +}
> +
> +if {[prepare_for_testing "failed to prepare" ${testfile} \
> +	 [list $srcfile $asm_file] nodebug]} {
> +    return
> +}
> +
> +if {![runto_main]} {
> +    return
> +}
> +
> +foreach var {
> +    truncated_addr
> +    truncated_const1u
> +    truncated_const1s
> +    truncated_const2u
> +    truncated_const2s
> +    truncated_const4u
> +    truncated_const4s
> +    truncated_const8u
> +    truncated_const8s
> +    truncated_implicit_value
> +    truncated_implicit_pointer
> +    truncated_gnu_implicit_pointer
> +    truncated_pick
> +    truncated_deref_size
> +    truncated_deref_type
> +    truncated_gnu_deref_type
> +    truncated_skip
> +    truncated_bra
> +    truncated_entry_value
> +    truncated_gnu_entry_value
> +    truncated_parameter_ref
> +    truncated_const_type_size
> +    truncated_const_type_payload
> +    truncated_gnu_const_type_size
> +    truncated_gnu_const_type_payload
> +} {
> +    with_test_prefix $var {
There exists a "foreach_with_prefix", that does basically what you did 
here.
> +	gdb_test "print $var" \
> +	    ".*DWARF expression error: ran off end of buffer reading .*"
> +    }
> +}


-- 
Cheers,
Guinevere Larsen
it/its
she/her (deprecated)


  reply	other threads:[~2026-06-23 18:56 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-06-18 18:01 Jielun Wu
2026-06-23 18:56 ` Guinevere Larsen [this message]
2026-06-26  8:31   ` Firmiana
2026-06-26 14:30     ` Simon Marchi
2026-06-25 15:23 ` Simon Marchi
2026-06-25 16:36 ` Simon Marchi
2026-06-26  7:34   ` Firmiana
2026-06-26 14:23     ` Simon Marchi

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=c500f8d4-3396-4b6c-b297-65987c98e7c7@redhat.com \
    --to=guinevere@redhat.com \
    --cc=firmiana402@gmail.com \
    --cc=gdb-patches@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox