From patchwork Wed Nov 30 01:07:51 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Malcolm X-Patchwork-Id: 61243 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 7C1B938582AC for ; Wed, 30 Nov 2022 01:08:33 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 7C1B938582AC DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1669770513; bh=tmZ482uOtUHYg1I/WZxfLXnIQJHUZUclu/+FhLS078M=; h=To:Cc:Subject:Date:List-Id:List-Unsubscribe:List-Archive: List-Post:List-Help:List-Subscribe:From:Reply-To:From; b=Pv7UzBUR4XBN+vvae5Ecj/xPd5Hr5635w3eIvQi94thcYftGZrlaY8N7pybGOrSpE 1HfI9rdTJJB1VRRAuRkRVHiVqbMDeUgyLlGYUBXyPJFUWwB523OHjLZxu/W5IB2P8y UHDoJAFm+BDtXNYfehwOP63l5m/IJ8mV3OZLjpMk= 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 F22D83858C2C for ; Wed, 30 Nov 2022 01:08:01 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org F22D83858C2C Received: from mimecast-mx02.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-300-BgMVQbXRNK-I3FK444TK-Q-1; Tue, 29 Nov 2022 20:08:00 -0500 X-MC-Unique: BgMVQbXRNK-I3FK444TK-Q-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.rdu2.redhat.com [10.11.54.2]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id E184F3C0CD42 for ; Wed, 30 Nov 2022 01:07:59 +0000 (UTC) Received: from t14s.localdomain.com (unknown [10.2.16.65]) by smtp.corp.redhat.com (Postfix) with ESMTP id A68F840C6EC4; Wed, 30 Nov 2022 01:07:59 +0000 (UTC) To: gcc-patches@gcc.gnu.org Cc: David Malcolm Subject: [committed] analyzer: move stdio known fns to sm-file.cc Date: Tue, 29 Nov 2022 20:07:51 -0500 Message-Id: <20221130010751.3663828-1-dmalcolm@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.2 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-11.9 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2, SPF_HELO_NONE, SPF_NONE, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) 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: David Malcolm via Gcc-patches From: David Malcolm Reply-To: David Malcolm Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu. Pushed to trunk as r13-4400-g84046b192e568e. gcc/analyzer/ChangeLog: * region-model-impl-calls.cc (class kf_fgets): Move to sm-file.cc. (kf_fgets::impl_call_pre): Likewise. (class kf_fread): Likewise. (kf_fread::impl_call_pre): Likewise. (class kf_getchar): Likewise. (class kf_stdio_output_fn): Likewise. (register_known_functions): Move registration of BUILT_IN_FPRINTF, BUILT_IN_FPRINTF_UNLOCKED, BUILT_IN_FPUTC, BUILT_IN_FPUTC_UNLOCKED, BUILT_IN_FPUTS, BUILT_IN_FPUTS_UNLOCKED, BUILT_IN_FWRITE, BUILT_IN_FWRITE_UNLOCKED, BUILT_IN_PRINTF, BUILT_IN_PRINTF_UNLOCKED, BUILT_IN_PUTC, BUILT_IN_PUTCHAR, BUILT_IN_PUTCHAR_UNLOCKED, BUILT_IN_PUTC_UNLOCKED, BUILT_IN_PUTS, BUILT_IN_PUTS_UNLOCKED, BUILT_IN_VFPRINTF, BUILT_IN_VPRINTF, "getchar", "fgets", "fgets_unlocked", and "fread" to register_known_file_functions. * sm-file.cc (class kf_stdio_output_fn): Move here from region-model-impl-calls.cc. (class kf_fgets): Likewise. (class kf_fread): Likewise. (class kf_getchar): Likewise. (register_known_file_functions): Move registration of BUILT_IN_FPRINTF, BUILT_IN_FPRINTF_UNLOCKED, BUILT_IN_FPUTC, BUILT_IN_FPUTC_UNLOCKED, BUILT_IN_FPUTS, BUILT_IN_FPUTS_UNLOCKED, BUILT_IN_FWRITE, BUILT_IN_FWRITE_UNLOCKED, BUILT_IN_PRINTF, BUILT_IN_PRINTF_UNLOCKED, BUILT_IN_PUTC, BUILT_IN_PUTCHAR, BUILT_IN_PUTCHAR_UNLOCKED, BUILT_IN_PUTC_UNLOCKED, BUILT_IN_PUTS, BUILT_IN_PUTS_UNLOCKED, BUILT_IN_VFPRINTF, BUILT_IN_VPRINTF, "fgets", "fgets_unlocked", "fread", and "getchar" to here from register_known_functions. Signed-off-by: David Malcolm --- gcc/analyzer/region-model-impl-calls.cc | 111 ------------------------ gcc/analyzer/sm-file.cc | 106 ++++++++++++++++++++++ 2 files changed, 106 insertions(+), 111 deletions(-) diff --git a/gcc/analyzer/region-model-impl-calls.cc b/gcc/analyzer/region-model-impl-calls.cc index 6d8c9f94138..8ba644c33cd 100644 --- a/gcc/analyzer/region-model-impl-calls.cc +++ b/gcc/analyzer/region-model-impl-calls.cc @@ -704,66 +704,6 @@ kf_error::impl_call_pre (const call_details &cd) const ctxt->terminate_path (); } -/* Handler for "fgets" and "fgets_unlocked". */ - -class kf_fgets : public known_function -{ -public: - bool matches_call_types_p (const call_details &cd) const final override - { - return (cd.num_args () == 3 - && cd.arg_is_pointer_p (0) - && cd.arg_is_pointer_p (2)); - } - - void impl_call_pre (const call_details &cd) const final override; -}; - -void -kf_fgets::impl_call_pre (const call_details &cd) const -{ - /* Ideally we would bifurcate state here between the - error vs no error cases. */ - region_model *model = cd.get_model (); - const svalue *ptr_sval = cd.get_arg_svalue (0); - if (const region *reg = ptr_sval->maybe_get_region ()) - { - const region *base_reg = reg->get_base_region (); - const svalue *new_sval = cd.get_or_create_conjured_svalue (base_reg); - model->set_value (base_reg, new_sval, cd.get_ctxt ()); - } -} - -/* Handler for "fread"". */ - -class kf_fread : public known_function -{ -public: - bool matches_call_types_p (const call_details &cd) const final override - { - return (cd.num_args () == 4 - && cd.arg_is_pointer_p (0) - && cd.arg_is_size_p (1) - && cd.arg_is_size_p (2) - && cd.arg_is_pointer_p (3)); - } - - void impl_call_pre (const call_details &cd) const final override; -}; - -void -kf_fread::impl_call_pre (const call_details &cd) const -{ - region_model *model = cd.get_model (); - const svalue *ptr_sval = cd.get_arg_svalue (0); - if (const region *reg = ptr_sval->maybe_get_region ()) - { - const region *base_reg = reg->get_base_region (); - const svalue *new_sval = cd.get_or_create_conjured_svalue (base_reg); - model->set_value (base_reg, new_sval, cd.get_ctxt ()); - } -} - /* Handler for "free", after sm-handling. If the ptr points to an underlying heap region, delete the region, @@ -803,20 +743,6 @@ kf_free::impl_call_post (const call_details &cd) const } } -/* Handler for "getchar"". */ - -class kf_getchar : public known_function -{ -public: - bool matches_call_types_p (const call_details &cd) const final override - { - return cd.num_args () == 0; - } - - /* Empty. No side-effects (tracking stream state is out-of-scope - for the analyzer). */ -}; - /* Handle the on_call_pre part of "malloc". */ class kf_malloc : public known_function @@ -1455,21 +1381,6 @@ public: /* Currently a no-op. */ }; -/* Handler for various stdio-related builtins that merely have external - effects that are out of scope for the analyzer: we only want to model - the effects on the return value. */ - -class kf_stdio_output_fn : public known_function -{ -public: - bool matches_call_types_p (const call_details &) const final override - { - return true; - } - - /* A no-op; we just want the conjured return value. */ -}; - /* Handler for "strcpy" and "__builtin_strcpy_chk". */ class kf_strcpy : public known_function @@ -1592,28 +1503,12 @@ register_known_functions (known_function_manager &kfm) kfm.add (BUILT_IN_CALLOC, make_unique ()); kfm.add (BUILT_IN_EXPECT, make_unique ()); kfm.add (BUILT_IN_EXPECT_WITH_PROBABILITY, make_unique ()); - kfm.add (BUILT_IN_FPRINTF, make_unique ()); - kfm.add (BUILT_IN_FPRINTF_UNLOCKED, make_unique ()); - kfm.add (BUILT_IN_FPUTC, make_unique ()); - kfm.add (BUILT_IN_FPUTC_UNLOCKED, make_unique ()); - kfm.add (BUILT_IN_FPUTS, make_unique ()); - kfm.add (BUILT_IN_FPUTS_UNLOCKED, make_unique ()); kfm.add (BUILT_IN_FREE, make_unique ()); - kfm.add (BUILT_IN_FWRITE, make_unique ()); - kfm.add (BUILT_IN_FWRITE_UNLOCKED, make_unique ()); kfm.add (BUILT_IN_MALLOC, make_unique ()); kfm.add (BUILT_IN_MEMCPY, make_unique ()); kfm.add (BUILT_IN_MEMCPY_CHK, make_unique ()); kfm.add (BUILT_IN_MEMSET, make_unique ()); kfm.add (BUILT_IN_MEMSET_CHK, make_unique ()); - kfm.add (BUILT_IN_PRINTF, make_unique ()); - kfm.add (BUILT_IN_PRINTF_UNLOCKED, make_unique ()); - kfm.add (BUILT_IN_PUTC, make_unique ()); - kfm.add (BUILT_IN_PUTCHAR, make_unique ()); - kfm.add (BUILT_IN_PUTCHAR_UNLOCKED, make_unique ()); - kfm.add (BUILT_IN_PUTC_UNLOCKED, make_unique ()); - kfm.add (BUILT_IN_PUTS, make_unique ()); - kfm.add (BUILT_IN_PUTS_UNLOCKED, make_unique ()); kfm.add (BUILT_IN_REALLOC, make_unique ()); kfm.add (BUILT_IN_STACK_RESTORE, make_unique ()); kfm.add (BUILT_IN_STACK_SAVE, make_unique ()); @@ -1621,8 +1516,6 @@ register_known_functions (known_function_manager &kfm) kfm.add (BUILT_IN_STRCPY, make_unique (2)); kfm.add (BUILT_IN_STRCPY_CHK, make_unique (3)); kfm.add (BUILT_IN_STRLEN, make_unique ()); - kfm.add (BUILT_IN_VFPRINTF, make_unique ()); - kfm.add (BUILT_IN_VPRINTF, make_unique ()); register_varargs_builtins (kfm); } @@ -1650,15 +1543,11 @@ register_known_functions (known_function_manager &kfm) /* Known builtins and C standard library functions. */ { - kfm.add ("getchar", make_unique ()); kfm.add ("memset", make_unique ()); } /* Known POSIX functions, and some non-standard extensions. */ { - kfm.add ("fgets", make_unique ()); - kfm.add ("fgets_unlocked", make_unique ()); // non-standard - kfm.add ("fread", make_unique ()); kfm.add ("putenv", make_unique ()); register_known_fd_functions (kfm); diff --git a/gcc/analyzer/sm-file.cc b/gcc/analyzer/sm-file.cc index 083c0ecbe41..d2dcb4312a2 100644 --- a/gcc/analyzer/sm-file.cc +++ b/gcc/analyzer/sm-file.cc @@ -489,6 +489,21 @@ make_fileptr_state_machine (logger *logger) return new fileptr_state_machine (logger); } +/* Handler for various stdio-related builtins that merely have external + effects that are out of scope for the analyzer: we only want to model + the effects on the return value. */ + +class kf_stdio_output_fn : public known_function +{ +public: + bool matches_call_types_p (const call_details &) const final override + { + return true; + } + + /* A no-op; we just want the conjured return value. */ +}; + /* Handler for "ferror"". */ class kf_ferror : public known_function @@ -517,6 +532,60 @@ public: /* No side effects. */ }; +/* Handler for "fgets" and "fgets_unlocked". */ + +class kf_fgets : public known_function +{ +public: + bool matches_call_types_p (const call_details &cd) const final override + { + return (cd.num_args () == 3 + && cd.arg_is_pointer_p (0) + && cd.arg_is_pointer_p (2)); + } + + void impl_call_pre (const call_details &cd) const final override + { + /* Ideally we would bifurcate state here between the + error vs no error cases. */ + region_model *model = cd.get_model (); + const svalue *ptr_sval = cd.get_arg_svalue (0); + if (const region *reg = ptr_sval->maybe_get_region ()) + { + const region *base_reg = reg->get_base_region (); + const svalue *new_sval = cd.get_or_create_conjured_svalue (base_reg); + model->set_value (base_reg, new_sval, cd.get_ctxt ()); + } + } +}; + +/* Handler for "fread"". */ + +class kf_fread : public known_function +{ +public: + bool matches_call_types_p (const call_details &cd) const final override + { + return (cd.num_args () == 4 + && cd.arg_is_pointer_p (0) + && cd.arg_is_size_p (1) + && cd.arg_is_size_p (2) + && cd.arg_is_pointer_p (3)); + } + + void impl_call_pre (const call_details &cd) const final override + { + region_model *model = cd.get_model (); + const svalue *ptr_sval = cd.get_arg_svalue (0); + if (const region *reg = ptr_sval->maybe_get_region ()) + { + const region *base_reg = reg->get_base_region (); + const svalue *new_sval = cd.get_or_create_conjured_svalue (base_reg); + model->set_value (base_reg, new_sval, cd.get_ctxt ()); + } + } +}; + /* Handler for "getc"". */ class kf_getc : public known_function @@ -531,15 +600,52 @@ public: /* No side effects. */ }; +/* Handler for "getchar"". */ + +class kf_getchar : public known_function +{ +public: + bool matches_call_types_p (const call_details &cd) const final override + { + return cd.num_args () == 0; + } + + /* Empty. No side-effects (tracking stream state is out-of-scope + for the analyzer). */ +}; + /* Populate KFM with instances of known functions relating to stdio streams. */ void register_known_file_functions (known_function_manager &kfm) { + kfm.add (BUILT_IN_FPRINTF, make_unique ()); + kfm.add (BUILT_IN_FPRINTF_UNLOCKED, make_unique ()); + kfm.add (BUILT_IN_FPUTC, make_unique ()); + kfm.add (BUILT_IN_FPUTC_UNLOCKED, make_unique ()); + kfm.add (BUILT_IN_FPUTS, make_unique ()); + kfm.add (BUILT_IN_FPUTS_UNLOCKED, make_unique ()); + kfm.add (BUILT_IN_FWRITE, make_unique ()); + kfm.add (BUILT_IN_FWRITE_UNLOCKED, make_unique ()); + kfm.add (BUILT_IN_PRINTF, make_unique ()); + kfm.add (BUILT_IN_PRINTF_UNLOCKED, make_unique ()); + kfm.add (BUILT_IN_PUTC, make_unique ()); + kfm.add (BUILT_IN_PUTCHAR, make_unique ()); + kfm.add (BUILT_IN_PUTCHAR_UNLOCKED, make_unique ()); + kfm.add (BUILT_IN_PUTC_UNLOCKED, make_unique ()); + kfm.add (BUILT_IN_PUTS, make_unique ()); + kfm.add (BUILT_IN_PUTS_UNLOCKED, make_unique ()); + kfm.add (BUILT_IN_VFPRINTF, make_unique ()); + kfm.add (BUILT_IN_VPRINTF, make_unique ()); + kfm.add ("ferror", make_unique ()); + kfm.add ("fgets", make_unique ()); + kfm.add ("fgets_unlocked", make_unique ()); // non-standard kfm.add ("fileno", make_unique ()); + kfm.add ("fread", make_unique ()); kfm.add ("getc", make_unique ()); + kfm.add ("getchar", make_unique ()); } #if CHECKING_P