From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from simark.ca (simark.ca [158.69.221.121]) by sourceware.org (Postfix) with ESMTPS id 7B2963858D37 for ; Tue, 16 Apr 2024 19:10:03 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 7B2963858D37 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=simark.ca Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=simark.ca ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 7B2963858D37 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=158.69.221.121 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1713294606; cv=none; b=Og0hoF99WyKxiT2Nfn/v67YINkofCbsyPd7HIJVL21AwqI0gkVPLXr114MlgufIZxnxdWZAAmYJ0sMfCmPVhJ2t7jzwFZWWPOzee4GyW7FgGJNGKKPRgO6FzzhkdYArtD1v3cHd3bUeygRsdeKBo+S4WjOvbF0N+BDnx2h25Huk= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1713294606; c=relaxed/simple; bh=uk6JShsd+934jnMPktTQDb5Fx4yHdhocJ4QiPyUKbcs=; h=DKIM-Signature:Message-ID:Date:MIME-Version:Subject:To:From; b=MOvRrZ9p6zNfhbI4H4+AdJ11g5LLkJoJxqnMojrhST7up/xTUh1DMWdrqwfT0J1l7HqYMK7klDEbxSoxNjjl/ymDBNY0at+VGUPKSspn6F/ZiezBCiBC2LvCo1H8VdTNRFWfFFLhOPlcuHihuYRvqSGDj4ZNOQ+R+oNY1mFdDrs= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=simark.ca; s=mail; t=1713294603; bh=uk6JShsd+934jnMPktTQDb5Fx4yHdhocJ4QiPyUKbcs=; h=Date:Subject:To:Cc:References:From:In-Reply-To:From; b=BySeTFiGcVh2Cm4vVQJx2cABBnSoF3NMzPHmKaZOJdpePrNG0aSbSQqOTtPqAb8mL DcKI61S6MvDLx7rsfYDCMxeR4MKTwUtvMrOR/fPrM+Tc6P4hre1cXxxyTl+vQCyHDI /azPU4i1keus1k/hLLdV+3twjUzLIO0iFMK6Dk6Q= Received: from [10.0.0.170] (modemcable238.237-201-24.mc.videotron.ca [24.201.237.238]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits) key-exchange X25519 server-signature ECDSA (prime256v1) server-digest SHA256) (No client certificate requested) by simark.ca (Postfix) with ESMTPSA id 7AD591E030; Tue, 16 Apr 2024 15:10:02 -0400 (EDT) Message-ID: <40c3c863-1369-4f4f-bef4-f2d35357c8eb@simark.ca> Date: Tue, 16 Apr 2024 15:10:02 -0400 MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: Re: [PATCH] [gdb/python] Throw MemoryError in inferior.read_memory if malloc fails To: Tom de Vries , Tom Tromey Cc: gdb-patches@sourceware.org References: <20240411105257.15421-1-tdevries@suse.de> <875xwn51dq.fsf@tromey.com> Content-Language: fr From: Simon Marchi In-Reply-To: Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 7bit X-Spam-Status: No, score=-10.6 required=5.0 tests=BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,GIT_PATCH_0,KAM_SHORT,SPF_HELO_PASS,SPF_PASS,TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: On 4/12/24 3:09 AM, Tom de Vries wrote: > On 4/11/24 18:07, Tom Tromey wrote: >>>>>>> "Tom" == Tom de Vries writes: >> >> Tom> PR python/31631 reports a gdb internal error when doing: >> Tom> ... >> Tom> (gdb) python gdb.selected_inferior().read_memory (0, 0xffffffffffffffff) >> Tom> utils.c:709: internal-error: virtual memory exhausted. >> Tom> A problem internal to GDB has been detected, >> Tom> further debugging may prove unreliable. >> Tom> ... >> >> Tom> Fix this by throwing a python MemoryError, such that we have instead: >> Tom> ... >> Tom> (gdb) python gdb.selected_inferior().read_memory (0, 0xffffffffffffffff) >> Tom> Python Exception : >> Tom> Error occurred in Python. >> Tom> (gdb) >> Tom> ... >> >> I tend to think you will regret opening this door, because I imagine >> there are a large number of ways to crash gdb by passing nonsensical >> values to Python APIs. >> > > Hm, ok then let's hope I don't regret it. > >> Tom> @request("readMemory") >> Tom> @capability("supportsReadMemoryRequest") >> Tom> def read_memory(*, memoryReference: str, offset: int = 0, count: int, **extra): >> Tom> addr = int(memoryReference, 0) + offset >> Tom> - buf = gdb.selected_inferior().read_memory(addr, count) >> Tom> + oom = False >> Tom> + try: >> Tom> + buf = gdb.selected_inferior().read_memory(addr, count) >> Tom> + except MemoryError: >> Tom> + oom = True >> Tom> + if oom: >> Tom> + raise DAPException("Out of memory") >> >> This should probably chain the memory error in the except block and >> re-throw. See https://peps.python.org/pep-3134/ >> > > Ack, that's what I had initially, but I ran into an error that I can no longer reproduce ... so, I'm not sure what happened there. Anyway, fixed. > >> However I don't really understand why this is needed. Isn't the >> exception already propagated back to the server thread? >> > > Without it I run into: > ... > FAIL: gdb.dap/memory.exp: exceptions in log file > ... > because in the dap log we have: > ... > READ: <<<{"seq": 7, "type": "request", "command": "readMemory", "arguments": {"memoryReference": "0x402010", "count": 18446744073709551615}}>>> > Traceback (most recent call last): > File "/data/vries/gdb/leap-15-5/build/gdb/data-directory/python/gdb/dap/server.py", line 157, in _handle_command > body = _commands[params["command"]](**args) > File "/data/vries/gdb/leap-15-5/build/gdb/data-directory/python/gdb/dap/server.py", line 300, in check > return func(*args, **kwargs) > File "/data/vries/gdb/leap-15-5/build/gdb/data-directory/python/gdb/dap/server.py", line 360, in sync_call > return send_gdb_with_response(lambda: func(**args)) > File "/data/vries/gdb/leap-15-5/build/gdb/data-directory/python/gdb/dap/server.py", line 514, in send_gdb_with_response > raise val > File "/data/vries/gdb/leap-15-5/build/gdb/data-directory/python/gdb/dap/server.py", line 470, in __call__ > val = self.fn() > File "/data/vries/gdb/leap-15-5/build/gdb/data-directory/python/gdb/dap/server.py", line 360, in > return send_gdb_with_response(lambda: func(**args)) > File "/data/vries/gdb/leap-15-5/build/gdb/data-directory/python/gdb/dap/startup.py", line 113, in ensure_gdb_thread > return func(*args, **kwargs) > File "/data/vries/gdb/leap-15-5/build/gdb/data-directory/python/gdb/dap/memory.py", line 28, in read_memory > buf = gdb.selected_inferior().read_memory(addr, count) > MemoryError > WROTE: <<<{"request_seq": 7, "type": "response", "command": "readMemory", "success": false, "message": ""}>>> > ... > > So that needs fixing here: > ... > diff --git a/gdb/python/lib/gdb/dap/server.py b/gdb/python/lib/gdb/dap/server.py > index 7eb87177710..8408232eceb 100644 > --- a/gdb/python/lib/gdb/dap/server.py > +++ b/gdb/python/lib/gdb/dap/server.py > @@ -173,6 +173,9 @@ class Server: > log_stack(LogLevel.FULL) > result["success"] = False > result["message"] = str(e) > + except MemoryError as e: > + result["success"] = False > + result["message"] = str(e) > except BaseException as e: > ... > > But I couldn't come up with a good rationale as to why I should handle MemoryError differently from BaseException, so I decided to catch it locally and turn it into a DAPException. > >> Tom> + /* We used to use xmalloc, which does this trick to avoid malloc >> Tom> + returning a nullptr for a valid reason. Keep doing the same. */ >> Tom> + if (length == 0) >> Tom> + length = 1; >> >> This is most likely a workaround for vendor implementations of malloc >> that return NULL for malloc(0). See >> https://www.gnu.org/software/gnulib/manual/html_node/malloc.html >> >> However, here this is not necessary, because a 0-length memory read is >> meaningless, and so this case can simply be reported as an error. > > I went for backward compatibility here, but ok, fixed. Updated version attached. > > Thanks, > - Tom In an Asan-enabled build, I get: 74 (gdb) python gdb.selected_inferior().read_memory (0, 0xffffffffffffffff)^M 75 =================================================================^M 76 ^[[1m^[[31m==791047==ERROR: AddressSanitizer: requested allocation size 0xffffffffffffffff (0x800 after adjustments for alignment, red zones etc.) exceeds maximum supported size of 0x100 00000000 (thread T0)^M 77 ^[[1m^[[0m #0 0x7f02c58d49cf in __interceptor_malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:69^M 78 #1 0x55cc5937f257 in infpy_read_memory /home/smarchi/src/binutils-gdb/gdb/python/py-inferior.c:565^M 79 #2 0x7f02c4ea9709 in method_vectorcall_VARARGS_KEYWORDS ../Objects/descrobject.c:364^M 80 ^M 81 ==791047==HINT: if you don't care about these errors you may set allocator_may_return_null=1^M 82 SUMMARY: AddressSanitizer: allocation-size-too-big ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:69 in __interceptor_malloc^M Simon