Blob Blame History Raw
[patch][python] Fix sigsegv when a printer fails to return a value and string_print is set.
http://sourceware.org/ml/gdb-patches/2011-07/msg00719.html
http://sourceware.org/ml/gdb-cvs/2011-07/msg00234.html

### src/gdb/ChangeLog	2011/07/27 19:31:30	1.13236
### src/gdb/ChangeLog	2011/07/28 10:36:37	1.13237
## -1,3 +1,8 @@
+2011-07-28  Phil Muldoon  <pmuldoon@redhat.com>
+
+	* varobj.c (value_get_print_value): Move hint check later into the
+	function.  Comment function.  Free thevalue before reusing it.
+
 2011-07-27  Jan Kratochvil  <jan.kratochvil@redhat.com>
 	    Pedro Alves  <pedro@codesourcery.com>
 
--- src/gdb/varobj.c	2011/07/18 09:21:43	1.180
+++ src/gdb/varobj.c	2011/07/28 10:36:40	1.181
@@ -2610,25 +2610,21 @@
 
 	if (PyObject_HasAttr (value_formatter, gdbpy_to_string_cst))
 	  {
-	    char *hint;
 	    struct value *replacement;
 	    PyObject *output = NULL;
 
-	    hint = gdbpy_get_display_hint (value_formatter);
-	    if (hint)
-	      {
-		if (!strcmp (hint, "string"))
-		  string_print = 1;
-		xfree (hint);
-	      }
-
 	    output = apply_varobj_pretty_printer (value_formatter,
 						  &replacement,
 						  stb);
+
+	    /* If we have string like output ...  */
 	    if (output)
 	      {
 		make_cleanup_py_decref (output);
 
+		/* If this is a lazy string, extract it.  For lazy
+		   strings we always print as a string, so set
+		   string_print.  */
 		if (gdbpy_is_lazy_string (output))
 		  {
 		    gdbpy_extract_lazy_string (output, &str_addr, &type,
@@ -2638,12 +2634,27 @@
 		  }
 		else
 		  {
+		    /* If it is a regular (non-lazy) string, extract
+		       it and copy the contents into THEVALUE.  If the
+		       hint says to print it as a string, set
+		       string_print.  Otherwise just return the extracted
+		       string as a value.  */
+
 		    PyObject *py_str
 		      = python_string_to_target_python_string (output);
 
 		    if (py_str)
 		      {
 			char *s = PyString_AsString (py_str);
+			char *hint;
+
+			hint = gdbpy_get_display_hint (value_formatter);
+			if (hint)
+			  {
+			    if (!strcmp (hint, "string"))
+			      string_print = 1;
+			    xfree (hint);
+			  }
 
 			len = PyString_Size (py_str);
 			thevalue = xmemdup (s, len + 1, len + 1);
@@ -2662,6 +2673,9 @@
 		      gdbpy_print_stack ();
 		  }
 	      }
+	    /* If the printer returned a replacement value, set VALUE
+	       to REPLACEMENT.  If there is not a replacement value,
+	       just use the value passed to this function.  */
 	    if (replacement)
 	      value = replacement;
 	  }
@@ -2672,12 +2686,18 @@
   get_formatted_print_options (&opts, format_code[(int) format]);
   opts.deref_ref = 0;
   opts.raw = 1;
+
+  /* If the THEVALUE has contents, it is a regular string.  */
   if (thevalue)
     LA_PRINT_STRING (stb, type, thevalue, len, encoding, 0, &opts);
   else if (string_print)
+    /* Otherwise, if string_print is set, and it is not a regular
+       string, it is a lazy string.  */
     val_print_string (type, encoding, str_addr, len, stb, &opts);
   else
+    /* All other cases.  */
     common_val_print (value, stb, 0, &opts, current_language);
+
   thevalue = ui_file_xstrdup (stb, NULL);
 
   do_cleanups (old_chain);
### src/gdb/testsuite/ChangeLog	2011/07/27 21:18:39	1.2816
### src/gdb/testsuite/ChangeLog	2011/07/28 10:36:40	1.2817
## -1,3 +1,10 @@
+2011-07-28  Phil Muldoon  <pmuldoon@redhat.com>
+
+	* gdb.python/py-mi.exp: Test printers returning string hint, and
+	also not returning a value.
+	* gdb.python/py-prettyprint.c: Add testcase for above.
+	* gdb.python/py-prettyprint.py: Add test printer for above.
+
 2011-07-27  Jan Kratochvil  <jan.kratochvil@redhat.com>
 
 	* gdb.dwarf2/dw2-simple-locdesc.S: Change DWARF version to 3.
--- src/gdb/testsuite/gdb.python/py-mi.exp	2011/07/26 18:38:55	1.13
+++ src/gdb/testsuite/gdb.python/py-mi.exp	2011/07/28 10:36:40	1.14
@@ -284,6 +284,13 @@ mi_list_varobj_children nstype2 {
     { {nstype2.<error at 0>} {<error at 0>} 6 {char \[6\]} }
 } "list children after setting exception flag"
 
+mi_create_varobj me me \
+  "create me varobj"
+
+mi_gdb_test "-var-evaluate-expression me" \
+	"\\^done,value=\"<error reading variable: Cannot access memory.>.*\"" \
+	"evaluate me varobj"
+
 # C++ MI tests
 gdb_exit
 if  { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" \
--- src/gdb/testsuite/gdb.python/py-prettyprint.c	2011/04/29 12:45:46	1.12
+++ src/gdb/testsuite/gdb.python/py-prettyprint.c	2011/07/28 10:36:40	1.13
@@ -149,6 +149,11 @@
 
 typedef struct justchildren nostring_type;
 
+struct memory_error
+{
+  const char *s;
+};
+
 struct container
 {
   string name;
@@ -227,6 +232,7 @@
   /* Clearing by being `static' could invoke an other GDB C++ bug.  */
   struct nullstr nullstr;
   nostring_type nstype, nstype2;
+  struct memory_error me;
   struct ns ns, ns2;
   struct lazystring estring, estring2;
   struct hint_error hint_error;
@@ -234,6 +240,8 @@
   nstype.elements = narray;
   nstype.len = 0;
 
+  me.s = "blah";
+
   init_ss(&ss, 1, 2);
   init_ss(ssa+0, 3, 4);
   init_ss(ssa+1, 5, 6);
--- src/gdb/testsuite/gdb.python/py-prettyprint.py	2011/04/11 17:40:41	1.11
+++ src/gdb/testsuite/gdb.python/py-prettyprint.py	2011/07/28 10:36:40	1.12
@@ -17,6 +17,7 @@
 # printers.
 
 import re
+import gdb
 
 # Test returning a Value from a printer.
 class string_print:
@@ -186,6 +187,18 @@
         yield 's', self.val['s']
         yield 'x', self.val['x']
 
+class MemoryErrorString:
+    "Raise an error"
+
+    def __init__(self, val):
+        self.val = val
+
+    def to_string(self):
+        raise gdb.MemoryError ("Cannot access memory.");
+
+    def display_hint (self):
+        return 'string'
+
 def lookup_function (val):
     "Look-up and return a pretty-printer that can print val."
 
@@ -261,6 +274,8 @@
     pretty_printers_dict[re.compile ('^struct hint_error$')]  = pp_hint_error
     pretty_printers_dict[re.compile ('^hint_error$')]  = pp_hint_error
 
+    pretty_printers_dict[re.compile ('^memory_error$')]  = MemoryErrorString
+
 pretty_printers_dict = {}
 
 register_pretty_printers ()