From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 48) id A6904385EC59; Wed, 26 Jan 2022 07:23:52 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org A6904385EC59 From: "rguenther at suse dot de" To: gcc-bugs@gcc.gnu.org Subject: [Bug tree-optimization/104215] bogus -Wuse-after-free=3 due to forwprop moving a pointer test after realloc Date: Wed, 26 Jan 2022 07:23:52 +0000 X-Bugzilla-Reason: CC X-Bugzilla-Type: changed X-Bugzilla-Watch-Reason: None X-Bugzilla-Product: gcc X-Bugzilla-Component: tree-optimization X-Bugzilla-Version: 12.0 X-Bugzilla-Keywords: diagnostic X-Bugzilla-Severity: normal X-Bugzilla-Who: rguenther at suse dot de X-Bugzilla-Status: UNCONFIRMED X-Bugzilla-Resolution: X-Bugzilla-Priority: P3 X-Bugzilla-Assigned-To: unassigned at gcc dot gnu.org X-Bugzilla-Target-Milestone: --- X-Bugzilla-Flags: X-Bugzilla-Changed-Fields: Message-ID: In-Reply-To: References: Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable X-Bugzilla-URL: http://gcc.gnu.org/bugzilla/ Auto-Submitted: auto-generated MIME-Version: 1.0 X-BeenThere: gcc-bugs@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-bugs mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 26 Jan 2022 07:23:52 -0000 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=3D104215 --- Comment #6 from rguenther at suse dot de --- On Tue, 25 Jan 2022, msebor at gcc dot gnu.org wrote: > https://gcc.gnu.org/bugzilla/show_bug.cgi?id=3D104215 >=20 > --- Comment #5 from Martin Sebor --- > To "use" means to evaluate. The strict C semantics are that the realloc() > argument becomes indeterminate after the function has returned non-null, > whether or not the returned pointer is the same as the argument. The arg= ument > is only safe to use after realloc() has returned null. In other words, > strictly conforming programs must treat every successful call to realloc(= ) as > if it freed the original object. >=20 > The warning is based on these strict semantics. It handles the realloc f= ailure > case, and it tries to accommodate the use case of detecting whether reall= oc() > has moved the block to a different address by only warning on equality > expressions involving the original argument at level 3. >=20 > The warning cannot very well avoid triggering on this case if we want it = to > continue to work as designed (I of course do). The solution I'd like to = see is > the forwprop pass checking for the uses of the pointers in the propagated > condition in deallocation calls and suppressing the warning for the propa= gated > condition statement by calling suppress_warning(). This could be made re= liable > by having forwprop and the warning share the same code (a common function= to do > the same analysis to determine whether to suppress the warning in forwpro= p or > whether to trigger in gimple-ssa-warn-access). Note it's not only forwprop but any pass that eventually uses fold_stmt or moves code (sink for example) thereby honoring dataflow which does not represent that realloc() "clobbers" its first argument (on the !NULL return path). So I don't think it's feasible to fix this which means I don't think this warning will do any good to people. For example I see in a kernel build [ 59s] In file included from help.c:12: [ 59s] In function 'xrealloc', [ 59s] inlined from 'add_cmdname' at help.c:24:2: [ 59s] subcmd-util.h:56:23: error: pointer may be used after 'realloc'=20 [-Werror=3Duse-after-free] [ 59s] 56 | ret =3D realloc(ptr, size); [ 59s] | ^~~~~~~~~~~~~~~~~~ [ 59s] subcmd-util.h:52:21: note: call to 'realloc' here [ 59s] 52 | void *ret =3D realloc(ptr, size); [ 59s] | ^~~~~~~~~~~~~~~~~~ [ 59s] subcmd-util.h:58:31: error: pointer may be used after 'realloc'=20 [-Werror=3Duse-after-free] [ 59s] 58 | ret =3D realloc(ptr, 1); [ 59s] | ^~~~~~~~~~~~~~~ [ 59s] subcmd-util.h:52:21: note: call to 'realloc' here [ 59s] 52 | void *ret =3D realloc(ptr, size); [ 59s] | ^~~~~~~~~~~~~~~~~~ which eventually looks like static inline void *xrealloc(void *ptr, size_t size) { void *ret =3D realloc(ptr, size); if (!ret && !size) ret =3D realloc(ptr, 1); if (!ret) { ret =3D realloc(ptr, size); if (!ret && !size) ret =3D realloc(ptr, 1); if (!ret) die("Out of memory, realloc failed"); } return ret; } so it seems there'll be false positives even with the strict reading of the standard.=