This is the mail archive of the archer@sourceware.org mailing list for the Archer 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]

Crash when casting a gdb.Value


Found a reproducible crash in the project archer python branch.
The problem occurs when you cast a gdb.Value to it's own type.
Reproduction (works with any executable):
gdb /bin/sleep
run 20
^C
python v=gdb.Value("string");v=v.cast(v.type);print v

Sometimes have to run the last command a few times to make sure python's
Garbage Collection kicks in.  When it does it will segfault, or one of a
couple of other (probably fatal) things will happen.

This occurs because when you cast a value to its own type valpy_cast will
call value_to_value_object with a value that is already tracked by a
value_object, and at some point down the line it will be double-freed.

If its of any use I've attached a patch that fixes valpy_cast, and adds a
warning to the comment above value_to_value_object.  I also checked all
the other callers to value_to_value_object, but they all seem ok.

It would seem nicer if value_to_value_object could track whether a value
its being passed is already tracked, and increment the refcount if it was,
but that would require either extra space or extra time.

This was found on an up to date git checkout of origin/archer-tromey-python.

2009-05-25  Richard Ward  <richard.j.ward1@googlemail.com>

* gdb/python/python-value.c
    Fixed bad call in valpy_cast to value_to_value_object which was
    causing a crash when the value was collected.
    Added a warning about this problem in comment.

Richard Ward
diff --git a/gdb/python/python-value.c b/gdb/python/python-value.c
index 743e6a6..25ae901 100644
--- a/gdb/python/python-value.c
+++ b/gdb/python/python-value.c
@@ -235,6 +235,7 @@ valpy_cast (PyObject *self, PyObject *args)
   struct type *type;
   struct value *res_val = NULL;	  /* Initialize to appease gcc warning.  */
   volatile struct gdb_exception except;
+  struct value *val=((value_object *) self)->value;
 
   if (! PyArg_ParseTuple (args, "O", &type_obj))
     return NULL;
@@ -248,11 +249,17 @@ valpy_cast (PyObject *self, PyObject *args)
 
   TRY_CATCH (except, RETURN_MASK_ALL)
     {
-      res_val = value_cast (type, ((value_object *) self)->value);
+      res_val = value_cast (type, val);
     }
   GDB_PY_HANDLE_EXCEPTION (except);
 
-  return value_to_value_object (res_val);
+  if(res_val == val)
+    {
+      Py_INCREF(self);
+      return self;
+    }
+  else
+    return value_to_value_object (res_val);
 }
 
 static Py_ssize_t
@@ -793,7 +800,12 @@ valpy_float (PyObject *self)
 }
 
 /* Returns an object for a value which is released from the all_values chain,
-   so its lifetime is not bound to the execution of a command.  */
+   so its lifetime is not bound to the execution of a command.
+   DO NOT call with a value that is already stored in a value_object, as
+   this will eventually crash gdb.  If necessary value_copy can be used
+   first. It may be better if values_in_python could track the PyObjects to
+   which they are assigned and this function could manipulate their
+   refcounts.  */
 PyObject *
 value_to_value_object (struct value *val)
 {
-- 
1.6.0.4


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