From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from simark.ca by simark.ca with LMTP id eTqROVCJ4GqfES8AWB0awg (envelope-from ) for ; Tue, 27 Oct 2026 07:21:52 -0400 Authentication-Results: simark.ca; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20251104 header.b=MsZj4aEd; dkim-atps=neutral Received: by simark.ca (Postfix, from userid 112) id E5AB4378003; Tue, 27 Oct 2026 07:21:52 -0400 (EDT) X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-25) on simark.ca X-Spam-Level: X-Spam-Status: No, score=-5.4 required=5.0 tests=ARC_SIGNED,ARC_VALID,BAYES_00, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED autolearn=unavailable autolearn_force=no version=4.0.1 Received: from vm01.sourceware.org (vm01.sourceware.org [38.145.34.32]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature ECDSA (prime256v1) server-digest SHA256) (No client certificate requested) by simark.ca (Postfix) with ESMTPS id 136DC378002 for ; Tue, 27 Oct 2026 07:21:52 -0400 (EDT) Received: from vm01.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 4ED694BA23F4 for ; Tue, 27 Oct 2026 11:21:51 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 4ED694BA23F4 Authentication-Results: sourceware.org; dkim=pass (2048-bit key, unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20251104 header.b=MsZj4aEd Received: from mail-pl1-x62b.google.com (mail-pl1-x62b.google.com [IPv6:2607:f8b0:4864:20::62b]) by sourceware.org (Postfix) with ESMTPS id 2BF024BA2E06 for ; Tue, 27 Oct 2026 11:21:24 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 2BF024BA2E06 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=gmail.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 2BF024BA2E06 Authentication-Results: sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::62b ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1793100084; cv=none; b=KHMoO4iGerTXcOr0dHX5xcNs9BidpFeOl/zF9QMfEKNAqrvVzzr1CvQryrnMNb68dntV71O4qeFBX3Chlus7qKpD6oz2J3DTnyOryf0lPne3+MpP1GRwtGf8siSfAytA7KuNlNpBzKsTw9k2451cgdPlZuGnjtoVzY9UswRIr3A= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1793100084; c=relaxed/simple; bh=2fU0elaDMjWp/vMnvHbZ+867jgLmQuIzRIXxmjzvedk=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=g5n7vkI8HwC1D/RwJhX0AA/nsDS+cpnDi47nCca5bfj4L2sHLel8TWuAuCTRvtHVL3nh97BpEdVsLEqtmtZPs+2KMY8IR1t1HkC/iwuiniZONHENjwPvU3dv5EPDTRQeMBxIVwMQ1yWlONqZLKzH48LiYYOCN6kjuJR4eIAMC6U= ARC-Authentication-Results: i=1; sourceware.org; dkim=pass (2048-bit key, unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20251104 header.b=MsZj4aEd DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 2BF024BA2E06 Received: by mail-pl1-x62b.google.com with SMTP id d9443c01a7336-2e5fb79ce82so25560245ad.0 for ; Tue, 27 Oct 2026 04:21:24 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1793100083; x=1793704883; darn=sourceware.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to:content-type; bh=CQwhRE09+JOOZdXeSltvhNEZBdaXgT3dzTHG6kMwdI8=; b=MsZj4aEdlNoP5xacb4V62BAuv4JdkgB4L6S/eWpuW2E7y4pG7PnifAJjnCXm8ONASc 4Cadr1fes8dsC6TBGJajZvI/DpX5EGw3xzzf2kW01iCNwgbSczivEPiIkrZf9KgShmbD dU/KL6CFMd+r2RH/72nqGSnWpXnbVxRSD8pKt9ASKkJzPBd2gcYhY1nSVoR0p64K++Ec fD/kxoTASOz+hy+AzWXwSn99M8YCuhrFTLdTWDP9p2L8imqTJd1JtXo2UV47+DVpDWCn m3SFsjccDCcsJdkyO/t1MUquJcB6uRkDsKVBKJJUPA1hW7qU6rH/AEYzMBQr0a4d5+uk aeXA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1793100083; x=1793704883; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to:content-type; bh=CQwhRE09+JOOZdXeSltvhNEZBdaXgT3dzTHG6kMwdI8=; b=Y3FeQEGX8bf7s9ZXH18iOWDXhylruVVUIldnG97+vDuNOAlPtXAUvsNrAP7jalgDDS AfhWZc4CBsg+YDBQPnfZF1BWmMHXbGJdFhoUGDzBqDaY3cWui3W00A5pqpm27SAsgAE+ fsPm1XfiIv46HNysc3+Zm5LtGtizBGQbUx4998h+PojKFTgR1HU+v7SWmm9q2mJSXXtZ t1KBWcirBuNWvY8MLSYr5b0fGH3WWvxKLx84dhhglbgl47kkyhcdsWJALdJAgvJWRKUc 0ey62tedlbuat4XdGS+lsdpE/KJPohMGTK49yp2T9WsXh8uCK++a+ZeOPUX1SfPwT4FV /DbA== X-Gm-Message-State: AFq9FYLgLyDaKn+kS0Nw5eeaRMPna6iyW0QpWoFJM4F5poWmuwCjGI9J 2wBLc34qhCMHFvR58hvt7ZFP1zao9PXPJOciuqtEhPoVi6k703bSKH7+ X-Gm-Gg: AYBFou0ZrBUMpWQICcTQ50Nn7kcv9dvzKxXbdujOiLLl0u0sgEeRvHoKE/iztWZguQ3 rm218lclS2578Y3UgeiNhm2Yof0cuINLKcW+goexjQfETcFWfaM2slSlnSkT6KN5/SkybdEE3le ikpGibaHYIoTTJ2Rd3LCoCcNvKxkA6H1nYKZ1eeUWcjXRFC8sQs63LDPCbNfHhagfrlrAImlbND YbioDkCNr/ArG2tkRO9I1Q8f+Hoks7LiIFEzMyZsVnZeISDEtG1DeFU/y7t3jZ5skJWlb42eu0k 56qh53h0gezMCX2+s1V6x967jR1DjqoY2YZM8JfOazxFEdv3pf6/sDf3Kh/kiTVXShoULAmalwH 8C6UkNaMUOaJpq9u22Qch4535A9Nyx4DTGRt0zBDUu9f4W57v9S+EorncDXWKwVhct9YnXR9PRr Kd5mhNwWMJHxxWFjyfA4rXJ4jxQZ5U3pEFuN+HMCZIpRpSoZsh4D1J5b6YlbZQUqqFCDr06M/7O mRFGuEnW6W9sd4W0cmZj0ECpBFIACoHHvDCJWAhAOnO2eqHFz7HpTtB2aUt4WuO3D+IReKQ/m8W StCZOcOC0kp9o5cMQlM= X-Received: by 2002:a17:90b:2e0e:b0:3a0:c85a:ee02 with SMTP id 98e67ed59e1d1-3adead2f2a2mr7741344a91.17.1793100083015; Tue, 27 Oct 2026 04:21:23 -0700 (PDT) Received: from dhcp-9-123-0-222.bl1-in.ibm.com ([129.41.58.6]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-3ae404274b2sm3477457a91.5.2026.10.27.04.21.20 (version=TLS1_3 cipher=TLS_CHACHA20_POLY1305_SHA256 bits=256/256); Tue, 27 Oct 2026 04:21:22 -0700 (PDT) From: Aditya Vidyadhar Kamath To: ulrich.weigand@de.ibm.com, simon.marchi@polymtl.ca, tom@tromey.com Cc: gdb-patches@sourceware.org, Aditya.Kamath1@ibm.com, sangamesh.swamy@in.ibm.com, Aditya Vidyadhar Kamath Subject: [PATCH v3] Fix crash when target-wide-charset doesn't match wchar_t size Date: Tue, 27 Oct 2026 16:51:14 +0530 Message-ID: <20261027112114.73988-1-akamath996@gmail.com> X-Mailer: git-send-email 2.43.0 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gdb-patches-bounces~public-inbox=simark.ca@sourceware.org From: Aditya Vidyadhar Kamath Tom asked [1] whether setting target-wide-charset to an encoding with the wrong unit size can crash GDB. It can. 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 ----- On 64-bit AIX wchar_t is 4 bytes wide. Setting target-wide-charset to UTF-16 causes wchar_iterator::iterate() to be constructed with m_width=4 but a 2-byte-per-unit charset. On the EILSEQ path, iconv consumes only 2 bytes before returning, and then: m_input += m_width; /* advances by 4 */ m_bytes -= m_width; /* m_bytes was 4, wraps to a huge size_t */ The loop races past the end of the buffer, corrupting the stack and crashing inside libiconv. Two fixes: 1. validate() now checks the unit width implied by the charset name against wchar_bit and rejects the setting with a clear error. The previous good value is restored on failure since the setshow framework stores the new value before calling the sfunc. 2. wchar_iterator::iterate() guards the EILSEQ path: if m_bytes < m_width, clamp m_bytes to zero instead of subtracting, so the loop terminates cleanly regardless of how the iterator was constructed. 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. Tested on powerpc64-ibm-aix7.2.0.0 with 32-bit and 64-bit inferiors. [1]: https://sourceware.org/pipermail/gdb-patches/2026-October/231110.html --- gdb/charset.c | 68 ++++++++++++++++++++++++++++++-- gdb/testsuite/gdb.base/wchar.exp | 34 ++++++++++++++++ 2 files changed, 99 insertions(+), 3 deletions(-) diff --git a/gdb/charset.c b/gdb/charset.c index 1b0725b5078..327e4f4cf91 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. */ @@ -646,8 +695,21 @@ wchar_iterator::iterate (enum wchar_iterate_result *out_result, *out_result = wchar_iterate_invalid; *ptr = m_input; *len = m_width; - m_input += m_width; - m_bytes -= m_width; + /* Guard against unsigned wrap: m_bytes < m_width can happen + when the charset unit size doesn't match m_width (e.g. a + UTF-16 charset used with a 4-byte wchar_t). Clamp to zero + rather than letting m_bytes underflow to a huge value and + sending the loop past the end of the buffer. */ + if (m_bytes >= m_width) + { + m_input += m_width; + m_bytes -= m_width; + } + else + { + m_input += m_bytes; + m_bytes = 0; + } return 0; case E2BIG: diff --git a/gdb/testsuite/gdb.base/wchar.exp b/gdb/testsuite/gdb.base/wchar.exp index b02f4a78336..801aeb9ee20 100644 --- a/gdb/testsuite/gdb.base/wchar.exp +++ b/gdb/testsuite/gdb.base/wchar.exp @@ -75,3 +75,37 @@ 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. +# Derive good/bad charsets from the inferior's actual wchar_t size so the +# test is correct for both 32-bit (2-byte wchar_t -> UTF-16) and 64-bit +# (4-byte wchar_t -> UTF-32) targets. +set wchar_bytes 0 +gdb_test_multiple "print sizeof(wchar_t)" "" { + -re " = 2.*$gdb_prompt $" { set wchar_bytes 2 } + -re " = 4.*$gdb_prompt $" { set wchar_bytes 4 } +} +if { $wchar_bytes == 2 } { + set good_cs UTF-16 + set bad_cs UTF-32 +} elseif { $wchar_bytes == 4 } { + set 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