From patchwork Sat Jan 29 21:41:59 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Harald Anlauf X-Patchwork-Id: 50574 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 4F74F385842C for ; Sat, 29 Jan 2022 21:42:47 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 4F74F385842C DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1643492567; bh=K7aASI/m+2axMBqPVwsMNfKfQPaQdaSnuiODYZPYSzI=; h=To:Subject:Date:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:From; b=LDKY5+/hgKj1B8Id1K2oWauNfOn1RGNHiviH+Ox7zSwm3+UBSZ/Q21J9bKIX7FhIZ Yd+Q7U1bjmIv7teooiHmgmEZU1fbn73pVB4wcS8NXTDwx7AHOhfQuE3sShTkhdUe1A ztMy+9r0/HKAwBla23iKSJKTE3439fX9BHNjOjPI= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mout.gmx.net (mout.gmx.net [212.227.17.20]) by sourceware.org (Postfix) with ESMTPS id 491C13858401; Sat, 29 Jan 2022 21:42:01 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 491C13858401 X-UI-Sender-Class: 01bb95c1-4bf8-414a-932a-4f6e2808ef9c Received: from [93.207.83.36] ([93.207.83.36]) by web-mail.gmx.net (3c-app-gmx-bap30.server.lan [172.19.172.100]) (via HTTP); Sat, 29 Jan 2022 22:41:59 +0100 MIME-Version: 1.0 Message-ID: To: fortran , gcc-patches Subject: [PATCH] PR/101135 - Load of null pointer when passing absent assumed-shape array argument for an optional dummy argument Date: Sat, 29 Jan 2022 22:41:59 +0100 Importance: normal Sensitivity: Normal X-Priority: 3 X-Provags-ID: V03:K1:N1bBCMD4b1uJmaNI5sLMB/nKH/FW14NPwsLFdhDywNJRFdy6S+U9Y/Btk0fC+Q2vTlw8i iz/bx0ALn1KllBsRz4AYbqECjuU7ZYAqnDO9icJsZyoyKqR61SkN3kN1cXmKG3vEe12ElW0i5K5n u7uf779WBmJykIIT691AF2ssy4FEF15qYSkMZ/MtiG29Izlj0CBxdtd0NcBOsWNTnfOhjUszSb4s fWzqWTL2MNuRvpsNmOri5sup2BjIr9FAKpEAz41wJsm70CWI6rKoFjCrEWp2I1c9VtnDUe9CbYL4 rE= X-UI-Out-Filterresults: notjunk:1;V03:K0:07qGalra31I=:VwHeItW+jR52RiNQeOxA9X GLAv+ifRY5VcX+orOA3OjwlZA5aiBngDD9eeXJLB5cUuX2qlJQhzCjCI1L4AkBpLiUDDeJm2R hRKYkf32GtZN6bTzdPz5YqXBZBC/g1wAHArJkN3LqMWWJA2rrG4YtX8Pqt+wePxDOajeRcD2f VBM8BRtw9HiyM4yaiag7QDLVaIQPgMGz4ts/lCqaKV1hQqeMtCafeBQl6/OuoY5nUzupZLdBD +abQkn/JQK0uExz1ThJ66O0XiscVh7F5SkUNxTq8Jk3mtmYueAligSMiGBiwnRrAFZNf8SsbF 6emoigmwiOvUTrkNpzuxpRSKkhfcBszK4wDsRicQjHu+bdx7uaAz1BrbOFK3BEylGwe44EsQn mVmuKb66vWyIhNB6wJG9mTInkHNYtLSwjFlmHtnQK9cLbNo7+MBy4sRKIg5Uzuj2d9W3YscYH g/uyP/7EQ1vJcdVPnNjEnpSBHEGvNuTaNAm4YL0ypQdIK/vDGljq8KI5OlELUy9VFk7yPp8gn Ml252TlSbpZhkJazjSEexqtt1gN4cmWCDX+7yRj6UCai2WURL3cTafusOYeN23QNnasUl3AtR cw3L1GfdtxzUs7BqwIb3ABX4KdfXzEL5iiT6QSaeOmnbOY6KK0sM1CcmFbD3ZgVYVauG80+uQ RiBtyH6waSVJqhDuTlk39JMOcMpK15vABD68TJMnRO8/5MrpSIVm8cVoqnj4wTiG4ciOvINgY pjfhAeQam7ZecopPxFIAdEHDqm+m6e2Y9jXbDPct28mI4yjwS/DvqERPlHZVU+DO2oW4itHVF HxcoOO1 X-Spam-Status: No, score=-12.3 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, FREEMAIL_FROM, GIT_PATCH_0, RCVD_IN_DNSWL_LOW, SPF_HELO_NONE, SPF_PASS, 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: Harald Anlauf via Gcc-patches From: Harald Anlauf Reply-To: Harald Anlauf Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" Dear Fortranners, compiling with -fsanitize=undefined shows that we did mishandle the case where a missing optional argument is passed to another procedure. Besides the example given in the PR, the existing testcase fortran.dg/missing_optional_dummy_6a.f90 fails with: gcc/testsuite/gfortran.dg/missing_optional_dummy_6a.f90:21:29: runtime error: load of null pointer of type 'integer(kind=4)' gcc/testsuite/gfortran.dg/missing_optional_dummy_6a.f90:22:30: runtime error: load of null pointer of type 'integer(kind=4)' gcc/testsuite/gfortran.dg/missing_optional_dummy_6a.f90:27:29: runtime error: load of null pointer of type 'integer(kind=4)' The least invasive change - already pointed out by the reporter - is to check the presence of the argument before dereferencing the data pointer after the offset calculation. This requires adjusting the checking pattern for gfortran.dg/missing_optional_dummy_6a.f90. Regtesting reminded me that procedures with bind(c) attribute are doing their own stuff, which is why they need to be excluded here, otherwise testcase bind-c-contiguous-4.f90 would regress on the expected output. I've created a testcase that uses this PR's input as well as the lesson learned from studying the bind(c) testcase and placed this in the asan subdirectory. There is a potential alternative solution which I did not pursue, as I think it is more invasive, but also that I didn't succeed to implement: A non-present dummy array argument should not need to get its descriptor set up. Pursuing this is probably not the right thing to do during the current stage of development and could be implemented later. If somebody believes this is important, feel free to open a PR for this. Regtested on x86_64-pc-linux-gnu. OK for mainline? Thanks, Harald From 69ca8f83149107f48b86360eb878d9d746b99234 Mon Sep 17 00:00:00 2001 From: Harald Anlauf Date: Sat, 29 Jan 2022 22:18:30 +0100 Subject: [PATCH] Fortran: fix handling of absent array argument passed to optional dummy gcc/fortran/ChangeLog: PR fortran/101135 * trans-array.cc (gfc_get_dataptr_offset): Check for optional arguments being present before dereferencing data pointer. gcc/testsuite/ChangeLog: PR fortran/101135 * gfortran.dg/missing_optional_dummy_6a.f90: Adjust diagnostic patterns. * gfortran.dg/asan/missing_optional_dummy_7.f90: New test. --- gcc/fortran/trans-array.cc | 11 ++++ .../asan/missing_optional_dummy_7.f90 | 64 +++++++++++++++++++ .../gfortran.dg/missing_optional_dummy_6a.f90 | 4 +- 3 files changed, 77 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/gfortran.dg/asan/missing_optional_dummy_7.f90 diff --git a/gcc/fortran/trans-array.cc b/gcc/fortran/trans-array.cc index cfb6eac11c7..9eaa99c5550 100644 --- a/gcc/fortran/trans-array.cc +++ b/gcc/fortran/trans-array.cc @@ -7207,6 +7207,17 @@ gfc_get_dataptr_offset (stmtblock_t *block, tree parm, tree desc, tree offset, /* Set the target data pointer. */ offset = gfc_build_addr_expr (gfc_array_dataptr_type (desc), tmp); + + /* Check for optional dummy argument being present. BIND(C) procedure + arguments are excepted here since they are handled differently. */ + if (expr->expr_type == EXPR_VARIABLE + && expr->symtree->n.sym->attr.dummy + && expr->symtree->n.sym->attr.optional + && !expr->symtree->n.sym->ns->proc_name->attr.is_bind_c) + offset = build3_loc (input_location, COND_EXPR, TREE_TYPE (offset), + gfc_conv_expr_present (expr->symtree->n.sym), offset, + fold_convert (TREE_TYPE (offset), gfc_index_zero_node)); + gfc_conv_descriptor_data_set (block, parm, offset); } diff --git a/gcc/testsuite/gfortran.dg/asan/missing_optional_dummy_7.f90 b/gcc/testsuite/gfortran.dg/asan/missing_optional_dummy_7.f90 new file mode 100644 index 00000000000..bdd7006170d --- /dev/null +++ b/gcc/testsuite/gfortran.dg/asan/missing_optional_dummy_7.f90 @@ -0,0 +1,64 @@ +! { dg-do run } +! { dg-additional-options "-fdump-tree-original -fsanitize=undefined" } +! +! PR fortran/101135 - Load of null pointer when passing absent +! assumed-shape array argument for an optional dummy argument +! +! Based on testcase by Marcel Jacobse + +program main + implicit none + character(len=3) :: a(6) = ['abc', 'def', 'ghi', 'jlm', 'nop', 'qrs'] + call as () + call as (a(::2)) + call as_c () + call as_c (a(2::2)) + call test_wrapper + call test_wrapper_c + call test2_wrapper +contains + subroutine as (xx) + character(len=*), optional, intent(in) :: xx(*) + if (.not. present (xx)) return + print *, xx(1:3) + end subroutine as + subroutine as_c (zz) bind(c) + character(len=*), optional, intent(in) :: zz(*) + if (.not. present (zz)) return + print *, zz(1:3) + end subroutine as_c + + subroutine test_wrapper (x) + real, dimension(1), intent(out), optional :: x + call test (x) ! + end subroutine test_wrapper + subroutine test (y) + real, dimension(:), intent(out), optional :: y + if (present (y)) y=0 + end subroutine test + + subroutine test_wrapper_c (w) bind(c) + real, dimension(1), intent(out), optional :: w + call test_c (w) + end subroutine test_wrapper_c + subroutine test_c (y) bind(c) + real, dimension(:), intent(out), optional :: y + if (present (y)) y=0 + end subroutine test_c + + subroutine test2_wrapper (u, v) + real, intent(out), optional :: u + real, dimension(1), intent(out), optional :: v + call test2 (u) + call test2 (v) ! + end subroutine test2_wrapper + subroutine test2 (z) + real, dimension(..), intent(out), optional :: z + end subroutine test2 +end program + +! { dg-final { scan-tree-dump-times "data = v != 0B " 1 "original" } } +! { dg-final { scan-tree-dump-times "data = x != 0B " 1 "original" } } +! { dg-final { scan-tree-dump-times "data = xx.0 != 0B " 1 "original" } } +! { dg-output " abcghinop(\n|\r\n|\r)" }" +! { dg-output " defjlmqrs(\n|\r\n|\r)" }" diff --git a/gcc/testsuite/gfortran.dg/missing_optional_dummy_6a.f90 b/gcc/testsuite/gfortran.dg/missing_optional_dummy_6a.f90 index c08c97a2c7e..bd34613c143 100644 --- a/gcc/testsuite/gfortran.dg/missing_optional_dummy_6a.f90 +++ b/gcc/testsuite/gfortran.dg/missing_optional_dummy_6a.f90 @@ -49,10 +49,10 @@ end program test ! { dg-final { scan-tree-dump-times "scalar2 \\(slr1" 1 "original" } } -! { dg-final { scan-tree-dump-times "= es1 != 0B" 1 "original" } } +! { dg-final { scan-tree-dump-times "= es1 != 0B" 2 "original" } } ! { dg-final { scan-tree-dump-times "assumed_shape2 \\(es1" 0 "original" } } ! { dg-final { scan-tree-dump-times "explicit_shape2 \\(es1" 1 "original" } } -! { dg-final { scan-tree-dump-times "= as1.0 != 0B" 2 "original" } } +! { dg-final { scan-tree-dump-times "= as1.0 != 0B" 4 "original" } } ! { dg-final { scan-tree-dump-times "assumed_shape2 \\(as1" 0 "original" } } ! { dg-final { scan-tree-dump-times "explicit_shape2 \\(as1" 0 "original" } } -- 2.31.1