]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
Mark unavailable bytes of limited-length arrays when allocating contents
authorHannes Domani <ssbssa@yahoo.de>
Tue, 6 Aug 2024 17:34:18 +0000 (19:34 +0200)
committerHannes Domani <ssbssa@yahoo.de>
Tue, 6 Aug 2024 17:36:25 +0000 (19:36 +0200)
Using 'output' to print arrays larger than max-value-size, with only
repeating elements, can cause gdb to crash:
```
$ cat a.c:
char a[1000000];

int main()
{
  return a[0];
}
$ gdb -q a
(gdb) print a
$1 = {0 '\000' <repeats 65536 times>, <unavailable> <repeats 934464 times>}
(gdb) output a

This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.
```

Using 'print' works, because value::record_latest sets the unavailable
bytes of the value when it's added to the value history.
But 'outout' doesn't do that, so the printing tries to access more bytes
than are available.

The original problem in PR32015 was about using 'print' of a dynamic
array in a D program.
Here the crash happens because for 'print' the value was a struct with
length/ptr fields, which is converted in d-valprint.c into an array.
So value::record_latest didn't have a chance to mark the unavailable
bytes in this case.

To make sure the unavailable bytes always match the contents, this fixes
it by marking the unavailable bytes immediately after the contents are
allocated.

Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=32015
Reviewed-By: Alexandra Petlanova Hajkova <ahajkova@redhat.com>
Approved-By: Andrew Burgess <aburgess@redhat.com>
gdb/testsuite/gdb.base/limited-length.c
gdb/testsuite/gdb.base/limited-length.exp
gdb/value.c

index 627c34d2dbe8f423f2a04ac702ed7685923e602e..c8ece16167eb76ca01b913353806967365ed26c8 100644 (file)
@@ -41,6 +41,8 @@ int large_2d_array[][10] = {
   {90, 91, 92, 93, 94, 95, 96, 97, 98, 99}
 };
 
+char large_empty_string[100000] = "";
+
 int
 main ()
 {
index a24adcb458a48b8fd4394f3cf74651d096853f2b..2d160e128ae1e1ccf6d0582fcbf849e66b8705cc 100644 (file)
@@ -240,3 +240,13 @@ with_test_prefix "with unlimited print elements" {
        "value is not available" \
        "output expression referring unavailable element from history"
 }
+
+gdb_test_no_output "set max-value-size 10000"
+gdb_test_no_output "set print elements 200"
+
+gdb_test "print large_empty_string" \
+    " = \\\{0 '\\\\000' <repeats 10000 times>, <unavailable> <repeats 90000 times>\\\}" \
+    "print large empty string which is not fully available"
+gdb_test -nonl "output large_empty_string" \
+    "\\\{0 '\\\\000' <repeats 10000 times>, <unavailable> <repeats 90000 times>\\\}" \
+    "output large empty string which is not fully available"
index 09fb19b9bf8a1a3ab910987690c00eb0d7236a32..aaa9ed20ae1c211a5a0f7d9f0c9fa2bd629b6356 100644 (file)
@@ -1716,10 +1716,6 @@ value::record_latest ()
       fetch_lazy ();
     }
 
-  ULONGEST limit = m_limited_length;
-  if (limit != 0)
-    mark_bytes_unavailable (limit, m_enclosing_type->length () - limit);
-
   /* Mark the value as recorded in the history for the availability check.  */
   m_in_history = true;
 
@@ -3990,6 +3986,11 @@ value::fetch_lazy_memory ()
   if (len > 0)
     read_value_memory (this, 0, stack (), addr,
                       contents_all_raw ().data (), len);
+
+  /* If only part of an array was loaded, mark the rest as unavailable.  */
+  if (m_limited_length > 0)
+    mark_bytes_unavailable (m_limited_length,
+                           m_enclosing_type->length () - m_limited_length);
 }
 
 /* See value.h.  */