From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail.hallyn.com (mail.hallyn.com [178.63.66.53]) by sourceware.org (Postfix) with ESMTPS id 2BB0C385842B for ; Fri, 24 Feb 2023 01:21:16 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 2BB0C385842B Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=hallyn.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=mail.hallyn.com Received: by mail.hallyn.com (Postfix, from userid 1001) id 5D4C8CA7; Thu, 23 Feb 2023 19:21:14 -0600 (CST) Date: Thu, 23 Feb 2023 19:21:14 -0600 From: "Serge E. Hallyn" To: Alex Colomar Cc: Martin Uecker , GCC , Iker Pedrosa , Florian Weimer , Paul Eggert , Michael Kerrisk , =?utf-8?B?SuKCkeKCmeKCmw==?= Gustedt , David Malcolm , Sam James , Serge Hallyn , Jonathan Wakely Subject: Re: Missed warning (-Wuse-after-free) Message-ID: <20230224012114.GA360078@mail.hallyn.com> References: <8ed6d28c-69dc-fed8-5ab5-99f685f06fac@gmail.com> <38e7e994a81d2a18666404dbaeb556f3508a6bd6.camel@redhat.com> <23d3a3ff-adad-ac2e-92a6-4e19f4093143@gmail.com> <2148ef80dee2a034ee531d662fc8709d26159ec5.camel@tugraz.at> <0049730a-e28c-0e0f-8d92-695395f1ec21@gmail.com> <6edeb3c197c327c1c6639d322c53ec6056039a33.camel@tugraz.at> MIME-Version: 1.0 Content-Type: text/plain; charset=iso-8859-1 Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,KAM_DMARC_STATUS,SPF_HELO_PASS,SPF_PASS 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 Fri, Feb 24, 2023 at 01:02:54AM +0100, Alex Colomar wrote: > Hi Martin, > > On 2/23/23 20:57, Martin Uecker wrote: > > Am Donnerstag, dem 23.02.2023 um 20:23 +0100 schrieb Alex Colomar: > > > Hi Martin, > > > > > > On 2/17/23 14:48, Martin Uecker wrote: > > > > > This new wording doesn't even allow one to use memcmp(3); > > > > > just reading the pointer value, however you do it, is UB. > > > > > > > > memcmp would not use the pointer value but work > > > > on the representation bytes and is still allowed. > > > > > > Hmm, interesting. It's rather unspecified behavior. Still > > > unpredictable: (memcmp(&p, &p, sizeof(p) == 0) might evaluate to true or > > > false randomly; the compiler may compile out the call to memcmp(3), > > > since it knows it won't produce any observable behavior. > > > > > > > > > > No, I think several things get mixed up here. > > > > The representation of a pointer that becomes invalid > > does not change. > > > > So (0 === memcmp(&p, &p, sizeof(p)) always > > evaluates to true. > > > > Also in general, an unspecified value is simply unspecified > > but does not change anymore. Right. p is its own thing - n bytes on the stack containing some value. Once it comes into scope, it doesn't change on its own. And if I do free(p) or o = realloc(p), then the value of p itself - the n bytes on the stack - does not change. I realize C11 appears to have changed that. I fear that in doing so it actually risks increasing the confusion about pointers. IMO it's much easier to reason about o = realloc(p, X); (and more baroque constructions) when keeping in mind that o, p, and the object pointed to by either one are all different things. > > Reading an uninitialized value of automatic storage whose > > address was not taken is undefined behavior, so everything > > is possible afterwards. > > > > An uninitialized variable whose address was taken has a > > representation which can represent an unspecified value > > or a no-value (trap) representation. Reading the > > representation itself is always ok and gives consistent > > results. Reading the variable can be undefined behavior > > iff it is a trap representation, otherwise you get > > the unspecified value which is stored there. > > > > At least this is my reading of the C standard. Compilers > > are not full conformant. > > Does all this imply that the following is well defined behavior (and shall > print what one would expect)? > > free(p); > > (void) &p; // take the address > // or maybe we should (void) memcmp(&p, &p, sizeof(p)); ? > > printf("%p\n", p); // we took previously its address, > // so now it has to hold consistently > // the previous value > > > This feels weird. And a bit of a Schroedinger's pointer. I'm not entirely > convinced, but might be. Again, p is just an n byte variable which happens to have (one hopes) pointed at a previously malloc'd address. And I'd argue that pre-C11, this was not confusing, and would not have felt weird to you. But I am most grateful to you for having brought this to my attention. I may not agree with it and not like it, but it's right there in the spec, so time for me to adjust :) -serge