From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from simark.ca by simark.ca with LMTP id 2dA2DKTM0GqyQREAWB0awg (envelope-from ) for ; Thu, 15 Oct 2026 08:52:52 -0400 Authentication-Results: simark.ca; dkim=pass (2048-bit key; unprotected) header.d=polymtl.ca header.i=@polymtl.ca header.a=rsa-sha256 header.s=oct2025 header.b=AYrfj9Rc; dkim-atps=neutral Received: by simark.ca (Postfix, from userid 112) id 2A9381E050; Thu, 15 Oct 2026 08:52: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=-2.4 required=5.0 tests=ARC_SIGNED,ARC_VALID,BAYES_00, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED,RCVD_IN_VALIDITY_CERTIFIED_BLOCKED, RCVD_IN_VALIDITY_RPBL_BLOCKED,RCVD_IN_VALIDITY_SAFE_BLOCKED autolearn=ham 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 ACC201E04E for ; Thu, 15 Oct 2026 08:52:50 -0400 (EDT) Received: from vm01.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 2A07B4BA2E22 for ; Thu, 15 Oct 2026 12:52:50 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 2A07B4BA2E22 Authentication-Results: sourceware.org; dkim=pass (2048-bit key, unprotected) header.d=polymtl.ca header.i=@polymtl.ca header.a=rsa-sha256 header.s=oct2025 header.b=AYrfj9Rc Received: from smtp.polymtl.ca (smtp.polymtl.ca [132.207.4.11]) by sourceware.org (Postfix) with ESMTPS id A2FAB4BA23DD for ; Thu, 15 Oct 2026 12:52:24 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org A2FAB4BA23DD Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=polymtl.ca Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=polymtl.ca ARC-Filter: OpenARC Filter v1.0.0 sourceware.org A2FAB4BA23DD Authentication-Results: sourceware.org; arc=none smtp.remote-ip=132.207.4.11 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1792068744; cv=none; b=jlG9yZRLZ54+vFQNPIcEfeEXLl5ip7tJ1X3vsQssFx/xfkWZMVzV4fVQI4kDRV838+xIBv7Jk060JDHkZ1jPZ7BuTkYBGr0VcCkzi7MKnGIJvwXTwu7e2hU4fWEARvOFFWonVQB4VahIEFMdyJ//1pmnoJ/81WKHeHFWeySbUQM= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1792068744; c=relaxed/simple; bh=nDpADJ5SkHWlXbR7YKBA2hZeUsyjt9M05bUAwbJ4EzM=; h=DKIM-Signature:Message-ID:Date:MIME-Version:Subject:To:From; b=QBR1ShkgFVeLT4KBdXdEpCmBzehtzjLPsIV+ckIu17/jjXDWIITZdu3ARL1Qh5wVRr4HKphPwAWhMErDmoBZupSewNT0IxaVAEU8rG8DCb4Lozm0Q555j/dg3ByHoS9p1falx3IZuNgUsqwaiiCnf1mH7POA+uUh1Pn+P9T1Nzk= ARC-Authentication-Results: i=1; sourceware.org; dkim=pass (2048-bit key, unprotected) header.d=polymtl.ca header.i=@polymtl.ca header.a=rsa-sha256 header.s=oct2025 header.b=AYrfj9Rc DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org A2FAB4BA23DD Received: from simark.ca (simark.ca [158.69.221.121]) (authenticated bits=0) by smtp.polymtl.ca (8.14.7/8.14.7) with ESMTP id 69FCqFLI051224 (version=TLSv1/SSLv3 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 15 Oct 2026 08:52:20 -0400 DKIM-Filter: OpenDKIM Filter v2.11.0 smtp.polymtl.ca 69FCqFLI051224 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=polymtl.ca; s=oct2025; t=1792068741; bh=rI9Z85aptcJPVxpDBn3jRMTjFyCL7t/bXtL8V97aeRk=; h=Date:Subject:To:From:In-Reply-To:From; b=AYrfj9RcapDPHXZ+36DPzyYPyPFShfhm/CgFTAT5H+ECHjBId/lLkN2Tx6LDsX3ft +ccqm5/k69jW7AHAcvjEmFrb9OmYRxRLVrfkTd07ojrGW/zaVwnA4xuj+RUIrHXXYH FJWD3YY6irH1uS0cdFAShiNhN/niuocxEyYnUrY0I8uExX/wwjVd3ybbMIyq9QEJIt eND+9VTGhFzEIjBgdiP3mbJHWzTCAf/6sPYEf8j6NhSjQmvnAb7RmnQtWGFvbZzm7M zVD0BqzZepNzQYkoTDviMOYSBS5xw13KZKChTMwFsbOZrZsdVxxRMCojokRn80WDBR 0l33OkqaRuU5A== Received: by simark.ca (Postfix) id 07BAC1E04E; Thu, 15 Oct 2026 08:52:14 -0400 (EDT) Message-ID: <88a45684-9c70-46ce-b152-424528d2d98f@polymtl.ca> Date: Thu, 15 Oct 2026 08:52:13 -0400 MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: Re: [PATCH] gdb: fix out-of-bounds read when printing a pointer with a format To: Andrew Burgess , gdb-patches@sourceware.org References: <20261005024658.927684-1-simon.marchi@polymtl.ca> <87zewf8css.fsf@redhat.com> Content-Language: fr From: Simon Marchi In-Reply-To: <87zewf8css.fsf@redhat.com> Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 7bit X-Poly-FromMTA: (simark.ca [158.69.221.121]) at Thu, 15 Oct 2026 12:52:15 +0000 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 On 10/15/26 6:42 AM, Andrew Burgess wrote: > simon.marchi@polymtl.ca writes: > >> From: Simon Marchi >> >> I stumbled on this while investigating bug 34638 ("Multi-register-reading >> oddity / anachronism"), but this patch is not otherwise related to that >> bug. >> >> When the value being printed is a pointer, print_scalar_formatted >> overrides the number of bytes it reads from the value buffer: >> >> if (type->code () == TYPE_CODE_PTR) >> len = gdbarch_addr_bit (gdbarch) / TARGET_CHAR_BIT; >> >> VALADDR only holds type->length() bytes though, and for a pointer type >> built by GDB that is `gdbarch_ptr_bit / TARGET_CHAR_BIT` bytes. On targets >> where gdbarch_addr_bit is larger than gdbarch_ptr_bit, we therefore read >> past the end of the buffer. >> >> AVR is such a target: gdbarch_ptr_bit is 16 while gdbarch_addr_bit is 32, >> so printing any pointer with a format reads 4 bytes out of a 2-byte buffer. >> With a GDB built with AddressSanitizer: >> >> (gdb) p/x $sp >> ================================================================= >> ==433709==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x7c11d1239e33 at pc 0x55eb8e8438f0 bp 0x7ffc17c69050 sp 0x7ffc17c69040 >> >> It can be reproduced without running a program, simply with a GDB that has >> AVR support, by forcing the architecture to be AVR: >> >> (gdb) set architecture avr >> The target architecture is set to "avr". >> (gdb) p/x (void *) 0x1234 >> ================================================================= >> ==434356==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x7bbca0e21293 at pc 0x55f5d74d08f0 bp 0x7ffe74cba960 sp 0x7ffe74cba950 >> >> "info registers SP" on an AVR target goes through the same path, so hits >> the same crash: >> >> (gdb) c >> Continuing. >> >> Breakpoint 1, main () at test.c:16 >> 16 int local = 42; >> (gdb) info registers SP >> ================================================================= >> ==432390==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x7b764403b413 at pc 0x55e8ef8628f0 bp 0x7fff13994110 sp 0x7fff13994100 >> >> The override comes with this comment: >> >> /* If the value is a pointer, and pointers and addresses are not the >> same, then at this point, the value's length (in target bytes) is >> gdbarch_addr_bit/TARGET_CHAR_BIT, not type->length (). */ >> >> This was true when the override was introduced, in commit ef166cf46a1b >> (2001). At the time, print_scalar_formatted started by converting the >> value to a LONGEST: >> >> val_long = unpack_long (type, valaddr); >> >> For pointers, unpack_long goes through extract_typed_address, then >> gdbarch_pointer_to_address, which converts the pointer to a CORE_ADDR >> gdbarch_addr_bit wide. On AVR, for instance, data pointer 0x1234 (2 bytes >> long) becomes address 0x801234 (4 bytes long). "The value" in the comment >> refers to this VAL_LONG, not to the bytes at VALADDR. LEN was then only >> used to mask VAL_LONG, and the override made sure that the mask did not >> truncate the converted address to gdbarch_ptr_bit bits. VALADDR (2 bytes) >> was never read using LEN (4 bytes), so there was no out-of-bounds read. >> >> Commit d9109c8080ac ("Simplify print_scalar_formatted", 2017) changed the >> function to print the value using the print_*_chars functions, which >> operate directly on the bytes at VALADDR, and removed the conversion to >> LONGEST. From then on, the value printed became the raw pointer >> representation, type->length() bytes long (2 bytes), not the converted >> address (4 bytes). The length override was left in place, and this is >> when the out-of-bounds read was introduced. >> >> Note that commit d9109c8080ac therefore changed how `print (void *) 0x1234` >> is printed for architectures like AVR, it went from >> >> $1 = 0x801234 >> >> to just >> >> $1 = 0x1234 >> >> I don't think it's a mistake in itself, but I am not sure it was fully >> understood at the time. >> >> Since the LEN override no longer has a reason to be, remove it. >> >> With LEN now always equal to type->length(), the following block becomes >> dead code, so remove it. The comment above it is also a relic of the >> VAL_LONG time. >> >> I started by adding a very simple test to >> gdb.base/all-architectures.exp.tcl to try to print a formatted pointer with >> each arch. I then thought it would be useful to test printing a pointer >> without formatting, and then the various kinds of pointers (data vs code). >> The result is the somewhat complicated procedure in this patch. It did not >> find additional bugs, but I think it's still useful to have in the >> testsuite, as it captures what GDB does today. If a change in the pointer >> printing code ever changes (notably in the address <-> pointer conversion), >> we will notice it. > > LGTM. > > Approved-By: Andrew Burgess Thanks, pushed. Simon