This is the mail archive of the
archer@sourceware.org
mailing list for the Archer project.
[python] fix possible Type crash
- From: Tom Tromey <tromey at redhat dot com>
- To: Project Archer <archer at sourceware dot org>
- Date: Mon, 10 Nov 2008 10:27:58 -0700
- Subject: [python] fix possible Type crash
- Reply-to: tromey at redhat dot com
This fixes the possible Type crash I noticed recently.
In some situations, a derived Type must refer to the Type from which
it is derived. This avoids having a 'struct type' freed too soon.
This is still not ideal due to the lack of memoizing. That would
require much more work, though. However, I think it is necessary to
get things like '==' working in a nice way.
Tom
2008-11-10 Tom Tromey <tromey@redhat.com>
* python/python-value.c (valpy_type): Update.
* python/python-internal.h (type_to_type_object): Update.
* python/python-type.c (pyty_type_object) <originator>: New
field.
(typy_pointer): Update.
(typy_reference): Update.
(typy_target): Update.
(typy_template_argument): Update.
(type_to_type_object): Add 'parent' argument.
(set_type): Likewise. Initialize new field.
(typy_dealloc): Remove reference count on 'originator'.
diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h
index 672a2fe..71c2297 100644
--- a/gdb/python/python-internal.h
+++ b/gdb/python/python-internal.h
@@ -72,7 +72,7 @@ PyObject *symbol_to_symbol_object (struct symbol *sym);
PyObject *block_to_block_object (struct block *block);
PyObject *value_to_value_object (struct value *v);
PyObject *gdb_owned_value_to_value_object (struct value *v);
-PyObject *type_to_type_object (struct type *);
+PyObject *type_to_type_object (PyObject *, struct type *);
PyObject *objfile_to_objfile_object (struct objfile *);
PyObject *objfpy_get_printers (PyObject *, void *);
diff --git a/gdb/python/python-type.c b/gdb/python/python-type.c
index 996e4e6..3a1074c 100644
--- a/gdb/python/python-type.c
+++ b/gdb/python/python-type.c
@@ -41,6 +41,11 @@ typedef struct pyty_type_object
/* This is nonzero if the type is owned by this object and should be
freed when the object is deleted. */
int owned;
+
+ /* A Type derived from an 'owned' type will refer to its originator.
+ This prevents us from freeing the underlying 'type' too
+ early. In other cases, this is NULL. */
+ PyObject *originator;
} type_object;
static PyTypeObject type_object_type;
@@ -58,7 +63,7 @@ typy_pointer (PyObject *self, PyObject *args)
}
GDB_PY_HANDLE_EXCEPTION (except);
- return type_to_type_object (type);
+ return type_to_type_object (self, type);
}
/* Return a Type object which represents a reference to SELF. */
@@ -74,7 +79,7 @@ typy_reference (PyObject *self, PyObject *args)
}
GDB_PY_HANDLE_EXCEPTION (except);
- return type_to_type_object (type);
+ return type_to_type_object (self, type);
}
/* Return a Type object which represents the target type of SELF. */
@@ -89,7 +94,7 @@ typy_target (PyObject *self, PyObject *args)
return NULL;
}
- return type_to_type_object (TYPE_TARGET_TYPE (type));
+ return type_to_type_object (self, TYPE_TARGET_TYPE (type));
}
/* Return the size of the type represented by SELF, in bytes. */
@@ -247,7 +252,7 @@ typy_template_argument (PyObject *self, PyObject *args)
if (! argtype)
return NULL;
- return type_to_type_object (argtype);
+ return type_to_type_object (self, argtype);
}
static PyObject *
@@ -313,7 +318,7 @@ clean_up_objfile_types (struct objfile *objfile, void *datum)
}
static void
-set_type (type_object *obj, struct type *type)
+set_type (type_object *obj, struct type *type, type_object *parent)
{
obj->type = type;
obj->owned = 0;
@@ -329,6 +334,14 @@ set_type (type_object *obj, struct type *type)
}
else
obj->next = NULL;
+
+ if (type && parent && parent->owned)
+ {
+ Py_INCREF (parent);
+ obj->originator = (PyObject *) parent;
+ }
+ else
+ obj->originator = NULL;
}
static PyObject *
@@ -371,7 +384,7 @@ typy_new (PyTypeObject *subtype, PyObject *args, PyObject *kwargs)
if (! result)
return NULL;
- set_type (result, type);
+ set_type (result, type, NULL);
return (PyObject *) result;
}
@@ -392,6 +405,10 @@ typy_dealloc (PyObject *obj)
delete_type_recursive (type->type, deleted_types);
htab_delete (deleted_types);
}
+ else if (type->originator)
+ {
+ Py_DECREF (type->originator);
+ }
else
{
if (type->prev)
@@ -411,14 +428,18 @@ typy_dealloc (PyObject *obj)
type->ob_type->tp_free (type);
}
+/* Create a new Type referring to TYPE. PARENT is the Type from which
+ TYPE is derived; this is needed to handle reference counting for
+ derived 'owned' types. PARENT can be NULL if you know that this is
+ not a problem; otherwise it must be a Type object. */
PyObject *
-type_to_type_object (struct type *type)
+type_to_type_object (PyObject *parent, struct type *type)
{
type_object *type_obj;
type_obj = PyObject_New (type_object, &type_object_type);
if (type_obj)
- set_type (type_obj, type);
+ set_type (type_obj, type, (type_object *) parent);
return (PyObject *) type_obj;
}
diff --git a/gdb/python/python-value.c b/gdb/python/python-value.c
index 04039ce..9d88e58 100644
--- a/gdb/python/python-value.c
+++ b/gdb/python/python-value.c
@@ -150,7 +150,7 @@ static PyObject *
valpy_type (PyObject *self, PyObject *args)
{
struct value *value = ((value_object *) self)->value;
- return type_to_type_object (value_type (value));
+ return type_to_type_object (NULL, value_type (value));
}
/* Cast a value to a given type. */