From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-pf1-x42a.google.com (mail-pf1-x42a.google.com [IPv6:2607:f8b0:4864:20::42a]) by sourceware.org (Postfix) with ESMTPS id ADA8D385382B for ; Sat, 22 Jul 2023 15:14:42 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org ADA8D385382B Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-pf1-x42a.google.com with SMTP id d2e1a72fcca58-668711086f4so1912017b3a.1 for ; Sat, 22 Jul 2023 08:14:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20221208; t=1690038881; x=1690643681; h=in-reply-to:content-disposition:mime-version:references:message-id :subject:cc:to:from:date:from:to:cc:subject:date:message-id:reply-to; bh=0SHn2b9pRriPU9Bii008XExZ9j17JjQ6ysszwEiUgCE=; b=MHWV+fCqiOXrg7T3e/THLOFccripqkBBUtI7g0wZwE4am7jJNW4yD5em+cxcEUgxMp KPTSRrMbVpJGpa8D35jnR3UGwjZDcYeQ3EETE+gLfBuu4FW4rwZUfEQC46o/FIoAInBq XPRpQ7p1fhBgVhzq4s0iICT1IMPibQuaTylcTiNGZKnyQSZ16NNbMIFc1MA9fzKLWJdD 6jE1Y5PrfroxGTDBWFYwUVw3xE9BVROXNf3mt5hunZ0+lrY31nkYs1LDPg3FUKXC0dmJ s2/F6j7ZupKbazUw1nb3kQPpX7FiQtzlhtzSg+3bS34wMMFb6iZPV26cOY2auruEGYyX NMSg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1690038881; x=1690643681; h=in-reply-to:content-disposition:mime-version:references:message-id :subject:cc:to:from:date:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=0SHn2b9pRriPU9Bii008XExZ9j17JjQ6ysszwEiUgCE=; b=KsiB0tbHwO3XpJzuzwqs3E2VTK88tdt3Mcul7IkP2sObkWQixsOE1cxM4466B1GSTF /IgpIGqf0M7Z8cTwnzLIPxPEjVf6olEmtmins39ZVE1aWySsCimHMdhlKDZ9HXw5Q3Jt znaSh+g3rhE8erwuyklMdVS1Hnbji5hhmej2/IZdrPBw6dbAxTc3lafuxEH9a4ieHRA9 d554Sy5UcywhY35sZSseTwG5Q6ucoP/XqsWk4eW0K/iN7rOw/VxM9YhQ7jLSgweYkWv1 smhrihMXbsvMFq4fKOuQa6eFeXAZX3QrWvm6dN9PPtFpECu2a3zdG9eUFoRevDRgeKPF wa6g== X-Gm-Message-State: ABy/qLa8O5gYjjYrAjGuctUqskJn/sEi8d0KZSWusUvuJprNYMn5TeQo NfbUnls69zL0L/akjawKYIQYmGVmguE= X-Google-Smtp-Source: APBJJlF1qFhGQ9dfxsUvnrAsbUQu4U6wX5OsfuVJhZ0TjR39I5GIKILeV7Z7qbfULzLrmqWcj0bAJA== X-Received: by 2002:a05:6a20:918e:b0:134:70b7:238a with SMTP id v14-20020a056a20918e00b0013470b7238amr6737452pzd.12.1690038881378; Sat, 22 Jul 2023 08:14:41 -0700 (PDT) Received: from Thaum.localdomain (59-102-120-25.tpgi.com.au. [59.102.120.25]) by smtp.gmail.com with ESMTPSA id v11-20020a62a50b000000b00682a16f0b00sm4690909pfm.210.2023.07.22.08.14.39 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 22 Jul 2023 08:14:41 -0700 (PDT) Date: Sun, 23 Jul 2023 01:14:37 +1000 From: Nathaniel Shead To: gcc-patches@gcc.gnu.org Cc: Jason Merrill , Patrick Palka Subject: [PATCH v5 2/3] c++: Prevent dangling pointers from becoming nullptr in constexpr [PR110619] Message-ID: References: MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: X-Spam-Status: No, score=-11.4 required=5.0 tests=BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM,GIT_PATCH_0,RCVD_IN_DNSWL_NONE,SPF_HELO_NONE,SPF_PASS,TXREP,T_SCC_BODY_TEXT_LINE 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: Currently, when typeck discovers that a return statement will refer to a local variable it rewrites to return a null pointer. This causes the error messages for using the return value in a constant expression to be unhelpful, especially for reference return values, and is also a visible change to otherwise valid code (as in the linked PR). The transformation is nonetheless important, however, both as a safety guard against attackers being able to gain a handle to other data on the stack, and to prevent duplicate warnings from later null-dereference warning passes. As such, this patch just delays the transformation until cp_genericize, after constexpr function definitions have been generated. PR c++/110619 gcc/cp/ChangeLog: * cp-gimplify.cc (cp_genericize_r): Transform RETURN_EXPRs to not return dangling pointers. * cp-tree.h (RETURN_EXPR_LOCAL_ADDR_P): New flag. (check_return_expr): Add a new parameter. * semantics.cc (finish_return_stmt): Set flag on RETURN_EXPR when referring to dangling pointer. * typeck.cc (check_return_expr): Disable transformation of dangling pointers, instead pass this information to caller. gcc/testsuite/ChangeLog: * g++.dg/cpp1y/constexpr-110619.C: New test. Signed-off-by: Nathaniel Shead --- gcc/cp/cp-gimplify.cc | 23 ++++++++++++++++--- gcc/cp/cp-tree.h | 8 ++++++- gcc/cp/semantics.cc | 4 +++- gcc/cp/typeck.cc | 9 ++++---- gcc/testsuite/g++.dg/cpp1y/constexpr-110619.C | 10 ++++++++ 5 files changed, 45 insertions(+), 9 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-110619.C diff --git a/gcc/cp/cp-gimplify.cc b/gcc/cp/cp-gimplify.cc index f5734197774..0a5d6300aca 100644 --- a/gcc/cp/cp-gimplify.cc +++ b/gcc/cp/cp-gimplify.cc @@ -1336,9 +1336,26 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data) break; case RETURN_EXPR: - if (TREE_OPERAND (stmt, 0) && is_invisiref_parm (TREE_OPERAND (stmt, 0))) - /* Don't dereference an invisiref RESULT_DECL inside a RETURN_EXPR. */ - *walk_subtrees = 0; + if (TREE_OPERAND (stmt, 0)) + { + if (is_invisiref_parm (TREE_OPERAND (stmt, 0))) + /* Don't dereference an invisiref RESULT_DECL inside a RETURN_EXPR. */ + *walk_subtrees = 0; + if (RETURN_EXPR_LOCAL_ADDR_P (stmt)) + { + /* Don't return the address of a local variable. */ + tree *p = &TREE_OPERAND (stmt, 0); + while (TREE_CODE (*p) == COMPOUND_EXPR) + p = &TREE_OPERAND (*p, 0); + if (TREE_CODE (*p) == INIT_EXPR) + { + tree op = TREE_OPERAND (*p, 1); + tree new_op = build2 (COMPOUND_EXPR, TREE_TYPE (op), op, + build_zero_cst (TREE_TYPE (op))); + TREE_OPERAND (*p, 1) = new_op; + } + } + } break; case OMP_CLAUSE: diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 3de0e154c12..e0c181d9aef 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -447,6 +447,7 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX]; INIT_EXPR_NRV_P (in INIT_EXPR) ATOMIC_CONSTR_MAP_INSTANTIATED_P (in ATOMIC_CONSTR) contract_semantic (in ASSERTION_, PRECONDITION_, POSTCONDITION_STMT) + RETURN_EXPR_LOCAL_ADDR_P (in RETURN_EXPR) 1: IDENTIFIER_KIND_BIT_1 (in IDENTIFIER_NODE) TI_PENDING_TEMPLATE_FLAG. TEMPLATE_PARMS_FOR_INLINE. @@ -4071,6 +4072,11 @@ struct GTY(()) lang_decl { (LANG_DECL_FN_CHECK (FUNCTION_DECL_CHECK (NODE)) \ ->u.saved_auto_return_type) +/* In a RETURN_EXPR, whether the expression refers to the address + of a local variable. */ +#define RETURN_EXPR_LOCAL_ADDR_P(NODE) \ + TREE_LANG_FLAG_0 (RETURN_EXPR_CHECK (NODE)) + /* True if NODE is an implicit INDIRECT_REF from convert_from_reference. */ #define REFERENCE_REF_P(NODE) \ (INDIRECT_REF_P (NODE) \ @@ -8139,7 +8145,7 @@ extern tree composite_pointer_type (const op_location_t &, tsubst_flags_t); extern tree merge_types (tree, tree); extern tree strip_array_domain (tree); -extern tree check_return_expr (tree, bool *); +extern tree check_return_expr (tree, bool *, bool *); extern tree spaceship_type (tree, tsubst_flags_t = tf_warning_or_error); extern tree genericize_spaceship (location_t, tree, tree, tree); extern tree cp_build_binary_op (const op_location_t &, diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc index 8fb47fd179e..720521b7f1a 100644 --- a/gcc/cp/semantics.cc +++ b/gcc/cp/semantics.cc @@ -1240,8 +1240,9 @@ finish_return_stmt (tree expr) { tree r; bool no_warning; + bool dangling; - expr = check_return_expr (expr, &no_warning); + expr = check_return_expr (expr, &no_warning, &dangling); if (error_operand_p (expr) || (flag_openmp && !check_omp_return ())) @@ -1259,6 +1260,7 @@ finish_return_stmt (tree expr) } r = build_stmt (input_location, RETURN_EXPR, expr); + RETURN_EXPR_LOCAL_ADDR_P (r) = dangling; if (no_warning) suppress_warning (r, OPT_Wreturn_type); r = maybe_cleanup_point_expr_void (r); diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc index 859b133a18d..d5c0c85ed51 100644 --- a/gcc/cp/typeck.cc +++ b/gcc/cp/typeck.cc @@ -10920,10 +10920,11 @@ maybe_warn_pessimizing_move (tree expr, tree type, bool return_p) change RETVAL into the function return type, and to assign it to the DECL_RESULT for the function. Set *NO_WARNING to true if code reaches end of non-void function warning shouldn't be issued - on this RETURN_EXPR. */ + on this RETURN_EXPR. Set *DANGLING to true if code returns the + address of a local variable. */ tree -check_return_expr (tree retval, bool *no_warning) +check_return_expr (tree retval, bool *no_warning, bool *dangling) { tree result; /* The type actually returned by the function. */ @@ -10935,6 +10936,7 @@ check_return_expr (tree retval, bool *no_warning) location_t loc = cp_expr_loc_or_input_loc (retval); *no_warning = false; + *dangling = false; /* A `volatile' function is one that isn't supposed to return, ever. (This is a G++ extension, used to get better code for functions @@ -11273,8 +11275,7 @@ check_return_expr (tree retval, bool *no_warning) else if (!processing_template_decl && maybe_warn_about_returning_address_of_local (retval, loc) && INDIRECT_TYPE_P (valtype)) - retval = build2 (COMPOUND_EXPR, TREE_TYPE (retval), retval, - build_zero_cst (TREE_TYPE (retval))); + *dangling = true; } /* A naive attempt to reduce the number of -Wdangling-reference false diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-110619.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-110619.C new file mode 100644 index 00000000000..cca13302238 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-110619.C @@ -0,0 +1,10 @@ +// { dg-do compile { target c++14 } } +// { dg-options "-Wno-return-local-addr" } +// PR c++/110619 + +constexpr auto f() { + int i = 0; + return &i; +}; + +static_assert( f() != nullptr ); -- 2.41.0