* [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
* Re: [PATCH v2] Fix crash when target-wide-charset doesn't match wchar_t size
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
0 siblings, 1 reply; 5+ messages in thread
From: Tom Tromey @ 2026-10-23 18:36 UTC (permalink / raw)
To: Aditya Vidyadhar Kamath
Cc: ulrich.weigand, simon.marchi, tom, gdb-patches, Aditya.Kamath1,
sangamesh.swamy
>>>>> Aditya Vidyadhar Kamath <akamath996@gmail.com> writes:
> 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 -----
Could you show the backtrace? I don't know if I can reproduce this but
I am also curious to know how it happens.
> +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;
I somewhat suspect we should have a different fix targeting the crash
itself. But I'm not totally sure.
Tom
^ permalink raw reply [flat|nested] 5+ messages in thread
* RE: [PATCH v2] Fix crash when target-wide-charset doesn't match wchar_t size
2026-10-23 18:36 ` Tom Tromey
@ 2026-10-23 18:41 ` Aditya Kamath
2026-10-23 19:31 ` Tom Tromey
0 siblings, 1 reply; 5+ messages in thread
From: Aditya Kamath @ 2026-10-23 18:41 UTC (permalink / raw)
To: Tom Tromey, Aditya Vidyadhar Kamath
Cc: Ulrich Weigand, simon.marchi, tom, gdb-patches, SANGAMESH MALLAYYA
[-- Attachment #1: Type: text/plain, Size: 391 bytes --]
Hi Tom,
>Could you show the backtrace? I don't know if I can reproduce this but
>I am also curious to know how it happens.
https://sourceware.org/pipermail/gdb-patches/2026-October/231148.html
Please see the stack in the mailing list link above I shared with Simon. It has the backtrace plus core dump backtrace stack.
Have a nice day ahead.
Thanks and regards,
Aditya.
[-- Attachment #2: Type: text/html, Size: 1939 bytes --]
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH v2] Fix crash when target-wide-charset doesn't match wchar_t size
2026-10-23 18:41 ` Aditya Kamath
@ 2026-10-23 19:31 ` Tom Tromey
2026-10-27 11:18 ` Aditya Kamath
0 siblings, 1 reply; 5+ messages in thread
From: Tom Tromey @ 2026-10-23 19:31 UTC (permalink / raw)
To: Aditya Kamath
Cc: Tom Tromey, Aditya Vidyadhar Kamath, Ulrich Weigand,
simon.marchi, gdb-patches, SANGAMESH MALLAYYA
> https://sourceware.org/pipermail/gdb-patches/2026-October/231148.html
> Please see the stack in the mailing list link above I shared with
> Simon. It has the backtrace plus core dump backtrace stack.
Ok. It's kind of hard to read that message for me (there's no
line-wrapping in the web browser); but I tend to think the bug is in
wchar_iterator. I think it shouldn't be possible for it to read too
much, or for m_bytes to wrap.
Tom
^ permalink raw reply [flat|nested] 5+ messages in thread
* RE: [PATCH v2] Fix crash when target-wide-charset doesn't match wchar_t size
2026-10-23 19:31 ` Tom Tromey
@ 2026-10-27 11:18 ` Aditya Kamath
0 siblings, 0 replies; 5+ messages in thread
From: Aditya Kamath @ 2026-10-27 11:18 UTC (permalink / raw)
To: Tom Tromey
Cc: Tom Tromey, Aditya Vidyadhar Kamath, Ulrich Weigand,
simon.marchi, gdb-patches, SANGAMESH MALLAYYA
[-- Attachment #1: Type: text/plain, Size: 1483 bytes --]
Hi Tom and community members,
>> https://urldefense.proofpoint.com/v2/url?u=https-3A__sourceware.org_pipermail_gdb-2Dpatches_2026-2DOctober_231148.html&d=DwIBAg&c=BSDicqBQBDjDI9RkVyTcHQ&r=f-oUQ8ByG1nZ71OI9p76qywCPh7mxzU69hBYnkP9Nis&m=ZqvNQdHjpMR8NN0gN2DAY-Qg76biG9X9nreFY45JXKG87ov0rUCcoCBwwm5e-m0d&s=mhF7tPz7DruvE3dGutyrsOFzFxdxwhNnTl7BB8s8a40&e=
>> Please see the stack in the mailing list link above I shared with
>> Simon. It has the backtrace plus core dump backtrace stack.
>Ok. It's kind of hard to read that message for me (there's no
>line-wrapping in the web browser); but I tend to think the bug is in
>wchar_iterator. I think it shouldn't be possible for it to read too
>much, or for m_bytes to wrap.
Thanks for the review. You were right that the bug is in wchar_iterator; the backtrace confirms it. On 64-bit AIX, wchar_t is 4 bytes wide, so the iterator is constructed with m_width = 4. When the target-wide charset is UTF-16, set_be_le_names resolves it to UTF-16BE, which uses 2-byte code units. In this case, iconv returns EILSEQ after consuming only 2 bytes, but the existing code still does:
m_input += m_width; /* advances by 4 */
m_bytes -= m_width; /* m_bytes was 4, wraps to a huge size_t */
The subsequent while (m_bytes > 0) loop then continues past the end of the buffer, eventually corrupting the stack and crashing inside libiconv's qsort. I will send a v3 that addresses this issue directly.
Regards,
Aditya.
[-- Attachment #2: Type: text/html, Size: 5981 bytes --]
^ 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