From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 48) id 48E583856258; Wed, 11 May 2022 06:26:53 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 48E583856258 From: "cvs-commit at gcc dot gnu.org" To: gcc-bugs@gcc.gnu.org Subject: [Bug sanitizer/105396] [9/10 Regression] missed stack-buffer-overflow by -O0 Date: Wed, 11 May 2022 06:26:52 +0000 X-Bugzilla-Reason: CC X-Bugzilla-Type: changed X-Bugzilla-Watch-Reason: None X-Bugzilla-Product: gcc X-Bugzilla-Component: sanitizer X-Bugzilla-Version: 12.0 X-Bugzilla-Keywords: X-Bugzilla-Severity: normal X-Bugzilla-Who: cvs-commit at gcc dot gnu.org X-Bugzilla-Status: ASSIGNED X-Bugzilla-Resolution: X-Bugzilla-Priority: P2 X-Bugzilla-Assigned-To: jakub at gcc dot gnu.org X-Bugzilla-Target-Milestone: 9.5 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, 11 May 2022 06:26:53 -0000 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=3D105396 --- Comment #11 from CVS Commits --- The releases/gcc-9 branch has been updated by Jakub Jelinek : https://gcc.gnu.org/g:4431014dc2e905a427d1e9dd4f4d494ae2d7ab96 commit r9-10152-g4431014dc2e905a427d1e9dd4f4d494ae2d7ab96 Author: Jakub Jelinek Date: Wed Apr 27 08:34:18 2022 +0200 asan: Fix up asan_redzone_buffer::emit_redzone_byte [PR105396] On the following testcase, we have in main's frame 3 variables, some red zone padding, 4 byte d, followed by 12 bytes of red zone paddi= ng, then 8 byte b followed by 24 bytes of red zone padding, then 40 bytes c foll= owed by some red zone padding. The intended content of shadow memory for that is (note, each byte describes 8 bytes of memory): f1 f1 f1 f1 04 f2 00 f2 f2 f2 00 00 00 00 00 f3 f3 f3 f3 f3 left red d mr b middle r c right red zone f1 is left red zone magic f2 is middle red zone magic f3 is right red zone magic 00 when all 8 bytes are accessible 01-07 when only 1 to 7 bytes are accessible followed by inaccessible by= tes The -fdump-rtl-expand-details dump makes it clear that it misbehaves: Flushing rzbuffer at offset -160 with: f1 f1 f1 f1 Flushing rzbuffer at offset -128 with: 04 f2 00 00 Flushing rzbuffer at offset -128 with: 00 00 00 f2 Flushing rzbuffer at offset -96 with: f2 f2 00 00 Flushing rzbuffer at offset -64 with: 00 00 00 f3 Flushing rzbuffer at offset -32 with: f3 f3 f3 f3 In the end we end up with f1 f1 f1 f1 00 00 00 f2 f2 f2 00 00 00 00 00 f3 f3 f3 f3 f3 shadow bytes because at offset -128 there are 2 overlapping stores as asan_redzone_buffer::emit_redzone_byte has flushed the temporary 4 b= yte buffer in the middle. The function is called with an offset and value. If the passed offset = is consecutive with the prev_offset + buffer size (off =3D=3D offset), then we handle it correctly, similarly if the new offset is far enough from = the old one (we then flush whatever was in the buffer and if needed add up = to 3 bytes of 00 before actually pushing value. But what isn't handled correctly is when the offset isn't consecutive to what has been added last time, but it is in the same 4 byte word of sha= dow memory (32 bytes of actual memory), like the above case where we have consecutive 04 f2 and then skip one shadow memory byte (aka 8 b= ytes of real memory) and then want to emit f2. Emitting that as a store of little-endian 0x0000f204 followed by a store of 0xf2000000 to the sa= me address doesn't work, we want to emit 0xf200f204. The following patch does that by pushing 1 or 2 00 bytes. Additionally, as a small cleanup, instead of using m_shadow_bytes.safe_push (value); flush_if_full (); in all of if, else if and else bodies it sinks those 2 stmts to the end of function as all do the same thing. 2022-04-27 Jakub Jelinek PR sanitizer/105396 * asan.c (asan_redzone_buffer::emit_redzone_byte): Handle the c= ase where offset is bigger than off but smaller than m_prev_offset = + 32 bits by pushing one or more 0 bytes. Sink the m_shadow_bytes.safe_push (value); flush_if_full (); statements = from all cases to the end of the function. * gcc.dg/asan/pr105396.c: New test. (cherry picked from commit 9715f10c0651c9549b479b69d67be50ac4bd98a6)=