diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 5ef6eb20a..80c17da 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,13 @@ +2010-11-04 Aman Gupta + * value.c (release_value): Return 0 on success. + (release_value_or_incref): New function, incref value if already + released. + * python/py-value.c (valpy_new, value_to_value_object): Use + release_value_or_incref() instead of value_incref() to prevent leaks. + (valpy_richcompare, valpy_binop, valpy_getitem): Call value_mark() + before calling into gdb, and make sure to value_free_to_mark() before + returning or raising any exceptions. + 2010-11-04 Hui Zhu * tracepoint.c (remote_trace_set_readonly_regions): Change lma to vma. diff --git a/gdb/python/py-value.c b/gdb/python/py-value.c index 4445655..f3c6309 100644 --- a/gdb/python/py-value.c +++ b/gdb/python/py-value.c @@ -150,7 +150,7 @@ valpy_new (PyTypeObject *subtype, PyObject *args, PyObject *keywords) } value_obj->value = value; - value_incref (value); + release_value_or_incref (value); value_obj->address = NULL; value_obj->type = NULL; value_obj->dynamic_type = NULL; @@ -445,8 +445,10 @@ valpy_getitem (PyObject *self, PyObject *key) { value_object *self_value = (value_object *) self; char *field = NULL; + PyObject *res_obj = NULL; struct value *res_val = NULL; volatile struct gdb_exception except; + struct value *mark = value_mark (); if (gdbpy_is_string (key)) { @@ -486,9 +488,15 @@ valpy_getitem (PyObject *self, PyObject *key) } xfree (field); + if (except.reason < 0) + value_free_to_mark (mark); GDB_PY_HANDLE_EXCEPTION (except); - return res_val ? value_to_value_object (res_val) : NULL; + if (res_val) + res_obj = value_to_value_object (res_val); + + value_free_to_mark (mark); + return res_obj; } static int @@ -625,8 +633,10 @@ enum valpy_opcode static PyObject * valpy_binop (enum valpy_opcode opcode, PyObject *self, PyObject *other) { + PyObject *res_obj = NULL; struct value *res_val = NULL; /* Initialize to appease gcc warning. */ volatile struct gdb_exception except; + struct value *mark = value_mark (); TRY_CATCH (except, RETURN_MASK_ALL) { @@ -717,9 +727,16 @@ valpy_binop (enum valpy_opcode opcode, PyObject *self, PyObject *other) break; } } + + if (except.reason < 0) + value_free_to_mark (mark); GDB_PY_HANDLE_EXCEPTION (except); - return res_val ? value_to_value_object (res_val) : NULL; + if (res_val) + res_obj = value_to_value_object (res_val); + + value_free_to_mark (mark); + return res_obj; } static PyObject * @@ -881,6 +898,7 @@ valpy_richcompare (PyObject *self, PyObject *other, int op) int result = 0; struct value *value_other; volatile struct gdb_exception except; + struct value *mark = value_mark (); if (other == Py_None) /* Comparing with None is special. From what I can tell, in Python @@ -939,6 +957,7 @@ valpy_richcompare (PyObject *self, PyObject *other, int op) break; } } + value_free_to_mark (mark); GDB_PY_HANDLE_EXCEPTION (except); /* In this case, the Python exception has already been set. */ @@ -1062,7 +1081,7 @@ value_to_value_object (struct value *val) if (val_obj != NULL) { val_obj->value = val; - value_incref (val); + release_value_or_incref (val); val_obj->address = NULL; val_obj->type = NULL; val_obj->dynamic_type = NULL; diff --git a/gdb/value.c b/gdb/value.c index 381318b..805dcf0 100644 --- a/gdb/value.c +++ b/gdb/value.c @@ -737,9 +737,10 @@ free_value_chain (struct value *v) } /* Remove VAL from the chain all_values - so it will not be freed automatically. */ + so it will not be freed automatically. + Result of 0 indicates the value was found and released. */ -void +int release_value (struct value *val) { struct value *v; @@ -748,7 +749,7 @@ release_value (struct value *val) { all_values = val->next; val->next = NULL; - return; + return 0; } for (v = all_values; v; v = v->next) @@ -757,12 +758,25 @@ release_value (struct value *val) { v->next = val->next; val->next = NULL; - break; + return 0; } } + + return -1; +} + +/* Release VAL or increment its reference count if + it was released already */ + +void +release_value_or_incref (struct value *val) +{ + if (release_value (val) != 0) + value_incref (val); } /* Release all values up to mark */ + struct value * value_release_to_mark (struct value *mark) { diff --git a/gdb/value.h b/gdb/value.h index 543290a..e7e00d2 100644 --- a/gdb/value.h +++ b/gdb/value.h @@ -641,7 +641,9 @@ extern void free_all_values (void); extern void free_value_chain (struct value *v); -extern void release_value (struct value *val); +extern int release_value (struct value *val); + +extern void release_value_or_incref (struct value *val); extern int record_latest_value (struct value *val);