This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH] Force array coercion in c_get_string


On 4/26/19 5:49 PM, Tom Tromey wrote:
>>>>>> "Pedro" == Pedro Alves <palves@redhat.com> writes:
> 
>>> The actual patch is somewhat more
>>> complicated than you might think, because the caller can request more
>>> array elements than the type allows.  This is normal when the type is
>>> using the C struct hack.
> 
> Pedro> Which test exposes this issue?
> 
> From py-value.exp:
> 
>   # Test fetching a string longer than its declared (in C) size.
>   # PR 16286
>   gdb_py_test_silent_cmd "python xstr = gdb.parse_and_eval('xstr')" "get xstr" 1
>   gdb_test "python print(xstr\['text'\].string (length = xstr\['length'\]))" "x{100}" \
>     "read string beyond declared size"
> 
> Pedro> I'm a bit confused here.  If we ever coerce an array and then read more
> Pedro> elements than the type allows, won't we be reading garbage passed the
> Pedro> coerced array elements?
> 
> In the case where we want to read past the array limit, c_get_string
> will take the second branch, which does an explicit read_string.

Try this:

 (gdb) python print (gdb.parse_and_eval("\"ab\"").string (length = 10))

This will go to the "in GDB's memory" branch, but it will
read beyond the value's contents buffer.

That's preexisting, but it's related to what I was saying above.

Looking at this comment:

> +     An array is assumed to live in GDB's memory, so we take this path
> +     here.  However, it's possible for the caller to request more
> +     array elements than apparently exist -- this can happen when
> +     using the C struct hack.  So, only do this for an array if either
> +     no length was specified, or the length is within the existing
> +     bounds.  */

in my previous message, I was thinking that in the second branch we'd
end up copying the array to target memory and then read past its end.

We won't copy the array to memory, because the other hunk skips
value_as_address.

However,

>    else
>      {
> -      CORE_ADDR addr = value_as_address (value);
> +      /* value_as_address calls coerce_array, but that won't actually
> +	 coerce the array if c_style_arrays is false.  In this case,
> +	 get the address of the array directly.  */

Note: I found this comment confusing.  The first sentence suggests that you
_want_ the coercion, including copying a "GDB memory" array to target
memory, but you don't get it because of c_style_arrays.
But I don't think getting the raw address of an array is coercion,
not in the sense of converting to a different type, like a pointer
to the first element, as in C.

> +      CORE_ADDR addr;
> +      if (TYPE_CODE (type) == TYPE_CODE_ARRAY)
> +	addr = value_address (value);

Can we get here with an LVAL != lval_memory?  

I assume so, given the condition:

  if ((VALUE_LVAL (value) == not_lval
       || VALUE_LVAL (value) == lval_internalvar)
      && fetchlimit != UINT_MAX)

So if we get to the second branch with:

 VALUE_LVAL (value) == not_lval
 TYPE_CODE (type) == TYPE_CODE_ARRAY
 fetchlimit == UINT_MAX

We'll be calling value_address on a non-lval_memory value.
value_address returns address 0 in that case, does not throw
an error (maybe it should).

value_coerce_array, if it were reached, has this:

  if (VALUE_LVAL (arg1) != lval_memory)
    error (_("Attempt to take address of value not located in memory."));

So shouldn't we have such a check here too?

Thanks,
Pedro Alves


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]