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]

FYI: fix PR 11919


I am checking this in.

This patch fixes PR 11919.  That bug concerns an error case in the field
name completion code:

(gdb) p gdb_stdin.x.<TAB>Type struct ui_file has no component named x.

The fix is to catch exceptions from parse_field_expression and just
return NULL from the completer in this case.

This patch also fixes a latent memory leak in parse_field_expression,
and cleans up the error reporting code in lookup_struct_elt_type.

Built and regtested on x86-64 (compile farm).

Tom

2010-08-18  Tom Tromey  <tromey@redhat.com>

	PR symtab/11919:
	* gdbtypes.c (lookup_struct_elt_type): Clean up error emission.
	* parse.c (parse_field_expression): Use RETURN_MASK_ERROR.  Move
	name-copying lower.  Document exception behavior.
	* completer.c (expression_completer): Catch exceptions from
	parse_field_expression.

2010-08-18  Tom Tromey  <tromey@redhat.com>

	PR symtab/11919:
	* gdb.base/completion.exp: Add test.

Index: completer.c
===================================================================
RCS file: /cvs/src/src/gdb/completer.c,v
retrieving revision 1.39
diff -u -r1.39 completer.c
--- completer.c	13 May 2010 23:53:32 -0000	1.39
+++ completer.c	18 Aug 2010 18:33:05 -0000
@@ -24,6 +24,7 @@
 #include "filenames.h"		/* For DOSish file names.  */
 #include "language.h"
 #include "gdb_assert.h"
+#include "exceptions.h"
 
 #include "cli/cli-decode.h"
 
@@ -414,13 +415,19 @@
 char **
 expression_completer (struct cmd_list_element *ignore, char *text, char *word)
 {
-  struct type *type;
+  struct type *type = NULL;
   char *fieldname, *p;
+  volatile struct gdb_exception except;
 
   /* Perform a tentative parse of the expression, to see whether a
      field completion is required.  */
   fieldname = NULL;
-  type = parse_field_expression (text, &fieldname);
+  TRY_CATCH (except, RETURN_MASK_ERROR)
+    {
+      type = parse_field_expression (text, &fieldname);
+    }
+  if (except.reason < 0)
+    return NULL;
   if (fieldname && type)
     {
       for (;;)
Index: gdbtypes.c
===================================================================
RCS file: /cvs/src/src/gdb/gdbtypes.c,v
retrieving revision 1.196
diff -u -r1.196 gdbtypes.c
--- gdbtypes.c	28 Jul 2010 16:23:58 -0000	1.196
+++ gdbtypes.c	18 Aug 2010 18:33:07 -0000
@@ -1212,6 +1212,7 @@
 lookup_struct_elt_type (struct type *type, char *name, int noerr)
 {
   int i;
+  char *typename;
 
   for (;;)
     {
@@ -1225,11 +1226,9 @@
   if (TYPE_CODE (type) != TYPE_CODE_STRUCT 
       && TYPE_CODE (type) != TYPE_CODE_UNION)
     {
-      target_terminal_ours ();
-      gdb_flush (gdb_stdout);
-      fprintf_unfiltered (gdb_stderr, "Type ");
-      type_print (type, "", gdb_stderr, -1);
-      error (_(" is not a structure or union type."));
+      typename = type_to_string (type);
+      make_cleanup (xfree, typename);
+      error (_("Type %s is not a structure or union type."), typename);
     }
 
 #if 0
@@ -1281,14 +1280,9 @@
       return NULL;
     }
 
-  target_terminal_ours ();
-  gdb_flush (gdb_stdout);
-  fprintf_unfiltered (gdb_stderr, "Type ");
-  type_print (type, "", gdb_stderr, -1);
-  fprintf_unfiltered (gdb_stderr, " has no component named ");
-  fputs_filtered (name, gdb_stderr);
-  error (("."));
-  return (struct type *) -1;	/* For lint */
+  typename = type_to_string (type);
+  make_cleanup (xfree, typename);
+  error (_("Type %s has no component named %s."), typename, name);
 }
 
 /* Lookup the vptr basetype/fieldno values for TYPE.
Index: parse.c
===================================================================
RCS file: /cvs/src/src/gdb/parse.c,v
retrieving revision 1.102
diff -u -r1.102 parse.c
--- parse.c	4 Jun 2010 21:39:47 -0000	1.102
+++ parse.c	18 Aug 2010 18:33:07 -0000
@@ -1202,8 +1202,10 @@
 /* Parse STRING as an expression.  If parsing ends in the middle of a
    field reference, return the type of the left-hand-side of the
    reference; furthermore, if the parsing ends in the field name,
-   return the field name in *NAME.  In all other cases, return NULL.
-   Returned non-NULL *NAME must be freed by the caller.  */
+   return the field name in *NAME.  If the parsing ends in the middle
+   of a field reference, but the reference is somehow invalid, throw
+   an exception.  In all other cases, return NULL.  Returned non-NULL
+   *NAME must be freed by the caller.  */
 
 struct type *
 parse_field_expression (char *string, char **name)
@@ -1213,7 +1215,7 @@
   int subexp;
   volatile struct gdb_exception except;
 
-  TRY_CATCH (except, RETURN_MASK_ALL)
+  TRY_CATCH (except, RETURN_MASK_ERROR)
     {
       in_parse_field = 1;
       exp = parse_exp_in_context (&string, 0, 0, 0, &subexp);
@@ -1233,10 +1235,12 @@
       xfree (exp);
       return NULL;
     }
-  /* (*NAME) is a part of the EXP memory block freed below.  */
-  *name = xstrdup (*name);
 
+  /* This might throw an exception.  If so, we want to let it
+     propagate.  */
   val = evaluate_subexpression_type (exp, subexp);
+  /* (*NAME) is a part of the EXP memory block freed below.  */
+  *name = xstrdup (*name);
   xfree (exp);
 
   return value_type (val);
Index: testsuite/gdb.base/completion.exp
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.base/completion.exp,v
retrieving revision 1.46
diff -u -r1.46 completion.exp
--- testsuite/gdb.base/completion.exp	5 May 2010 18:06:57 -0000	1.46
+++ testsuite/gdb.base/completion.exp	18 Aug 2010 18:33:14 -0000
@@ -827,23 +827,8 @@
         timeout         { fail "(timeout) complete 'set follow-fork-mode'" }
         }
 
-send_gdb "p values\[0\].nonex.\t"
-gdb_expect  {
-        -re "Type struct some_struct has no component named nonex.\r\n$gdb_prompt $"\
-            { pass "Completing non-existing component" }
-        -re ".*$gdb_prompt $"       { fail "Completing non-existing component" }
-        timeout         { fail "(timeout) Completing non-existing component" }
-        eof             { fail "(eof) Completing non-existing component #2" }
-        }
-# Double memory freeing gets found only on the second run:
-send_gdb "p values\[0\].nonex.\t"
-gdb_expect  {
-        -re "Type struct some_struct has no component named nonex.\r\n$gdb_prompt $"\
-            { pass "Completing non-existing component #2" }
-        -re ".*$gdb_prompt $"       { fail "Completing non-existing component #2" }
-        timeout         { fail "(timeout) Completing non-existing component #2" }
-        eof             { fail "(eof) Completing non-existing component #2" }
-        }
+gdb_test_no_output "complete print values\[0\].x." \
+    "field completion with invalid field"
 
 # If there is a non-deprecated completion, it should be returned.
 gdb_test "complete sav" "save" "test non-deprecated completion"


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