* [PATCH 1/6] Add safe_target_to_connection_object
2026-10-23 19:15 [PATCH 0/6] Remove some Python safety FIXME comments Tom Tromey
@ 2026-10-23 19:15 ` Tom Tromey
2026-10-23 19:15 ` [PATCH 2/6] Add safety wrappers for from_{longest,ulongest} Tom Tromey
` (4 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Tom Tromey @ 2026-10-23 19:15 UTC (permalink / raw)
To: gdb-patches; +Cc: Tom Tromey
This adds safe_target_to_connection_object, a simple wrapper that lets
us remove a FIXME from the Python code.
---
gdb/python/py-connection.c | 17 ++++++++++++-----
gdb/python/python-internal.h | 3 +++
2 files changed, 15 insertions(+), 5 deletions(-)
diff --git a/gdb/python/py-connection.c b/gdb/python/py-connection.c
index 0b10ed2e594..809c60f9ce3 100644
--- a/gdb/python/py-connection.c
+++ b/gdb/python/py-connection.c
@@ -148,6 +148,17 @@ target_to_connection_object (process_stratum_target *target)
return conn_obj;
}
+/* See python-internal.h. */
+
+gdbpy_ref<>
+safe_target_to_connection_object (process_stratum_target *target)
+{
+ gdbpy_ref<> result = target_to_connection_object (target);
+ if (result == nullptr)
+ throw gdb_python_exception ();
+ return result;
+}
+
/* Return a list of gdb.TargetConnection objects, one for each currently
active connection. The returned list is in no particular order. */
@@ -160,11 +171,7 @@ gdbpy_connections ()
{
gdb_assert (target != nullptr);
- gdbpy_ref<> conn = target_to_connection_object (target);
- /* FIXME: Python safety. target_to_connection_object should
- throw on error. */
- if (conn == nullptr)
- return nullptr;
+ gdbpy_ref<> conn = safe_target_to_connection_object (target);
gdb_assert (conn.get () != Py_None);
gdbpy_list_append (list, conn);
diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h
index 2e064107cbc..b57f3b0123d 100644
--- a/gdb/python/python-internal.h
+++ b/gdb/python/python-internal.h
@@ -607,6 +607,9 @@ PyObject *gdbpy_buffer_to_membuf (gdb::unique_xmalloc_ptr<gdb_byte> buffer,
struct process_stratum_target;
gdbpy_ref<> target_to_connection_object (process_stratum_target *target);
+/* A safe variant of target_to_connection_object; this throws on
+ error. */
+gdbpy_ref<> safe_target_to_connection_object (process_stratum_target *target);
gdbpy_ref<> gdbpy_connections ();
const struct block *block_object_to_block (PyObject *obj);
--
2.49.0
^ permalink raw reply [flat|nested] 7+ messages in thread* [PATCH 2/6] Add safety wrappers for from_{longest,ulongest}
2026-10-23 19:15 [PATCH 0/6] Remove some Python safety FIXME comments Tom Tromey
2026-10-23 19:15 ` [PATCH 1/6] Add safe_target_to_connection_object Tom Tromey
@ 2026-10-23 19:15 ` Tom Tromey
2026-10-23 19:15 ` [PATCH 3/6] Add gdbpy_safe_invalid_object_repr Tom Tromey
` (3 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Tom Tromey @ 2026-10-23 19:15 UTC (permalink / raw)
To: gdb-patches; +Cc: Tom Tromey
This adds a couple of safety wrappers for the APIs that convert from a
LONGEST or ULONGEST to Python. This allows the removal of some
FIXMEs.
---
gdb/python/py-arch.c | 14 ++------------
gdb/python/py-wrappers.h | 19 +++++++++++++++++++
2 files changed, 21 insertions(+), 12 deletions(-)
diff --git a/gdb/python/py-arch.c b/gdb/python/py-arch.c
index a6fd12b5ce5..3de1b3c4533 100644
--- a/gdb/python/py-arch.c
+++ b/gdb/python/py-arch.c
@@ -198,21 +198,11 @@ arch_object::disassemble (gdbpy_borrowed_ref<> args,
string_file stb (styling_p);
int insn_len = gdb_print_insn (gdbarch, pc, &stb, NULL);
- /* FIXME: Python safety. Eventually gdb_py_object_from_ulongest
- should throw. */
- gdbpy_ref<> pc_obj = gdb_py_object_from_ulongest (pc);
- if (pc_obj == nullptr)
- throw gdb_python_exception ();
-
+ gdbpy_ref<> pc_obj = gdbpy_safe_from_ulongest (pc);
gdbpy_ref<> asm_obj = gdbpy_unicode_from_string (!stb.empty ()
? stb.c_str ()
: "<unknown>");
-
- /* FIXME: Python safety. Eventually gdb_py_object_from_longest
- should throw. */
- gdbpy_ref<> len_obj = gdb_py_object_from_longest (insn_len);
- if (len_obj == nullptr)
- throw gdb_python_exception ();
+ gdbpy_ref<> len_obj = gdbpy_safe_from_longest (insn_len);
gdbpy_dict_set_item_string (insn_dict, "addr", pc_obj);
gdbpy_dict_set_item_string (insn_dict, "asm", asm_obj);
diff --git a/gdb/python/py-wrappers.h b/gdb/python/py-wrappers.h
index 2e2d451167a..69295fa6af3 100644
--- a/gdb/python/py-wrappers.h
+++ b/gdb/python/py-wrappers.h
@@ -384,4 +384,23 @@ gdbpy_get_address (gdbpy_borrowed_ref<> obj)
return result;
}
+/* A wrapper for gdb_py_object_from_longest that throws on error. */
+static inline gdbpy_ref<>
+gdbpy_safe_from_longest (LONGEST l)
+{
+ gdbpy_ref<> result = gdb_py_object_from_longest (l);
+ if (result == nullptr)
+ throw gdb_python_exception ();
+ return result;
+}
+
+/* A wrapper for gdb_py_object_from_ulongest that throws on error. */
+static inline gdbpy_ref<>
+gdbpy_safe_from_ulongest (ULONGEST l)
+{
+ gdbpy_ref<> result = gdb_py_object_from_ulongest (l);
+ if (result == nullptr)
+ throw gdb_python_exception ();
+ return result;
+}
#endif /* GDB_PYTHON_PY_WRAPPERS_H */
--
2.49.0
^ permalink raw reply [flat|nested] 7+ messages in thread* [PATCH 3/6] Add gdbpy_safe_invalid_object_repr
2026-10-23 19:15 [PATCH 0/6] Remove some Python safety FIXME comments Tom Tromey
2026-10-23 19:15 ` [PATCH 1/6] Add safe_target_to_connection_object Tom Tromey
2026-10-23 19:15 ` [PATCH 2/6] Add safety wrappers for from_{longest,ulongest} Tom Tromey
@ 2026-10-23 19:15 ` Tom Tromey
2026-10-23 19:15 ` [PATCH 4/6] Some symbol-related Python safety fixes Tom Tromey
` (2 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Tom Tromey @ 2026-10-23 19:15 UTC (permalink / raw)
To: gdb-patches; +Cc: Tom Tromey
This adds gdbpy_safe_invalid_object_repr, a simple wrapper that lets
us remove some Python FIXMEs.
---
gdb/python/py-arch.c | 4 +---
gdb/python/py-connection.c | 5 +----
gdb/python/py-frame.c | 4 +---
gdb/python/py-symbol.c | 5 +----
gdb/python/py-wrappers.h | 11 +++++++++++
5 files changed, 15 insertions(+), 14 deletions(-)
diff --git a/gdb/python/py-arch.c b/gdb/python/py-arch.c
index 3de1b3c4533..d9639797bb8 100644
--- a/gdb/python/py-arch.c
+++ b/gdb/python/py-arch.c
@@ -286,9 +286,7 @@ gdbpy_ref<>
arch_object::repr ()
{
if (gdbarch == nullptr)
- /* FIXME: Python safety. Eventually gdb_py_invalid_object_repr
- should throw. */
- return gdbpy_ref<> (gdb_py_invalid_object_repr (this));
+ return gdbpy_safe_invalid_object_repr (this);
auto arch_info = gdbarch_bfd_arch_info (gdbarch);
return gdbpy_unicode_from_format ("<%s arch_name=%s printable_name=%s>",
diff --git a/gdb/python/py-connection.c b/gdb/python/py-connection.c
index 809c60f9ce3..313a5202ee3 100644
--- a/gdb/python/py-connection.c
+++ b/gdb/python/py-connection.c
@@ -248,10 +248,7 @@ gdbpy_ref<>
connection_object::repr ()
{
if (target == nullptr)
- /* FIXME: Python safety. gdb_py_invalid_object_repr ought to
- throw on error, and return gdbpy_ref<>, but currently does
- not. */
- return gdbpy_ref<> (gdb_py_invalid_object_repr (this));
+ return gdbpy_safe_invalid_object_repr (this);
return (gdbpy_unicode_from_format
("<%s num=%d, what=\"%s\">",
diff --git a/gdb/python/py-frame.c b/gdb/python/py-frame.c
index 4aedd7db563..58b08c3d454 100644
--- a/gdb/python/py-frame.c
+++ b/gdb/python/py-frame.c
@@ -173,9 +173,7 @@ frame_object::repr ()
{
frame_info_ptr f_info = frame_find_by_id (frame_id);
if (f_info == nullptr)
- /* FIXME: Python safety. gdb_py_invalid_object_repr should
- throw on error. */
- return gdbpy_ref<> (gdb_py_invalid_object_repr (this));
+ return gdbpy_safe_invalid_object_repr (this);
return gdbpy_unicode_from_format ("<%s level=%d frame-id=%s>",
gdbpy_py_obj_tp_name (this).c_str (),
diff --git a/gdb/python/py-symbol.c b/gdb/python/py-symbol.c
index 3be1d933493..b5dcca5658d 100644
--- a/gdb/python/py-symbol.c
+++ b/gdb/python/py-symbol.c
@@ -320,10 +320,7 @@ gdbpy_ref<>
symbol_object::repr ()
{
if (symbol == nullptr)
- /* FIXME: Python safety. gdb_py_invalid_object_repr ought to
- throw on error, and return gdbpy_ref<>, but currently does
- not. */
- return gdbpy_ref<> (gdb_py_invalid_object_repr (this));
+ return gdbpy_safe_invalid_object_repr (this);
return gdbpy_unicode_from_format ("<%s print_name=%s>",
gdbpy_py_obj_tp_name (this).c_str (),
diff --git a/gdb/python/py-wrappers.h b/gdb/python/py-wrappers.h
index 69295fa6af3..1f7d4bfc467 100644
--- a/gdb/python/py-wrappers.h
+++ b/gdb/python/py-wrappers.h
@@ -403,4 +403,15 @@ gdbpy_safe_from_ulongest (ULONGEST l)
throw gdb_python_exception ();
return result;
}
+
+/* A wrapper for gdb_py_invalid_object_repr that throws on error. */
+static inline gdbpy_ref<>
+gdbpy_safe_invalid_object_repr (gdbpy_borrowed_ref<> self)
+{
+ gdbpy_ref<> result (gdb_py_invalid_object_repr (self));
+ if (result == nullptr)
+ throw gdb_python_exception ();
+ return result;
+}
+
#endif /* GDB_PYTHON_PY_WRAPPERS_H */
--
2.49.0
^ permalink raw reply [flat|nested] 7+ messages in thread* [PATCH 4/6] Some symbol-related Python safety fixes
2026-10-23 19:15 [PATCH 0/6] Remove some Python safety FIXME comments Tom Tromey
` (2 preceding siblings ...)
2026-10-23 19:15 ` [PATCH 3/6] Add gdbpy_safe_invalid_object_repr Tom Tromey
@ 2026-10-23 19:15 ` Tom Tromey
2026-10-23 19:15 ` [PATCH 5/6] Safe wrappers for some string conversions Tom Tromey
2026-10-23 19:15 ` [PATCH 6/6] Some frame-related Python safety fixes Tom Tromey
5 siblings, 0 replies; 7+ messages in thread
From: Tom Tromey @ 2026-10-23 19:15 UTC (permalink / raw)
To: gdb-patches; +Cc: Tom Tromey
This makes some symbol-related Python safety fixes, with a goal of
simplifying some code and removing some FIXMEs.
A method can now return a 'symbol *'; this will be handled by a new
to_python overload.
A safe wrapper is now provided for symbol_to_symbol_object.
---
gdb/python/py-frame.c | 9 +++----
gdb/python/py-safety.h | 10 ++++++++
gdb/python/py-symbol.c | 59 ++++++++++++--------------------------------
gdb/python/python-internal.h | 9 ++++---
4 files changed, 34 insertions(+), 53 deletions(-)
diff --git a/gdb/python/py-frame.c b/gdb/python/py-frame.c
index 58b08c3d454..e4dd9e9252e 100644
--- a/gdb/python/py-frame.c
+++ b/gdb/python/py-frame.c
@@ -103,7 +103,7 @@ struct frame_object : public PyObject
/* Implementation of gdb.Frame.function (self) -> gdb.Symbol.
Returns the symbol for the function corresponding to this frame. */
- gdbpy_ref<> function ();
+ symbol *function ();
/* Implementation of gdb.Frame.older (self) -> gdb.Frame.
Returns the frame immediately older (outer) to this frame, or None if
@@ -267,7 +267,7 @@ frame_object::block ()
}
-gdbpy_ref<>
+symbol *
frame_object::function ()
{
frame_info_ptr frame = require_frame ();
@@ -277,10 +277,7 @@ frame_object::function ()
gdb::unique_xmalloc_ptr<char> funname
= find_frame_funname (frame, &funlang, &sym);
- if (sym != nullptr)
- return symbol_to_symbol_object (sym);
-
- return py_none ();
+ return sym;
}
/* Convert a frame_info struct to a Python Frame object.
diff --git a/gdb/python/py-safety.h b/gdb/python/py-safety.h
index 0653947fe90..0d5a45e72fd 100644
--- a/gdb/python/py-safety.h
+++ b/gdb/python/py-safety.h
@@ -120,6 +120,16 @@ to_python (gdbpy_ref<> &&value)
return value.release ();
}
+static inline PyObject *
+to_python (symbol *sym)
+{
+ if (sym == nullptr)
+ return py_none ().release ();
+ /* Note that currently this might return NULL on error; but that is
+ fine in this context. */
+ return symbol_to_symbol_object (sym).release ();
+}
+
/* An instantiation of this function is used when calling a gdb method
from Python. It accepts some number of arguments (normally
gdbpy_borrowed_ref or gdbpy_opt_borrowed_ref), and then calls the
diff --git a/gdb/python/py-symbol.c b/gdb/python/py-symbol.c
index b5dcca5658d..0d4515643f5 100644
--- a/gdb/python/py-symbol.c
+++ b/gdb/python/py-symbol.c
@@ -289,6 +289,15 @@ symbol_to_symbol_object (struct symbol *sym)
return gdbpy_ref<> (sym_obj);
}
+gdbpy_ref<>
+safe_symbol_to_symbol_object (symbol *sym)
+{
+ gdbpy_ref<> result = symbol_to_symbol_object (sym);
+ if (result == nullptr)
+ throw gdb_python_exception ();
+ return result;
+}
+
/* Return the symbol that is wrapped by this symbol object. */
struct symbol *
symbol_object_to_symbol (PyObject *obj)
@@ -363,14 +372,8 @@ gdbpy_lookup_symbol (gdbpy_borrowed_ref<> args, gdbpy_opt_borrowed_ref<> kw)
gdbpy_ref<> ret_tuple = gdbpy_tuple_new (2);
gdbpy_ref<> sym_obj;
- if (symbol)
- {
- sym_obj = symbol_to_symbol_object (symbol);
- /* FIXME: Python safety. symbol_to_symbol_object should throw,
- but the other callers aren't ready for this yet. */
- if (sym_obj == nullptr)
- throw gdb_python_exception ();
- }
+ if (symbol != nullptr)
+ sym_obj = safe_symbol_to_symbol_object (symbol);
else
sym_obj = py_none ();
@@ -386,7 +389,7 @@ gdbpy_lookup_symbol (gdbpy_borrowed_ref<> args, gdbpy_opt_borrowed_ref<> kw)
/* Implementation of
gdb.lookup_global_symbol (name [, domain]) -> symbol or None. */
-gdbpy_ref<>
+symbol *
gdbpy_lookup_global_symbol (gdbpy_borrowed_ref<> args,
gdbpy_opt_borrowed_ref<> kw)
{
@@ -398,27 +401,13 @@ gdbpy_lookup_global_symbol (gdbpy_borrowed_ref<> args,
&domain);
domain_search_flags flags = from_scripting_domain (domain);
- struct symbol *symbol = lookup_global_symbol (name, NULL, flags).symbol;
-
- gdbpy_ref<> sym_obj;
- if (symbol != nullptr)
- {
- /* FIXME: Python safety. symbol_to_symbol_object should throw,
- but the other callers aren't ready for this yet. */
- sym_obj = symbol_to_symbol_object (symbol);
- if (sym_obj == nullptr)
- throw gdb_python_exception ();
- }
- else
- sym_obj = py_none ();
-
- return sym_obj;
+ return lookup_global_symbol (name, NULL, flags).symbol;
}
/* Implementation of
gdb.lookup_static_symbol (name [, domain]) -> symbol or None. */
-gdbpy_ref<>
+symbol *
gdbpy_lookup_static_symbol (gdbpy_borrowed_ref<> args,
gdbpy_opt_borrowed_ref<> kw)
{
@@ -455,19 +444,7 @@ gdbpy_lookup_static_symbol (gdbpy_borrowed_ref<> args,
if (symbol == nullptr)
symbol = lookup_static_symbol (name, flags).symbol;
- gdbpy_ref<> sym_obj;
- if (symbol != nullptr)
- {
- /* FIXME: Python safety. symbol_to_symbol_object should throw,
- but the other callers aren't ready for this yet. */
- sym_obj = symbol_to_symbol_object (symbol);
- if (sym_obj == nullptr)
- throw gdb_python_exception ();
- }
- else
- sym_obj = py_none ();
-
- return sym_obj;
+ return symbol;
}
/* Implementation of
@@ -512,11 +489,7 @@ gdbpy_lookup_static_symbols (gdbpy_borrowed_ref<> args,
if (symbol != nullptr)
{
- /* FIXME: Python safety. symbol_to_symbol_object should throw,
- but the other callers aren't ready for this yet. */
- gdbpy_ref<> sym_obj = symbol_to_symbol_object (symbol);
- if (sym_obj == nullptr)
- throw gdb_python_exception ();
+ gdbpy_ref<> sym_obj = safe_symbol_to_symbol_object (symbol);
gdbpy_list_append (return_list, sym_obj);
}
}
diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h
index b57f3b0123d..5515820411b 100644
--- a/gdb/python/python-internal.h
+++ b/gdb/python/python-internal.h
@@ -534,10 +534,10 @@ const char *gdbpy_frame_stop_reason_string (gdbpy_borrowed_ref<> args,
gdbpy_opt_borrowed_ref<> kw);
gdbpy_ref<> gdbpy_lookup_symbol (gdbpy_borrowed_ref<> args,
gdbpy_opt_borrowed_ref<> kw);
-gdbpy_ref<> gdbpy_lookup_global_symbol (gdbpy_borrowed_ref<> args,
- gdbpy_opt_borrowed_ref<> kw);
-gdbpy_ref<> gdbpy_lookup_static_symbol (gdbpy_borrowed_ref<> args,
- gdbpy_opt_borrowed_ref<> kw);
+symbol *gdbpy_lookup_global_symbol (gdbpy_borrowed_ref<> args,
+ gdbpy_opt_borrowed_ref<> kw);
+symbol *gdbpy_lookup_static_symbol (gdbpy_borrowed_ref<> args,
+ gdbpy_opt_borrowed_ref<> kw);
gdbpy_ref<> gdbpy_lookup_static_symbols (gdbpy_borrowed_ref<> args,
gdbpy_opt_borrowed_ref<> kw);
PyObject *gdbpy_start_recording (PyObject *self, PyObject *args);
@@ -572,6 +572,7 @@ void gdbpy_register_tui_window (gdbpy_borrowed_ref<> args,
gdbpy_ref<> symtab_and_line_to_sal_object (struct symtab_and_line sal);
gdbpy_ref<> symtab_to_symtab_object (struct symtab *symtab);
gdbpy_ref<> symbol_to_symbol_object (struct symbol *sym);
+gdbpy_ref<> safe_symbol_to_symbol_object (struct symbol *sym);
gdbpy_ref<> block_to_block_object (const struct block *block,
struct objfile *objfile);
gdbpy_ref<> value_to_value_object (struct value *v);
--
2.49.0
^ permalink raw reply [flat|nested] 7+ messages in thread* [PATCH 5/6] Safe wrappers for some string conversions
2026-10-23 19:15 [PATCH 0/6] Remove some Python safety FIXME comments Tom Tromey
` (3 preceding siblings ...)
2026-10-23 19:15 ` [PATCH 4/6] Some symbol-related Python safety fixes Tom Tromey
@ 2026-10-23 19:15 ` Tom Tromey
2026-10-23 19:15 ` [PATCH 6/6] Some frame-related Python safety fixes Tom Tromey
5 siblings, 0 replies; 7+ messages in thread
From: Tom Tromey @ 2026-10-23 19:15 UTC (permalink / raw)
To: gdb-patches; +Cc: Tom Tromey
This adds a couple of new Python wrappers for "safe-style" string
conversions. This allows some FIXME removal.
Note that I've added a new gdbpy_borrowed_ref constructor, from
gdbpy_opt_borrowed_ref. This is checked at runtime to preserve the
invariant.
---
gdb/python/py-frame.c | 9 ++-------
gdb/python/py-ref.h | 7 +++++++
gdb/python/py-tui.c | 7 +------
gdb/python/py-utils.c | 20 ++++++++++++++++++++
gdb/python/python-internal.h | 4 ++++
5 files changed, 34 insertions(+), 13 deletions(-)
diff --git a/gdb/python/py-frame.c b/gdb/python/py-frame.c
index e4dd9e9252e..e34d4b5d2e9 100644
--- a/gdb/python/py-frame.c
+++ b/gdb/python/py-frame.c
@@ -355,13 +355,8 @@ frame_object::read_var (gdbpy_borrowed_ref<> args,
var = symbol_object_to_symbol (sym_obj);
else if (gdbpy_is_string (sym_obj))
{
- gdb::unique_xmalloc_ptr<char>
- var_name (python_string_to_target_string (sym_obj));
-
- /* FIXME: Python safety. python_string_to_target_string should
- throw on error. */
- if (var_name == nullptr)
- throw gdb_python_exception ();
+ gdb::unique_xmalloc_ptr<char> var_name
+ = safe_python_string_to_target_string (sym_obj);
if (block_obj != nullptr)
{
diff --git a/gdb/python/py-ref.h b/gdb/python/py-ref.h
index 3d0373b7001..7cbfb03b103 100644
--- a/gdb/python/py-ref.h
+++ b/gdb/python/py-ref.h
@@ -108,6 +108,13 @@ class gdbpy_borrowed_ref : public gdbpy_opt_borrowed_ref<T>
gdb_assert (this->m_obj != nullptr);
}
+ template<typename U>
+ gdbpy_borrowed_ref (gdbpy_opt_borrowed_ref<U> obj)
+ : gdbpy_opt_borrowed_ref<T> (obj)
+ {
+ gdb_assert (this->m_obj != nullptr);
+ }
+
gdbpy_borrowed_ref (std::nullptr_t) = delete;
/* Allow a (checked) conversion to any subclass of T. */
diff --git a/gdb/python/py-tui.c b/gdb/python/py-tui.c
index 388e441ed55..be8c22aac27 100644
--- a/gdb/python/py-tui.c
+++ b/gdb/python/py-tui.c
@@ -506,13 +506,8 @@ gdbpy_tui_window::set_title (gdbpy_opt_borrowed_ref<> new_title)
gdbpy_err_format (PyExc_TypeError,
_("Cannot delete \"title\" attribute."));
- /* FIXME: Python safety. Ideally python_string_to_host_string would
- throw on error, but this can't be done until more of the code has
- been converted. */
gdb::unique_xmalloc_ptr<char> value
- = python_string_to_host_string (new_title);
- if (value == nullptr)
- throw gdb_python_exception ();
+ = safe_python_string_to_host_string (new_title);
window->set_title (value.get ());
}
diff --git a/gdb/python/py-utils.c b/gdb/python/py-utils.c
index 1c68b206601..40433256c62 100644
--- a/gdb/python/py-utils.c
+++ b/gdb/python/py-utils.c
@@ -119,6 +119,16 @@ python_string_to_target_string (PyObject *obj)
return unicode_to_target_string (str.get ());
}
+/* Wrapper for python_string_to_target_string that throws on failure. */
+gdb::unique_xmalloc_ptr<char>
+safe_python_string_to_target_string (gdbpy_borrowed_ref<> obj)
+{
+ gdb::unique_xmalloc_ptr<char> result = python_string_to_target_string (obj);
+ if (result == nullptr)
+ throw gdb_python_exception ();
+ return result;
+}
+
/* Converts a python string (8-bit or unicode) to a target string in the
target's charset. Returns NULL on error, with a python exception
set.
@@ -147,6 +157,16 @@ python_string_to_host_string (PyObject *obj)
return unicode_to_encoded_string (str.get (), host_charset ());
}
+/* Wrapper for python_string_to_host_string that throws on failure. */
+gdb::unique_xmalloc_ptr<char>
+safe_python_string_to_host_string (gdbpy_borrowed_ref<> obj)
+{
+ gdb::unique_xmalloc_ptr<char> result = python_string_to_host_string (obj);
+ if (result == nullptr)
+ throw gdb_python_exception ();
+ return result;
+}
+
/* See python/python-internal.h. */
gdbpy_ref<>
diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h
index 5515820411b..ee1a19131bd 100644
--- a/gdb/python/python-internal.h
+++ b/gdb/python/python-internal.h
@@ -1017,8 +1017,12 @@ void gdbpy_print_stack_or_quit ();
gdbpy_ref<> python_string_to_unicode (PyObject *obj);
gdb::unique_xmalloc_ptr<char> unicode_to_target_string (PyObject *unicode_str);
gdb::unique_xmalloc_ptr<char> python_string_to_target_string (PyObject *obj);
+gdb::unique_xmalloc_ptr<char> safe_python_string_to_target_string
+ (gdbpy_borrowed_ref<> obj);
gdbpy_ref<> python_string_to_target_python_string (PyObject *obj);
gdb::unique_xmalloc_ptr<char> python_string_to_host_string (PyObject *obj);
+gdb::unique_xmalloc_ptr<char> safe_python_string_to_host_string
+ (gdbpy_borrowed_ref<> obj);
/* Convert a host string STR to a python string. */
--
2.49.0
^ permalink raw reply [flat|nested] 7+ messages in thread* [PATCH 6/6] Some frame-related Python safety fixes
2026-10-23 19:15 [PATCH 0/6] Remove some Python safety FIXME comments Tom Tromey
` (4 preceding siblings ...)
2026-10-23 19:15 ` [PATCH 5/6] Safe wrappers for some string conversions Tom Tromey
@ 2026-10-23 19:15 ` Tom Tromey
5 siblings, 0 replies; 7+ messages in thread
From: Tom Tromey @ 2026-10-23 19:15 UTC (permalink / raw)
To: gdb-patches; +Cc: Tom Tromey
This makes some frame-related Python safety fixes, with a goal of
simplifying some code and removing some FIXMEs.
A method can now return a frame_info_ptr; this will be handled by a
new to_python overload.
A safe wrapper is now provided for frame_info_to_frame_object.
---
gdb/python/py-frame.c | 49 ++++++++++++++++----------------------------
gdb/python/py-inferior.c | 2 +-
gdb/python/py-safety.h | 11 ++++++++++
gdb/python/python-internal.h | 5 +++--
4 files changed, 33 insertions(+), 34 deletions(-)
diff --git a/gdb/python/py-frame.c b/gdb/python/py-frame.c
index e34d4b5d2e9..f9e95f3aec3 100644
--- a/gdb/python/py-frame.c
+++ b/gdb/python/py-frame.c
@@ -108,12 +108,12 @@ struct frame_object : public PyObject
/* Implementation of gdb.Frame.older (self) -> gdb.Frame.
Returns the frame immediately older (outer) to this frame, or None if
there isn't one. */
- gdbpy_ref<> older ();
+ frame_info_ptr older ();
/* Implementation of gdb.Frame.newer (self) -> gdb.Frame.
Returns the frame immediately newer (inner) to this frame, or None if
there isn't one. */
- gdbpy_ref<> newer ();
+ frame_info_ptr newer ();
/* Implementation of gdb.Frame.find_sal (self) -> gdb.Symtab_and_line.
Returns the frame's symtab and line. */
@@ -282,8 +282,6 @@ frame_object::function ()
/* Convert a frame_info struct to a Python Frame object.
Sets a Python exception and returns NULL on error. */
-/* FIXME: Python safety. This function should be converted, but the
- callers aren't ready yet. */
gdbpy_ref<>
frame_info_to_frame_object (const frame_info_ptr &frame)
@@ -307,27 +305,26 @@ frame_info_to_frame_object (const frame_info_ptr &frame)
}
gdbpy_ref<>
+safe_frame_info_to_frame_object (const frame_info_ptr &frame)
+{
+ gdbpy_ref<> result = frame_info_to_frame_object (frame);
+ if (result == nullptr)
+ throw gdb_python_exception ();
+ return result;
+}
+
+frame_info_ptr
frame_object::older ()
{
frame_info_ptr frame = require_frame ();
- frame_info_ptr prev = get_prev_frame (frame);
-
- if (prev)
- return frame_info_to_frame_object (prev);
-
- return py_none ();
+ return get_prev_frame (frame);
}
-gdbpy_ref<>
+frame_info_ptr
frame_object::newer ()
{
frame_info_ptr frame = require_frame ();
- frame_info_ptr next = get_next_frame (frame);
-
- if (next)
- return frame_info_to_frame_object (next);
-
- return py_none ();
+ return get_next_frame (frame);
}
gdbpy_ref<>
@@ -431,29 +428,19 @@ frame_object::static_link ()
/* Implementation of gdb.newest_frame () -> gdb.Frame.
Returns the newest frame object. */
-gdbpy_ref<>
+frame_info_ptr
gdbpy_newest_frame ()
{
- /* FIXME: Python safety. Convert frame_info_to_frame_object. */
- gdbpy_ref<> result = frame_info_to_frame_object (get_current_frame ());
- if (result == nullptr)
- throw gdb_python_exception ();
- return result;
+ return get_current_frame ();
}
/* Implementation of gdb.selected_frame () -> gdb.Frame.
Returns the selected frame object. */
-gdbpy_ref<>
+frame_info_ptr
gdbpy_selected_frame ()
{
- frame_info_ptr frame
- = get_selected_frame ("No frame is currently selected.");
- /* FIXME: Python safety. Convert frame_info_to_frame_object. */
- gdbpy_ref<> result = frame_info_to_frame_object (frame);
- if (result == nullptr)
- throw gdb_python_exception ();
- return result;
+ return get_selected_frame ("No frame is currently selected.");
}
/* Implementation of gdb.stop_reason_string (Integer) -> String.
diff --git a/gdb/python/py-inferior.c b/gdb/python/py-inferior.c
index 5e77f9f37bd..84a4b1ae6ee 100644
--- a/gdb/python/py-inferior.c
+++ b/gdb/python/py-inferior.c
@@ -1023,7 +1023,7 @@ python_context_changed (user_selected_what selection)
try
{
if (has_stack_frames ())
- frame_obj = gdbpy_selected_frame ();
+ frame_obj = safe_frame_info_to_frame_object (gdbpy_selected_frame ());
else
frame_obj = py_none ();
}
diff --git a/gdb/python/py-safety.h b/gdb/python/py-safety.h
index 0d5a45e72fd..b8e6434d168 100644
--- a/gdb/python/py-safety.h
+++ b/gdb/python/py-safety.h
@@ -120,6 +120,17 @@ to_python (gdbpy_ref<> &&value)
return value.release ();
}
+static inline PyObject *
+to_python (const frame_info_ptr &frame)
+{
+ if (frame.is_null ())
+ return py_none ().release ();
+
+ /* Note that currently this might return NULL on error; but that is
+ fine in this context. */
+ return frame_info_to_frame_object (frame).release ();
+}
+
static inline PyObject *
to_python (symbol *sym)
{
diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h
index ee1a19131bd..8aaf96021f7 100644
--- a/gdb/python/python-internal.h
+++ b/gdb/python/python-internal.h
@@ -543,8 +543,8 @@ gdbpy_ref<> gdbpy_lookup_static_symbols (gdbpy_borrowed_ref<> args,
PyObject *gdbpy_start_recording (PyObject *self, PyObject *args);
PyObject *gdbpy_current_recording (PyObject *self, PyObject *args);
PyObject *gdbpy_stop_recording (PyObject *self, PyObject *args);
-gdbpy_ref<> gdbpy_newest_frame ();
-gdbpy_ref<> gdbpy_selected_frame ();
+frame_info_ptr gdbpy_newest_frame ();
+frame_info_ptr gdbpy_selected_frame ();
PyObject *gdbpy_lookup_type (PyObject *self, PyObject *args, PyObject *kw);
int gdbpy_is_field (PyObject *obj);
PyObject *gdbpy_create_lazy_string_object (CORE_ADDR address, long length,
@@ -578,6 +578,7 @@ gdbpy_ref<> block_to_block_object (const struct block *block,
gdbpy_ref<> value_to_value_object (struct value *v);
gdbpy_ref<> type_to_type_object (struct type *);
gdbpy_ref<> frame_info_to_frame_object (const frame_info_ptr &frame);
+gdbpy_ref<> safe_frame_info_to_frame_object (const frame_info_ptr &frame);
gdbpy_ref<> symtab_to_linetable_object (PyObject *symtab);
gdbpy_ref<> pspace_to_pspace_object (struct program_space *);
PyObject *pspy_get_printers (PyObject *, void *);
--
2.49.0
^ permalink raw reply [flat|nested] 7+ messages in thread