Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
* [PATCH v2] Fix crash when target-wide-charset doesn't match wchar_t size
@ 2026-10-21  9:01 Aditya Vidyadhar Kamath
  2026-10-23 18:36 ` Tom Tromey
  0 siblings, 1 reply; 5+ messages in thread
From: Aditya Vidyadhar Kamath @ 2026-10-21  9:01 UTC (permalink / raw)
  To: ulrich.weigand, simon.marchi, tom
  Cc: gdb-patches, Aditya.Kamath1, sangamesh.swamy, Aditya Vidyadhar Kamath

From: Aditya Vidyadhar Kamath <aditya.kamath1@ibm.com>

Tom asked a question [1] which is valid: can setting
target-wide-charset to an encoding with the wrong unit size crash GDB?

First I compiled gdb/testsuite/gdb.base/wchar.c

  gcc -g -maix64 -o /tmp/wchar64 gdb/testsuite/gdb.base/wchar.c

Then debug with GDB and we get the crash

  (gdb) b wchar.c:44
  (gdb) run
  (gdb) set target-wide-charset UTF-16
  (gdb) print single

  Fatal signal: Segmentation fault
  ----- Backtrace -----

This patch checks the width implied by the charset name against
wchar_bit in validate(), and gives an error if they differ.  Since the
set command stores the new value before calling the sfunc, restore the
old value when the check fails.

With the patch, the same session now
gives:

  (gdb) set target-wide-charset UTF-16
  Character set `UTF-16' has a 2-byte character width but `wchar_t' on this target is 4 bytes wide.
  Use `set target-wide-charset auto' to let GDB choose the correct encoding automatically.
  (gdb) print single
  $1 = 48879 L'\xbeef'

Add tests to wchar.exp for this.

[1]: https://sourceware.org/pipermail/gdb-patches/2026-October/231110.html
---
 gdb/charset.c                    | 51 +++++++++++++++++++++++++++++++-
 gdb/testsuite/gdb.base/wchar.exp | 31 +++++++++++++++++++
 2 files changed, 81 insertions(+), 1 deletion(-)

diff --git a/gdb/charset.c b/gdb/charset.c
index 1b0725b5078..9052f8b98c8 100644
--- a/gdb/charset.c
+++ b/gdb/charset.c
@@ -256,6 +256,10 @@ show_target_charset_name (struct ui_file *file, int from_tty,
 }
 
 static const char *target_wide_charset_name = "auto";
+
+/* Last known-good value of target_wide_charset_name, used to roll back
+   if a new setting fails validation.  */
+static const char *target_wide_charset_name_validated = "auto";
 static void
 show_target_wide_charset_name (struct ui_file *file,
 			       int from_tty,
@@ -336,6 +340,21 @@ set_be_le_names (struct gdbarch *gdbarch)
 /* 'Set charset', 'set host-charset', 'set target-charset', 'set
    target-wide-charset', 'set charset' sfunc's.  */
 
+/* Return the character width in bytes implied by a wide charset name:
+   2 for UTF-16/UCS-2, 4 for UTF-32/UCS-4, 0 if unknown.  */
+
+static int
+wide_charset_width (const char *name)
+{
+  if (strncasecmp (name, "UTF-16", 6) == 0
+      || strncasecmp (name, "UCS-2", 5) == 0)
+    return 2;
+  if (strncasecmp (name, "UTF-32", 6) == 0
+      || strncasecmp (name, "UCS-4", 5) == 0)
+    return 4;
+  return 0;
+}
+
 static void
 validate (struct gdbarch *gdbarch)
 {
@@ -346,6 +365,25 @@ validate (struct gdbarch *gdbarch)
 
   if (streq (target_wide_cset, "auto"))
     target_wide_cset = gdbarch_auto_wide_charset (gdbarch);
+  else
+    {
+      /* Reject charsets whose unit size doesn't match wchar_t.
+  A mismatch (e.g. UTF-16 with a 4-byte wchar_t) makes iconv
+  consume the wrong number of bytes and can crash GDB.  */
+      int charset_width = wide_charset_width (target_wide_cset);
+      if (charset_width != 0)
+	{
+	  int wchar_bytes = gdbarch_wchar_bit (gdbarch) / 8;
+	  if (charset_width != wchar_bytes)
+	    error (_ ("Character set \"%s\" has a %d-byte character width "
+		      "but \"wchar_t\" on this target is %d bytes wide.\n"
+		      "Use \"%ps\" to let GDB "
+		      "choose the correct encoding automatically."),
+		   target_wide_cset, charset_width, wchar_bytes,
+		   styled_string (command_style.style (),
+				  "set target-wide-charset auto"));
+	}
+    }
 
   desc = iconv_open (target_wide_cset, host_cset);
   if (desc == (iconv_t) -1)
@@ -395,7 +433,18 @@ static void
 set_target_wide_charset_sfunc (const char *charset, int from_tty,
 			       struct cmd_list_element *c)
 {
-  validate (get_current_arch ());
+  /* The setshow framework writes the new value before calling us, so
+     restore the previous setting if validation fails.  */
+  try
+    {
+      validate (get_current_arch ());
+      target_wide_charset_name_validated = target_wide_charset_name;
+    }
+  catch (const gdb_exception_error &)
+    {
+      target_wide_charset_name = target_wide_charset_name_validated;
+      throw;
+    }
 }
 
 /* sfunc for the 'show charset' command.  */
diff --git a/gdb/testsuite/gdb.base/wchar.exp b/gdb/testsuite/gdb.base/wchar.exp
index b02f4a78336..7a9b4612f9f 100644
--- a/gdb/testsuite/gdb.base/wchar.exp
+++ b/gdb/testsuite/gdb.base/wchar.exp
@@ -75,3 +75,34 @@ gdb_test "printf \"%ls\\n\", 0" "\\(null\\)"
 # From PR exp/33124 - a bug when converting escapes.
 set wbs {L'\\'}
 gdb_test "print $wbs" " = $decimal [string_to_regexp $wbs]"
+
+# A wide charset whose unit size doesn't match wchar_t must be rejected,
+# otherwise printing wide chars can crash GDB.
+# Use the encoding GDB picks for "auto" as the good one.
+set good_cs ""
+gdb_test_multiple "show target-wide-charset" "" {
+    -re "currently (UTF-\[0-9\]+).*$gdb_prompt $" {
+	set good_cs $expect_out(1,string)
+    }
+}
+if { $good_cs == "UTF-16" } {
+    set bad_cs UTF-32
+} elseif { $good_cs == "UTF-32" } {
+    set bad_cs UTF-16
+} else {
+    return
+}
+
+gdb_test "set target-wide-charset $bad_cs" \
+    "Character set \"$bad_cs\" has a .-byte character width.*" \
+    "reject target-wide-charset $bad_cs"
+
+# The rejected setting must not stick.
+gdb_test "print single" "= 48879 L'\\\\xbeef'" \
+    "print wchar_t after rejected target-wide-charset"
+
+gdb_test_no_output "set target-wide-charset $good_cs" \
+    "accept target-wide-charset $good_cs"
+
+gdb_test "print single" "= 48879 L'\\\\xbeef'" \
+    "print wchar_t with explicit target-wide-charset"
-- 
2.51.2


^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2026-10-27 11:19 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-21  9:01 [PATCH v2] Fix crash when target-wide-charset doesn't match wchar_t size Aditya Vidyadhar Kamath
2026-10-23 18:36 ` Tom Tromey
2026-10-23 18:41   ` Aditya Kamath
2026-10-23 19:31     ` Tom Tromey
2026-10-27 11:18       ` Aditya Kamath

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox