From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from simark.ca by simark.ca with LMTP id MfDmAo0tRWpLRiEAWB0awg (envelope-from ) for ; Wed, 01 Jul 2026 11:09:01 -0400 Authentication-Results: simark.ca; dkim=pass (1024-bit key; unprotected) header.d=amd.com header.i=@amd.com header.a=rsa-sha256 header.s=selector1 header.b=aKglbJua; dkim-atps=neutral Received: by simark.ca (Postfix, from userid 112) id E755B1E098; Wed, 01 Jul 2026 11:09:00 -0400 (EDT) X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-25) on simark.ca X-Spam-Level: X-Spam-Status: No, score=-6.4 required=5.0 tests=ARC_SIGNED,ARC_VALID,BAYES_00, DKIMWL_WL_HIGH,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED 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 94F9F1E024 for ; Wed, 01 Jul 2026 11:08:59 -0400 (EDT) Received: from vm01.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id B1CAB4BA2E36 for ; Wed, 1 Jul 2026 15:08:58 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org B1CAB4BA2E36 Authentication-Results: sourceware.org; dkim=pass (1024-bit key, unprotected) header.d=amd.com header.i=@amd.com header.a=rsa-sha256 header.s=selector1 header.b=aKglbJua Received: from BL0PR03CU003.outbound.protection.outlook.com (mail-eastusazlp170120007.outbound.protection.outlook.com [IPv6:2a01:111:f403:c101::7]) by sourceware.org (Postfix) with ESMTPS id CE0B84BA5436 for ; Wed, 1 Jul 2026 15:08:30 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org CE0B84BA5436 Authentication-Results: sourceware.org; dmarc=pass (p=quarantine dis=none) header.from=amd.com Authentication-Results: sourceware.org; spf=fail smtp.mailfrom=amd.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org CE0B84BA5436 Authentication-Results: sourceware.org; arc=pass smtp.remote-ip=2a01:111:f403:c101::7 ARC-Seal: i=2; a=rsa-sha256; d=sourceware.org; s=key; t=1782918510; cv=pass; b=WHyLhm/mdqBXC8HFAsGesYLqSb8TnhKFJoOyVvIFLP+PaMn7jQwXITs4tiBrvUopi4BZH7FDGdZw9rlKQbOB2rxsH8BXj2UYCiyw3fgNvtfT7Mlf9IB7c3wrdQEj819XvbP0ZWnomqf+HVzh5oJ4bujfw3si3BavB0PzzcWuq5o= ARC-Message-Signature: i=2; a=rsa-sha256; d=sourceware.org; s=key; t=1782918510; c=relaxed/simple; bh=gQVB9zeJuaFekBLD5H1IHRun1J76Ucs7dslsWoAO4Z4=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=tynJ41tt7o4lVxGYYPzK51/rxH9bQcDkFqKQK+tnFAK0pHlC0KsOKzyWtCErb/GtbcfimWeWnA3X6wTzuS9BWtwzi/PH/CA8RnI+JX2rmZWRXtApeNzwzWijlbLOy4AW1zHDYNLRNpBt9zMAwtf+t8sJBoi4zW7n+nJi+fNEI9o= ARC-Authentication-Results: i=2; sourceware.org; dkim=pass (1024-bit key, unprotected) header.d=amd.com header.i=@amd.com header.a=rsa-sha256 header.s=selector1 header.b=aKglbJua DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org CE0B84BA5436 ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=t5QaQBEbxuklgBB7EL8B1Mo+7y5j5HfOnvSMoPTaZwWL8+JEZVXi8Rtgvz3xnOwnAXGa+i4CgpZIuZ71Nrip9/Mq/KxR5RyxgUoBX+bJu6bvIgYVRb6QKglobjaFuoO3XrdmfxhCwfldvhyx/dKxPzGEQqPxyXgykDZUdlrtepUuZ5NUJ62n1TSyn4ZPQhUCti0cKWQpL1afBcve6rZad+ez3kEm4og3U2ZfD0CCKIS0vn5nCtLxhIkGCEGxfGx42K17qpFma8mXdf2KKJwEk7o4plVylqzedEG4gHRH2Wr7qmgeG04OKwVSyqSq+8QtpCk32EVVEeJfOnEBYWSj/Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=Bm2+9tGPrrN/Vr6ExHJOmwaClg/PVoZIspypdabWEmg=; b=Ntw/cvTuTsKaBt+tKph0oxYpDTOndhhx/2TZfEdEkFJt29uSjuR3u8KDegZL+1Ti8UFOnODsWjfakufJ6UGmnIy8fh6YqFmjzfzljNlJHcNxy6pBUGLb5G2ij50Z68cgHAi5lKOxPdw8bOncPz8oj2A9abBBIFc91w0AOczFTTPorGqf6nxls+BEywDB8bhKKE4FsapfOoknPW/22SuEoVYoutqQJZ1qsfIIsWPtV7u58du9JTSsuYm5/yPz9C/Nd7TdhoNapKYjeO4JtdMwaGB0WG60WxWMePzfhttqQwtyJPQEOmmMeJbIdHGM3iioOyaVuc2VsRxYo70M3jv7cQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 165.204.84.17) smtp.rcpttodomain=sourceware.org smtp.mailfrom=amd.com; dmarc=pass (p=quarantine sp=quarantine pct=100) action=none header.from=amd.com; dkim=none (message not signed); arc=none (0) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amd.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=Bm2+9tGPrrN/Vr6ExHJOmwaClg/PVoZIspypdabWEmg=; b=aKglbJuaky3C63eYLT30spzIGICuU9/n7gHwXDjwJMW2Blz5SVewBTPaHXj0V9U7UayWq6BJkqPdsvPGsASLwndHNWGmhvOiZBM6riEReZ8opWT73p1GTmu9bPMn1nMucqv8f3rr8S+V9CzRDJMdBYaR1jm1zT70i6TzusGEmG4= Received: from SA0PR11CA0145.namprd11.prod.outlook.com (2603:10b6:806:131::30) by CYXPR12MB9278.namprd12.prod.outlook.com (2603:10b6:930:e5::11) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.21.181.8; Wed, 1 Jul 2026 15:08:28 +0000 Received: from SA2PEPF00003F62.namprd04.prod.outlook.com (2603:10b6:806:131:cafe::72) by SA0PR11CA0145.outlook.office365.com (2603:10b6:806:131::30) with Microsoft SMTP Server (version=TLS1_3, cipher=TLS_AES_256_GCM_SHA384) id 15.21.181.9 via Frontend Transport; Wed, 1 Jul 2026 15:08:26 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 165.204.84.17) smtp.mailfrom=amd.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=amd.com; Received-SPF: Pass (protection.outlook.com: domain of amd.com designates 165.204.84.17 as permitted sender) receiver=protection.outlook.com; client-ip=165.204.84.17; helo=satlexmb07.amd.com; pr=C Received: from satlexmb07.amd.com (165.204.84.17) by SA2PEPF00003F62.mail.protection.outlook.com (10.167.248.37) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.21.181.6 via Frontend Transport; Wed, 1 Jul 2026 15:08:25 +0000 Received: from ctr-rack32-mi300x-1.amd.com (10.180.168.240) by satlexmb07.amd.com (10.181.42.216) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.41; Wed, 1 Jul 2026 10:07:25 -0500 From: Luis Machado To: CC: , Subject: [PATCH v2] gdb: replace alloca with gdb::unique_xmalloc_ptr in remote-fileio.c Date: Wed, 1 Jul 2026 10:07:14 -0500 Message-ID: <20260701150714.3124191-1-luis.machado@amd.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260630095238.1700797-1-luis.machado@amd.com> References: <20260630095238.1700797-1-luis.machado@amd.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Content-Type: text/plain X-Originating-IP: [10.180.168.240] X-ClientProxiedBy: satlexmb08.amd.com (10.181.42.217) To satlexmb07.amd.com (10.181.42.216) X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: SA2PEPF00003F62:EE_|CYXPR12MB9278:EE_ X-MS-Office365-Filtering-Correlation-Id: a9956e87-bc60-4824-8c16-08ded782997b X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; ARA:13230040|23010399003|82310400026|1800799024|376014|36860700016|22082099003|18002099003|11063799006|56012099006|5023799004; X-Microsoft-Antispam-Message-Info: jtzd4wduDn5hZebgQbstnlAZMJUwvraJ8uVuiPQYyZtNCDk9E1tnKtRCWBVFS7fZtUCH94irRn+PC3IO4cZnV23i3wYNIhrg+6uwhHReCJOQ+y2z39aXmFJgxBCuruZXGAt/IkTHDmxPHZjjZ+B+IdrUMbEwQPzowGZtl6qc5S1DiqbfQwjjrWeufwLtKTZ5FXXZLD1oNQ9hj3Ur1D8pQQiO0ysZH0jvfn9t2CB47I3GLIs+iEDDJC+b+kKv7ihYhFL+SJAuY5HdYQZrdTcsnTZraErhu0Aafw+XgP7/KCBGElffceYDK6MZOhl4KyZA+zpb6jogUWR/5Ad6XVklzJJ6OUpb/oD5k7oZoHotOw/QaqnydX0BP7jnPoYOnxD7NrIcIbR+D41YJpLm5dTok1sAZepS/YP0fkG3rfWdd18zJK43/bgyWn89a2yieVlwt8MMY0+3ZhVj9zYrW65FKRQIMqEaAQpnea7TRX3ElhVQICrXH+EYCET2dj7Bp65YhW15ZzckIGQDkCnvTzITDkEtYT4/yn8pnbibVwfIP3PJ+p70uVsfiGnIcbhdHF6FEFNyRZACbdpA6o1tshYzC3b6++lfXdG9f2bcFFJRSQbcmTiFD4+SfKBmn3VVl8ssr6J/gAC/rS+9kYvJBC+MEJUbrxwQJBYwOEtnI+BQZMuOKzBFz4bpUtWdw3PAptJvzy6zOXkOSE9ikOMUoSm6mw== X-Forefront-Antispam-Report: CIP:165.204.84.17; CTRY:US; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:satlexmb07.amd.com; PTR:InfoDomainNonexistent; CAT:NONE; SFS:(13230040)(23010399003)(82310400026)(1800799024)(376014)(36860700016)(22082099003)(18002099003)(11063799006)(56012099006)(5023799004); DIR:OUT; SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: BcUBRlwGluGV3zMBGeEbeCBUuBweVzJ0PaEzt2xzRGLiw9t732Yjw08oD6bJXmn96BMh5l5we0e38kTEjy8yG3siv8WTnN8pet+Yw5oTIMfm7IqfnsFVbXbCIlZpJiVuqo9fQ63eNmlWkZhl7DQ3kyxNjx5THmvlUrXLdrdqI86zlS32i0/iEoFptFP0HpYlggLm8Fqa6+fgPUlDme0QuC8OeQfd4RFsJFNF7ZLC93lTsWHZkqJuM9KVWNo1kp4NNXzB3Pj8vFO3h5x6obOKJIsqUijWmVjDQ8CPC2shl2eyVGPRuEsMIHU/DO79lXoyPIiZQpVTkM8yQ9KbPn84Ldx0I/vSo52o9NrVv/djUz36qzjeXnnTHK99eNIFe2tLSKMAbhsRBy5kQELgSOQ8RP5+2Z37o51DMxKZslugeomPGR3/eg/n64lE0lTRhLLv X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 01 Jul 2026 15:08:25.3505 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: a9956e87-bc60-4824-8c16-08ded782997b X-MS-Exchange-CrossTenant-Id: 3dd8961f-e488-4e60-8e11-a82d994e183d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=3dd8961f-e488-4e60-8e11-a82d994e183d; Ip=[165.204.84.17]; Helo=[satlexmb07.amd.com] X-MS-Exchange-CrossTenant-AuthSource: SA2PEPF00003F62.namprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: CYXPR12MB9278 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 remote_fileio_extract_ptr_w_len parsed a debuggee controlled 64 bit length, narrowed it to int with no bounds check, and the value flowed directly into alloca() across RSP File I/O handlers (Fopen, Frename, Funlink, Fstat, Fsystem). A malicious inferior or remote stub could send a crafted packet with a large path length, displacing the stack pointer by up to 2 GiB and potentially crashing the debugger. remote_fileio_extract_ptr_w_len now rejects negative lengths and zero. An allow_zero_length flag lets the Fsystem handler opt in to the zero length sentinel that signals a NULL cmdline query. All other handlers use the default and are protected without any per call checks. Oversized names are rejected naturally by the underlying syscall with ENAMETOOLONG. All alloca(length) calls have been replaced with gdb::unique_xmalloc_ptr, so an oversized but positive length now fails as a graceful heap allocation error rather than corrupting the stack. Add a selftest that exercises various problematic cases. Signed-off-by: Luis Machado --- gdb/remote-fileio.c | 139 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 108 insertions(+), 31 deletions(-) diff --git a/gdb/remote-fileio.c b/gdb/remote-fileio.c index ef608cabfab..24d9e1545f9 100644 --- a/gdb/remote-fileio.c +++ b/gdb/remote-fileio.c @@ -31,6 +31,7 @@ #include "target.h" #include "filenames.h" #include "gdbsupport/filestuff.h" +#include "gdbsupport/selftest.h" #include #include "gdbsupport/gdb_sys_time.h" @@ -194,7 +195,8 @@ remote_fileio_extract_int (char **buf, long *retint) } static int -remote_fileio_extract_ptr_w_len (char **buf, CORE_ADDR *ptrval, int *length) +remote_fileio_extract_ptr_w_len (char **buf, CORE_ADDR *ptrval, int *length, + bool allow_zero_length = false) { char *c; LONGEST retlong; @@ -211,6 +213,11 @@ remote_fileio_extract_ptr_w_len (char **buf, CORE_ADDR *ptrval, int *length) *buf = c; if (remote_fileio_extract_long (buf, &retlong)) return -1; + /* Reject negative lengths and zero (unless the caller permits it for the + Fsystem NULL-cmdline sentinel). Oversized names are caught by the + syscall. */ + if (retlong < 0 || (!allow_zero_length && retlong == 0)) + return -1; *length = (int) retlong; return 0; } @@ -305,7 +312,6 @@ remote_fileio_func_open (remote_target *remote, char *buf) long num; int flags, fd; mode_t mode; - char *pathname; struct stat st; /* 1. Parameter: Ptr to pathname / length incl. trailing zero. */ @@ -339,8 +345,8 @@ remote_fileio_func_open (remote_target *remote, char *buf) } /* Request pathname. */ - pathname = (char *) alloca (length); - if (target_read_memory (ptrval, (gdb_byte *) pathname, length) != 0) + gdb::unique_xmalloc_ptr pathname ((char *) xmalloc (length)); + if (target_read_memory (ptrval, (gdb_byte *) pathname.get (), length) != 0) { remote_fileio_ioerror (remote); return; @@ -349,7 +355,7 @@ remote_fileio_func_open (remote_target *remote, char *buf) /* Check if pathname exists and is not a regular file or directory. If so, return an appropriate error code. Same for trying to open directories for writing. */ - if (!stat (pathname, &st)) + if (!stat (pathname.get (), &st)) { if (!S_ISREG (st.st_mode) && !S_ISDIR (st.st_mode)) { @@ -364,7 +370,7 @@ remote_fileio_func_open (remote_target *remote, char *buf) } } - fd = gdb_open_cloexec (pathname, flags, mode).release (); + fd = gdb_open_cloexec (pathname.get (), flags, mode).release (); if (fd < 0) { remote_fileio_return_errno (remote, -1); @@ -659,7 +665,6 @@ remote_fileio_func_rename (remote_target *remote, char *buf) { CORE_ADDR old_ptr, new_ptr; int old_len, new_len; - char *oldpath, *newpath; int ret, of, nf; struct stat ost, nst; @@ -678,24 +683,24 @@ remote_fileio_func_rename (remote_target *remote, char *buf) } /* Request oldpath using 'm' packet */ - oldpath = (char *) alloca (old_len); - if (target_read_memory (old_ptr, (gdb_byte *) oldpath, old_len) != 0) + gdb::unique_xmalloc_ptr oldpath ((char *) xmalloc (old_len)); + if (target_read_memory (old_ptr, (gdb_byte *) oldpath.get (), old_len) != 0) { remote_fileio_ioerror (remote); return; } /* Request newpath using 'm' packet */ - newpath = (char *) alloca (new_len); - if (target_read_memory (new_ptr, (gdb_byte *) newpath, new_len) != 0) + gdb::unique_xmalloc_ptr newpath ((char *) xmalloc (new_len)); + if (target_read_memory (new_ptr, (gdb_byte *) newpath.get (), new_len) != 0) { remote_fileio_ioerror (remote); return; } /* Only operate on regular files and directories. */ - of = stat (oldpath, &ost); - nf = stat (newpath, &nst); + of = stat (oldpath.get (), &ost); + nf = stat (newpath.get (), &nst); if ((!of && !S_ISREG (ost.st_mode) && !S_ISDIR (ost.st_mode)) || (!nf && !S_ISREG (nst.st_mode) && !S_ISDIR (nst.st_mode))) { @@ -703,7 +708,7 @@ remote_fileio_func_rename (remote_target *remote, char *buf) return; } - ret = rename (oldpath, newpath); + ret = rename (oldpath.get (), newpath.get ()); if (ret == -1) { @@ -726,10 +731,10 @@ remote_fileio_func_rename (remote_target *remote, char *buf) char newfullpath[PATH_MAX]; int len; - cygwin_conv_path (CCP_WIN_A_TO_POSIX, oldpath, oldfullpath, - PATH_MAX); - cygwin_conv_path (CCP_WIN_A_TO_POSIX, newpath, newfullpath, - PATH_MAX); + cygwin_conv_path (CCP_WIN_A_TO_POSIX, oldpath.get (), + oldfullpath, PATH_MAX); + cygwin_conv_path (CCP_WIN_A_TO_POSIX, newpath.get (), + newfullpath, PATH_MAX); len = strlen (oldfullpath); if (IS_DIR_SEPARATOR (newfullpath[len]) && !filename_ncmp (oldfullpath, newfullpath, len)) @@ -752,7 +757,6 @@ remote_fileio_func_unlink (remote_target *remote, char *buf) { CORE_ADDR ptrval; int length; - char *pathname; int ret; struct stat st; @@ -763,8 +767,8 @@ remote_fileio_func_unlink (remote_target *remote, char *buf) return; } /* Request pathname using 'm' packet */ - pathname = (char *) alloca (length); - if (target_read_memory (ptrval, (gdb_byte *) pathname, length) != 0) + gdb::unique_xmalloc_ptr pathname ((char *) xmalloc (length)); + if (target_read_memory (ptrval, (gdb_byte *) pathname.get (), length) != 0) { remote_fileio_ioerror (remote); return; @@ -772,13 +776,14 @@ remote_fileio_func_unlink (remote_target *remote, char *buf) /* Only operate on regular files (and directories, which allows to return the correct return code). */ - if (!stat (pathname, &st) && !S_ISREG (st.st_mode) && !S_ISDIR (st.st_mode)) + if (!stat (pathname.get (), &st) && !S_ISREG (st.st_mode) + && !S_ISDIR (st.st_mode)) { remote_fileio_reply (remote, -1, FILEIO_ENODEV); return; } - ret = unlink (pathname); + ret = unlink (pathname.get ()); if (ret == -1) remote_fileio_return_errno (remote, -1); @@ -791,7 +796,6 @@ remote_fileio_func_stat (remote_target *remote, char *buf) { CORE_ADDR statptr, nameptr; int ret, namelength; - char *pathname; LONGEST lnum; struct stat st; struct fio_stat fst; @@ -812,14 +816,15 @@ remote_fileio_func_stat (remote_target *remote, char *buf) statptr = (CORE_ADDR) lnum; /* Request pathname using 'm' packet */ - pathname = (char *) alloca (namelength); - if (target_read_memory (nameptr, (gdb_byte *) pathname, namelength) != 0) + gdb::unique_xmalloc_ptr pathname ((char *) xmalloc (namelength)); + if (target_read_memory (nameptr, (gdb_byte *) pathname.get (), + namelength) != 0) { remote_fileio_ioerror (remote); return; } - ret = stat (pathname, &st); + ret = stat (pathname.get (), &st); if (ret == -1) { @@ -997,24 +1002,28 @@ remote_fileio_func_system (remote_target *remote, char *buf) { CORE_ADDR ptrval; int ret, length; - char *cmdline = NULL; /* Parameter: Ptr to commandline / length incl. trailing zero */ - if (remote_fileio_extract_ptr_w_len (&buf, &ptrval, &length)) + if (remote_fileio_extract_ptr_w_len (&buf, &ptrval, &length, true)) { remote_fileio_ioerror (remote); return; } + gdb::unique_xmalloc_ptr cmdline_buf; + const char *cmdline = nullptr; + if (length) { /* Request commandline using 'm' packet */ - cmdline = (char *) alloca (length); - if (target_read_memory (ptrval, (gdb_byte *) cmdline, length) != 0) + cmdline_buf.reset ((char *) xmalloc (length)); + if (target_read_memory (ptrval, (gdb_byte *) cmdline_buf.get (), + length) != 0) { remote_fileio_ioerror (remote); return; } + cmdline = cmdline_buf.get (); } /* Check if system(3) has been explicitly allowed using the @@ -1244,6 +1253,70 @@ show_system_call_allowed (const char *args, int from_tty) remote_fio_system_call_allowed ? "" : "not "); } +#if GDB_SELF_TEST + +namespace selftests { + +/* Verify that remote_fileio_extract_ptr_w_len rejects negative and zero + lengths, and accepts valid ones. The packet buffer format is + "ptr/len[,...]" with both fields as hex integers. */ + +static void +test_remote_fileio_extract_ptr_w_len () +{ + CORE_ADDR ptrval; + int length; + + /* Build a writable "ptr/len" buffer and parse it, with and without + the Fsystem zero-length allowance. */ + auto parse = [&] (const char *s) -> int + { + std::string buf (s); + char *p = buf.data (); + return remote_fileio_extract_ptr_w_len (&p, &ptrval, &length); + }; + auto parse_allow_zero = [&] (const char *s) -> int + { + std::string buf (s); + char *p = buf.data (); + return remote_fileio_extract_ptr_w_len (&p, &ptrval, &length, true); + }; + + /* Valid: length 1 (minimum positive). Verify both fields are parsed. */ + SELF_CHECK (parse ("deadbeef/1") == 0); + SELF_CHECK (ptrval == 0xdeadbeef); + SELF_CHECK (length == 1); + + /* Valid: packet with trailing fields. */ + SELF_CHECK (parse ("deadbeef/4,0,1a4") == 0); + SELF_CHECK (ptrval == 0xdeadbeef); + SELF_CHECK (length == 4); + + /* Valid: length 0 with allow_zero_length (Fsystem). */ + SELF_CHECK (parse_allow_zero ("0/0") == 0); + SELF_CHECK (length == 0); + + /* Invalid: length 0 without allow_zero_length (pathname handlers). */ + SELF_CHECK (parse ("0/0") == -1); + + /* Valid: largest positive length accepted (technically INT_MAX). */ + SELF_CHECK (parse ("1/7fffffff") == 0); + SELF_CHECK (length == 0x7fffffff); + + /* Invalid: a length whose 64-bit value is negative is rejected. */ + SELF_CHECK (parse ("1/8000000000000000") == -1); + + /* Invalid: negative length. */ + SELF_CHECK (parse ("1/-1") == -1); + + /* Invalid: missing '/' separator. */ + SELF_CHECK (parse ("deadbeef") == -1); +} + +} /* namespace selftests */ + +#endif /* GDB_SELF_TEST */ + void initialize_remote_fileio (struct cmd_list_element **remote_set_cmdlist, struct cmd_list_element **remote_show_cmdlist) @@ -1256,4 +1329,8 @@ initialize_remote_fileio (struct cmd_list_element **remote_set_cmdlist, show_system_call_allowed, _("Show if the host system(3) call is allowed for the target."), remote_show_cmdlist); +#if GDB_SELF_TEST + selftests::register_test ("remote_fileio_extract_ptr_w_len", + selftests::test_remote_fileio_extract_ptr_w_len); +#endif } -- 2.34.1