[PATCH 13/28] fix get_addr_from_python

Tom Tromey
2013-04-19T14:34:11Z

get_addr_from_python confused the checker and so I decided to change
it to a form that it found more palatable. In particular now it
returns a negative value on error (using
CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION), and it can no longer throw
a gdb exception. This let me hoist calls to it out of some
TRY_CATCHes.

* python/py-inferior.c (gdbpy_inferiors): Update. Hoist
get_addr_from_python calls out of TRY_CATCH.
(infpy_write_memory, infpy_search_memory): Likewise.
* python/py-utils.c (get_addr_from_python): Return negative
value on error. Use TRY_CATCH.
* python/python-internal.h (get_addr_from_python): Use
CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION.
---
gdb/python/py-inferior.c | 103 ++++++++++++++++++-------------------------
gdb/python/py-utils.c | 21 ++++++---
gdb/python/python-internal.h | 3 +-
3 files changed, 59 insertions(+), 68 deletions(-)

diff --git a/gdb/python/py-inferior.c b/gdb/python/py-inferior.c
index d4ff90b..45b79ce 100644
--- a/gdb/python/py-inferior.c
+++ b/gdb/python/py-inferior.c
@@ -406,7 +406,6 @@ gdbpy_inferiors (PyObject *unused, PyObject *unused2)
static PyObject *
infpy_read_memory (PyObject *self, PyObject *args, PyObject *kw)
{
- int error = 0;
CORE_ADDR addr, length;
void *buffer = NULL;
membuf_object *membuf_obj;
@@ -418,15 +417,12 @@ infpy_read_memory (PyObject *self, PyObject *args, PyObject *kw)
&addr_obj, &length_obj))
return NULL;

+ if (get_addr_from_python (addr_obj, &addr) < 0
+ || get_addr_from_python (length_obj, &length) < 0)
+ return NULL;
+
TRY_CATCH (except, RETURN_MASK_ALL)
{
- if (!get_addr_from_python (addr_obj, &addr)
- || !get_addr_from_python (length_obj, &length))
- {
- error = 1;
- break;
- }
-
buffer = xmalloc (length);

read_memory (addr, buffer, length);
@@ -437,12 +433,6 @@ infpy_read_memory (PyObject *self, PyObject *args, PyObject *kw)
GDB_PY_HANDLE_EXCEPTION (except);
}

- if (error)
- {
- xfree (buffer);
- return NULL;
- }
-
membuf_obj = PyObject_New (membuf_object, &membuf_object_type);
if (membuf_obj == NULL)
{
@@ -477,7 +467,6 @@ static PyObject *
infpy_write_memory (PyObject *self, PyObject *args, PyObject *kw)
{
Py_ssize_t buf_len;
- int error = 0;
const char *buffer;
CORE_ADDR addr, length;
PyObject *addr_obj, *length_obj = NULL;
@@ -500,21 +489,16 @@ infpy_write_memory (PyObject *self, PyObject *args, PyObject *kw)
return NULL;
#endif

+ if (get_addr_from_python (addr_obj, &addr) < 0)
+ goto fail;
+
+ if (!length_obj)
+ length = buf_len;
+ else if (get_addr_from_python (length_obj, &length) < 0)
+ goto fail;
+
TRY_CATCH (except, RETURN_MASK_ALL)
{
- if (!get_addr_from_python (addr_obj, &addr))
- {
- error = 1;
- break;
- }
-
- if (!length_obj)
- length = buf_len;
- else if (!get_addr_from_python (length_obj, &length))
- {
- error = 1;
- break;
- }
write_memory_with_notification (addr, buffer, length);
}
#ifdef IS_PY3K
@@ -522,11 +506,13 @@ infpy_write_memory (PyObject *self, PyObject *args, PyObject *kw)
#endif
GDB_PY_HANDLE_EXCEPTION (except);

-
- if (error)
- return NULL;
-
Py_RETURN_NONE;
+
+ fail:
+#ifdef IS_PY3K
+ PyBuffer_Release (&pybuf);
+#endif
+ return NULL;
}

/* Destructor of Membuf objects. */
@@ -662,34 +648,26 @@ infpy_search_memory (PyObject *self, PyObject *args, PyObject *kw)
return NULL;
#endif

- if (get_addr_from_python (start_addr_obj, &start_addr)
- && get_addr_from_python (length_obj, &length))
- {
- if (!length)
- {
- PyErr_SetString (PyExc_ValueError,
- _("Search range is empty."));
+ if (get_addr_from_python (start_addr_obj, &start_addr) < 0)
+ goto fail;
+
+ if (get_addr_from_python (length_obj, &length) < 0)
+ goto fail;

-#ifdef IS_PY3K
- PyBuffer_Release (&pybuf);
-#endif
- return NULL;
- }
- /* Watch for overflows. */
- else if (length > CORE_ADDR_MAX
- || (start_addr + length - 1) < start_addr)
- {
- PyErr_SetString (PyExc_ValueError,
- _("The search range is too large."));
-
-#ifdef IS_PY3K
- PyBuffer_Release (&pybuf);
-#endif
- return NULL;
- }
+ if (!length)
+ {
+ PyErr_SetString (PyExc_ValueError,
+ _("Search range is empty."));
+ goto fail;
+ }
+ /* Watch for overflows. */
+ else if (length > CORE_ADDR_MAX
+ || (start_addr + length - 1) < start_addr)
+ {
+ PyErr_SetString (PyExc_ValueError,
+ _("The search range is too large."));
+ goto fail;
}
- else
- return NULL;

TRY_CATCH (except, RETURN_MASK_ALL)
{
@@ -697,16 +675,21 @@ infpy_search_memory (PyObject *self, PyObject *args, PyObject *kw)
buffer, pattern_size,
&found_addr);
}
- GDB_PY_HANDLE_EXCEPTION (except);
-
#ifdef IS_PY3K
PyBuffer_Release (&pybuf);
#endif
+ GDB_PY_HANDLE_EXCEPTION (except);

if (found)
return PyLong_FromLong (found_addr);
else
Py_RETURN_NONE;
+
+ fail:
+#ifdef IS_PY3K
+ PyBuffer_Release (&pybuf);
+#endif
+ return NULL;
}

