PR 16286
authorDoug Evans <dje@google.com>
Wed, 11 Dec 2013 00:20:08 +0000 (16:20 -0800)
committerDoug Evans <dje@google.com>
Wed, 11 Dec 2013 00:20:08 +0000 (16:20 -0800)
* c-lang.c (c_get_string): Ignore the declared size of the object
if a specific length is requested.

testsuite/
* gdb.python/py-value.c: #include stdlib.h, string.h.
(str): New struct.
(main): New local xstr.
* gdb.python/py-value.exp (test_value_in_inferior): Add test to
fetch a value as a string with a length beyond the declared length
of the array.

gdb/ChangeLog
gdb/c-lang.c
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.python/py-value.c
gdb/testsuite/gdb.python/py-value.exp

index ed302dd1d1ffe2a73cd9dd6ebf2205b8320787c1..6c7fda5beef88b59f3a735122dd9b4b843fdc629 100644 (file)
@@ -1,3 +1,9 @@
+2013-12-10  Doug Evans  <dje@google.com>
+
+       PR 16286
+       * c-lang.c (c_get_string): Ignore the declared size of the object
+       if a specific length is requested.
+
 2013-12-10  Doug Evans  <dje@google.com>
 
        * interps.h (interp_exec_p): Delete.
index eecc76d6d105057086d7a8fee35e22627da20cac..2c075f46f4b262f0a1bffe05b3fb253a7a8c168e 100644 (file)
@@ -227,9 +227,13 @@ c_printstr (struct ui_file *stream, struct type *type,
    until a null character of the appropriate width is found, otherwise
    the string is read to the length of characters specified.  The size
    of a character is determined by the length of the target type of
-   the pointer or array.  If VALUE is an array with a known length,
-   the function will not read past the end of the array.  On
-   completion, *LENGTH will be set to the size of the string read in
+   the pointer or array.
+
+   If VALUE is an array with a known length, and *LENGTH is -1,
+   the function will not read past the end of the array.  However, any
+   declared size of the array is ignored if *LENGTH > 0.
+
+   On completion, *LENGTH will be set to the size of the string read in
    characters.  (If a length of -1 is specified, the length returned
    will not include the null character).  CHARSET is always set to the
    target charset.  */
@@ -309,6 +313,21 @@ c_get_string (struct value *value, gdb_byte **buffer,
     {
       CORE_ADDR addr = value_as_address (value);
 
+      /* Prior to the fix for PR 16196 read_string would ignore fetchlimit
+        if length > 0.  The old "broken" behaviour is the behaviour we want:
+        The caller may want to fetch 100 bytes from a variable length array
+        implemented using the common idiom of having an array of length 1 at
+        the end of a struct.  In this case we want to ignore the declared
+        size of the array.  However, it's counterintuitive to implement that
+        behaviour in read_string: what does fetchlimit otherwise mean if
+        length > 0.  Therefore we implement the behaviour we want here:
+        If *length > 0, don't specify a fetchlimit.  This preserves the
+        previous behaviour.  We could move this check above where we know
+        whether the array is declared with a fixed size, but we only want
+        to apply this behaviour when calling read_string.  PR 16286.  */
+      if (*length > 0)
+       fetchlimit = UINT_MAX;
+
       err = read_string (addr, *length, width, fetchlimit,
                         byte_order, buffer, length);
       if (err)
index ec01bffda7552cbd32ec7da0be94f8db2aaf9909..c8506045827f33728b789ad3900f09a4dac45d9e 100644 (file)
@@ -1,3 +1,12 @@
+2013-12-10  Doug Evans  <dje@google.com>
+
+       * gdb.python/py-value.c: #include stdlib.h, string.h.
+       (str): New struct.
+       (main): New local xstr.
+       * gdb.python/py-value.exp (test_value_in_inferior): Add test to
+       fetch a value as a string with a length beyond the declared length
+       of the array.
+
 2013-12-10  Andrew Burgess  <aburgess@broadcom.com>
 
        * lib/gdb.exp (gdb_compile_shlib): Add call to get_compiler_info,
index 0c94e64aa0662cfc43999da5ba64f8479a01a988..4f8c27b4c9f597aa63203ab1adf1c3e7d2f71e0e 100644 (file)
@@ -16,6 +16,8 @@
    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
 
 struct s
 {
@@ -39,6 +41,13 @@ typedef struct s *PTR;
 
 enum e evalue = TWO;
 
+struct str
+{
+  int length;
+  /* Variable length.  */
+  char text[1];
+};
+
 #ifdef __cplusplus
 
 struct Base {
@@ -86,6 +95,8 @@ main (int argc, char *argv[])
   int i = 2;
   int *ptr_i = &i;
   const char *sn = 0;
+  struct str *xstr;
+
   s.a = 3;
   s.b = 5;
   u.a = 7;
@@ -96,6 +107,12 @@ main (int argc, char *argv[])
   ptr_ref(ptr_i);
 #endif
 
+#define STR_LENGTH 100
+  xstr = (struct str *) malloc (sizeof (*xstr) + STR_LENGTH);
+  xstr->length = STR_LENGTH;
+  memset (xstr->text, 'x', STR_LENGTH);
+#undef STR_LENGTH
+
   save_argv = argv;      /* break to inspect struct and union */
   return 0;
 }
index 43de063ad00ef4cb9a1fe5a97c7b1d93c096bbc1..a05210481414cda82e9eb32a19e8f052e5b570c8 100644 (file)
@@ -291,6 +291,12 @@ proc test_value_in_inferior {} {
   # For the purposes of this test, use repr()
   gdb_py_test_silent_cmd "python nullst = nullst.string (length = 9)" "get string beyond null" 1
   gdb_test "python print (repr(nullst))" "u?'divide\\\\x00et'"
+
+  # 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"
 }
 
 proc test_lazy_strings {} {