From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 48) id D8DE9385802B; Sun, 20 Dec 2020 21:08:38 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org D8DE9385802B From: "msharov at users dot sourceforge.net" To: gcc-bugs@gcc.gnu.org Subject: [Bug c/98404] New: Compiler emits unexpected function call that may cause security problems Date: Sun, 20 Dec 2020 21:08:38 +0000 X-Bugzilla-Reason: CC X-Bugzilla-Type: new X-Bugzilla-Watch-Reason: None X-Bugzilla-Product: gcc X-Bugzilla-Component: c X-Bugzilla-Version: 10.2.0 X-Bugzilla-Keywords: X-Bugzilla-Severity: normal X-Bugzilla-Who: msharov at users dot sourceforge.net 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: bug_id short_desc product version bug_status bug_severity priority component assigned_to reporter target_milestone Message-ID: 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: Sun, 20 Dec 2020 21:08:39 -0000 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=3D98404 Bug ID: 98404 Summary: Compiler emits unexpected function call that may cause security problems Product: gcc Version: 10.2.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c Assignee: unassigned at gcc dot gnu.org Reporter: msharov at users dot sourceforge.net Target Milestone: --- int rotate_argv (const char** argv, int first, int mid, int end) { const char** p =3D argv+first; int n1 =3D mid-first; int n2 =3D end-mid; int nm =3D n1+n2-1; for (int j =3D 0; j < n2; ++j) { const char* v =3D p[nm]; for (int i =3D 0; i < nm; ++i) p[nm-i] =3D p[nm-i-1]; p[0] =3D v; } return n1; } This bit of code unexpectedly emits a call to memmove to replace the inner = copy loop. Such behavior is highly inappropriate, breaking the "what-you-see-is-what-you-get" spirit of C. Sure, the loop is equivalent to= a memmove call, but if I wanted to call memmove, I would have called memmove. Doing it behind my back brings in code paths that may cause problems imposs= ible to understand by looking at the code. Worse yet, the compiler only does thi= s in the optimized build (-Os, -O2, and -O3, but not -O1 or -O0), making debuggi= ng of the resulting problem a beat-your-head-on-the-desk frustrating exercise. The bug in my code was causing memory corruption in argv to happen in that inner loop, but looking at the code above will not reveal the problem, no matter how much you scream at the debugger. The bug was in my memmove implementation returning the wrong value, which the compiler then helpfully reloaded into p. Naturally, it's a good thing that I fixed the bug; having never used the return value of memmove myself I doubt I would have discover= ed it anytime soon. But this illustrates how a malicious exploit could be introduced into that loop without anybody being able to figure it out. Let's remember that we still have that LD_PRELOAD abomination. On a more mundane note, replacing the loop with memmove causes the compiled code to grow from 107 bytes to 166. This is using the -Os, switch, of cours= e. I have complained many times about how gcc doesn't care about size optimizati= on and doesn't inline stuff because it can't understand that inserting a funct= ion call into code that currently has none has great costs of register saving a= nd all that. I have by now resigned to having to #define inline inline __attribute__((always_inline)) everywhere, but will you perhaps someday reconsider your position that size optimization does not matter? If 55% code bloat in this example doesn't convince you, what will? Finally, calling memmove will make the code slower, not faster, due to its = much higher startup overhead that is justifiable for copying large blocks, but n= ot for copying one or two elements, which is what the code above is made for. = The conceit of the compiler, in thinking it knows better, thus results in worse outcome all around; in size, speed, and security.=