/* Implementation of gdb.Inferior.is_valid (self) -> Boolean.
diff --git a/gdb/python/py-utils.c b/gdb/python/py-utils.c
index 4cd35a0..6a7e9e4 100644
--- a/gdb/python/py-utils.c
+++ b/gdb/python/py-utils.c
@@ -291,39 +291,46 @@ gdbpy_convert_exception (struct gdb_exception exception)

/* Converts OBJ to a CORE_ADDR value.

- Returns 1 on success or 0 on failure, with a Python exception set. This
- function can also throw GDB exceptions.
+ Returns 0 on success or -1 on failure, with a Python exception set.
*/

int
get_addr_from_python (PyObject *obj, CORE_ADDR *addr)
{
if (gdbpy_is_value_object (obj))
- *addr = value_as_address (value_object_to_value (obj));
+ {
+ volatile struct gdb_exception except;
+
+ TRY_CATCH (except, RETURN_MASK_ALL)
+ {
+ *addr = value_as_address (value_object_to_value (obj));
+ }
+ GDB_PY_SET_HANDLE_EXCEPTION (except);
+ }
else
{
PyObject *num = PyNumber_Long (obj);
gdb_py_ulongest val;

if (num == NULL)
- return 0;
+ return -1;

val = gdb_py_long_as_ulongest (num);
Py_XDECREF (num);
if (PyErr_Occurred ())
- return 0;
+ return -1;

if (sizeof (val) > sizeof (CORE_ADDR) && ((CORE_ADDR) val) != val)
{
PyErr_SetString (PyExc_ValueError,
_("Overflow converting to address."));
- return 0;
+ return -1;
}

*addr = val;
}

- return 1;
+ return 0;
}

/* Convert a LONGEST to the appropriate Python object -- either an
diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h
index b887b66..5c3fe51 100644
--- a/gdb/python/python-internal.h
+++ b/gdb/python/python-internal.h
@@ -424,7 +424,8 @@ extern PyObject *gdbpy_gdberror_exc;
extern void gdbpy_convert_exception (struct gdb_exception)
CPYCHECKER_SETS_EXCEPTION;

-int get_addr_from_python (PyObject *obj, CORE_ADDR *addr);
+int get_addr_from_python (PyObject *obj, CORE_ADDR *addr)
+ CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;

PyObject *gdb_py_object_from_longest (LONGEST l);
PyObject *gdb_py_object_from_ulongest (ULONGEST l);
--
1.8.1.4