From patchwork Fri Feb 18 09:00:21 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Jelinek X-Patchwork-Id: 1594602 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.a=rsa-sha256 header.s=default header.b=AFcBLKCl; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=2620:52:3:1:0:246e:9693:128c; helo=sourceware.org; envelope-from=gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Received: from sourceware.org (server2.sourceware.org [IPv6:2620:52:3:1:0:246e:9693:128c]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4K0QfS0kKBz9s8q for ; Fri, 18 Feb 2022 20:01:18 +1100 (AEDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 31A12385C019 for ; Fri, 18 Feb 2022 09:01:13 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 31A12385C019 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1645174873; bh=Xwx6WnMu5NbmU93t3O7VDH4RupNfNEgrlX8XtwD7h5w=; h=Date:To:Subject:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:Cc:From; b=AFcBLKClQrWO5apbegMXy0ypF0X12HZPkY/FAr6VpdWJvb00Qugbi16s4MNgHWDye D8wrCW8Hxywx3OKDcRfNLVPa0OIEHKKNVrScs+BsYbcqwusddelw+urVgMnCbnPgfL 3u8y8t54rv3L9uN9e3Q3PkhImdGHTkS8hA+2IMhg= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by sourceware.org (Postfix) with ESMTPS id 03D49385842F for ; Fri, 18 Feb 2022 09:00:30 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 03D49385842F Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-508-RyFqzIwlPEidg-p3brWM0A-1; Fri, 18 Feb 2022 04:00:26 -0500 X-MC-Unique: RyFqzIwlPEidg-p3brWM0A-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id BEB5B1006AA3; Fri, 18 Feb 2022 09:00:25 +0000 (UTC) Received: from tucnak.zalov.cz (unknown [10.39.192.125]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 4C16466E27; Fri, 18 Feb 2022 09:00:25 +0000 (UTC) Received: from tucnak.zalov.cz (localhost [127.0.0.1]) by tucnak.zalov.cz (8.16.1/8.16.1) with ESMTPS id 21I90M1g3522402 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Fri, 18 Feb 2022 10:00:22 +0100 Received: (from jakub@localhost) by tucnak.zalov.cz (8.16.1/8.16.1/Submit) id 21I90LFw3522401; Fri, 18 Feb 2022 10:00:21 +0100 Date: Fri, 18 Feb 2022 10:00:21 +0100 To: Richard Biener Subject: [PATCH] asan: Mark instrumented vars addressable [PR102656] Message-ID: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Disposition: inline X-Spam-Status: No, score=-5.1 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, RCVD_IN_DNSWL_LOW, SPF_HELO_NONE, SPF_NONE, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Jakub Jelinek via Gcc-patches From: Jakub Jelinek Reply-To: Jakub Jelinek Cc: gcc-patches@gcc.gnu.org Errors-To: gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org Sender: "Gcc-patches" Hi! We ICE on the following testcase, because the asan1 pass decides to instrument .x = 0; and does that by _13 = &.x; .ASAN_CHECK (7, _13, 4, 4); .x = 0; and later sanopt pass turns that into: _39 = (unsigned long) &.x; _40 = _39 >> 3; _41 = _40 + 2147450880; _42 = (signed char *) _41; _43 = *_42; _44 = _43 != 0; _45 = _39 & 7; _46 = (signed char) _45; _47 = _46 + 3; _48 = _47 >= _43; _49 = _44 & _48; if (_49 != 0) goto ; [0.05%] else goto ; [99.95%] [local count: 536864]: __builtin___asan_report_store4 (_39); [local count: 1073741824]: .x = 0; The problem is during expansion, isn't marked TREE_ADDRESSABLE, even when we take its address in (unsigned long) &.x. Now, instrument_derefs has code to avoid the instrumentation altogether if we can prove the access is within bounds of an automatic variable in the current function and the var isn't TREE_ADDRESSABLE (or we don't instrument use after scope), but we do it solely for VAR_DECLs. I think we should treat RESULT_DECLs exactly like that too, which is what the following patch does. I must say I'm unsure about PARM_DECLs, those can have different cases, either they are fully or partially passed in registers, then if we take parameter's address, they are in a local copy inside of a function and so work like those automatic vars. But if they are fully passed in memory, we typically just take address of the slot and in that case they live in the caller's frame. It is true we don't (can't) put any asan padding in between the arguments, so all asan could detect in that case is if caller passes fewer on stack arguments or smaller arguments than callee accepts. Anyway, as I'm unsure, I haven't added PARM_DECLs to that case. And another thing is, when we actually build_fold_addr_expr, we need to mark_addressable the inner if it isn't addressable already. Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2022-02-18 Jakub Jelinek PR sanitizer/102656 * asan.cc (instrument_derefs): If inner is a RESULT_DECL and access is known to be within bounds, treat it like automatic variables. If instrumenting access and inner is {VAR,PARM,RESULT}_DECL from current function and !TREE_STATIC which is not TREE_ADDRESSABLE, mark it addressable. * g++.dg/asan/pr102656.C: New test. Jakub --- gcc/asan.cc.jj 2022-02-12 19:14:45.915168286 +0100 +++ gcc/asan.cc 2022-02-17 17:13:09.346987047 +0100 @@ -2688,13 +2688,13 @@ instrument_derefs (gimple_stmt_iterator return; poly_int64 decl_size; - if (VAR_P (inner) + if ((VAR_P (inner) || TREE_CODE (inner) == RESULT_DECL) && offset == NULL_TREE && DECL_SIZE (inner) && poly_int_tree_p (DECL_SIZE (inner), &decl_size) && known_subrange_p (bitpos, bitsize, 0, decl_size)) { - if (DECL_THREAD_LOCAL_P (inner)) + if (VAR_P (inner) && DECL_THREAD_LOCAL_P (inner)) return; /* If we're not sanitizing globals and we can tell statically that this access is inside a global variable, then there's no point adding @@ -2724,6 +2726,14 @@ instrument_derefs (gimple_stmt_iterator } } + if ((VAR_P (inner) + || TREE_CODE (inner) == PARM_DECL + || TREE_CODE (inner) == RESULT_DECL) + && !TREE_STATIC (inner) + && decl_function_context (inner) == current_function_decl + && !TREE_ADDRESSABLE (inner)) + mark_addressable (inner); + base = build_fold_addr_expr (t); if (!has_mem_ref_been_instrumented (base, size_in_bytes)) { --- gcc/testsuite/g++.dg/asan/pr102656.C.jj 2022-02-17 17:09:42.758866731 +0100 +++ gcc/testsuite/g++.dg/asan/pr102656.C 2022-02-17 17:10:46.212981870 +0100 @@ -0,0 +1,27 @@ +// PR sanitizer/102656 +// { dg-do compile } +// { dg-options "-std=c++20 -fsanitize=address" } + +#include + +class promise; + +struct future { + using promise_type = promise; + future() = default; + int x = 0; +}; + +struct promise { + future get_return_object() noexcept { return {}; } + auto initial_suspend() noexcept { return std::suspend_never{}; } + auto final_suspend() noexcept { return std::suspend_never{}; } + void return_void() noexcept {} + void unhandled_exception() {} +}; + +future +func () +{ + co_return; +}