From patchwork Thu Dec 7 00:28:22 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Malcolm X-Patchwork-Id: 174815 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:bcd1:0:b0:403:3b70:6f57 with SMTP id r17csp4467606vqy; Wed, 6 Dec 2023 16:28:54 -0800 (PST) X-Google-Smtp-Source: AGHT+IG1UTmEINWqLTCtpclGRVC5SDn2hk496dlaS5XNcDubCbl8naFzfGP8lhSixMcyPoxl2ABp X-Received: by 2002:a81:ad57:0:b0:5d7:1941:3558 with SMTP id l23-20020a81ad57000000b005d719413558mr1733082ywk.63.1701908934395; Wed, 06 Dec 2023 16:28:54 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1701908934; cv=pass; d=google.com; s=arc-20160816; b=h9TX9lRLKZHuUEbE961XCH716qn0SCGO0lpHnjQpPa/WBXl0/znog67gcZMXpoh75a zSMW2QcKQ259cNXKVaLFfdif3IkjnWRUf8iltzl5TmbAax6aLofcgG0q6JIed7ItVkp6 0D4jt5IdXHPoPWF9yhW4mh7H27RtNHIrtLcmkXy4DijLnz2eIuDoCoCos/Hy/moWTBFx aP/dGKcKMzEXyjdUg2nhDBvuRNikFS1a5sP3WrAF159L0BlO4wdfwOhR5u7R5csNfw/s Lkq6CZyUDbmH6+LCRR0znGIlOJ8Vs8lWuTT2OwuoxRmpZwxAlnZgm7aOjo+Hxlj/9ymF YTSQ== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:content-transfer-encoding :mime-version:message-id:date:subject:cc:to:from:dkim-signature :arc-filter:dmarc-filter:delivered-to; bh=HCKN2tHrz8ar8ZTrL2KQSYN6U4471xF/NQSPKPANRCI=; fh=NXemEfxTRbZtBxUkxR2ehQUaYlcDfMdzPkO8MChVQE4=; b=x4kRCQlGhEC/Yj8Tje8jAKd/gjhrF3CQWbRU0FJetSgEVBvKKA+OYFe/gUYhfg3G/M du3BimNyRmadhIqgzu3rsGRftQwjcUeT/u/LV5WQFuXUXEIC2r+i1vBSC7W8twbjWRfM Yd3ujGNQrIBn8l4KOkC4vFYd28FCx4u5W8wT2QDSIAJcK9hI4ZYr7eA/C2OAWgpAAiVJ gaKcqKbNh93JeUIParVpOd90N/wIiVY3fQpxWjZ+wCOlGnfbNmv9s7iE28KJDNtYGj6K leefn12Y/07+pa+38b+ORK0BNpI+plgawZsSAEAtAwc/xuEF8wyuQ//sDN5Wrr7nmE0/ 2yCQ== ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b="UT1hb/5T"; arc=pass (i=1); spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 8.43.85.97 as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: from server2.sourceware.org (server2.sourceware.org. [8.43.85.97]) by mx.google.com with ESMTPS id h5-20020a0ceec5000000b0067a9b8d04c5si114492qvs.329.2023.12.06.16.28.54 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 06 Dec 2023 16:28:54 -0800 (PST) Received-SPF: pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 8.43.85.97 as permitted sender) client-ip=8.43.85.97; Authentication-Results: mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b="UT1hb/5T"; arc=pass (i=1); spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 8.43.85.97 as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 295CF3857B8B for ; Thu, 7 Dec 2023 00:28:54 +0000 (GMT) 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 0C8D93858CD1 for ; Thu, 7 Dec 2023 00:28:26 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 0C8D93858CD1 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 0C8D93858CD1 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1701908911; cv=none; b=agkEbaq0me4S645O87DmSd2rUgbpi4l562o+9MvE5jc3R3PiMjH/6/eHzwvYyZo3aEDsSp+TW7QTUrxb8fdVMP++FeKoqeM9JWyJPs05HbZA7YziyD9BEy1x/u0D19D07TTWNeqaysgarLZc5jc00oLYTn4ZFX9ytHl6pvEvRrQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1701908911; c=relaxed/simple; bh=Zzt0l/aa6/5jSxw1PeA0NBbGYWRVZYgrBhm5fLhkxJs=; h=DKIM-Signature:From:To:Subject:Date:Message-Id:MIME-Version; b=LP3zOs0dYCE9XB4hBusnSy8KIOldvDZj3oAng1jsaOpx7yb+uf6WyvzLw3+RlC/vbdprZeQferqAVWK35z39VOzLrqTrDkz1kiSHrqiASpW+FvWaiU6BMviDbaHfyRutdI4kTi3nxjp3CqOuhX7e1Po9Jh6vB6i37X/dMzIMV1c= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1701908905; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=HCKN2tHrz8ar8ZTrL2KQSYN6U4471xF/NQSPKPANRCI=; b=UT1hb/5T9164qEkcP07JDYBsHOrjsMQNDmOCtVl0PK+Zeg/9jROGttXQyPlIHLrraPIVYp PEqwYXKQSkcF7hQNFO7h9Ok4clOnIu5C8q7CEVpcpfYzUm46o6cGqHc3dqPLk3PI8QPkOE 9Of4c7AKecQnJpVizK4qpq3kVAHi0SE= Received: from mimecast-mx02.redhat.com (mx-ext.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-132-TCU8OWqzPgq_jHaS6n1DOw-1; Wed, 06 Dec 2023 19:28:24 -0500 X-MC-Unique: TCU8OWqzPgq_jHaS6n1DOw-1 Received: from smtp.corp.redhat.com (int-mx10.intmail.prod.int.rdu2.redhat.com [10.11.54.10]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id E59593C100B2 for ; Thu, 7 Dec 2023 00:28:23 +0000 (UTC) Received: from t14s.localdomain.com (unknown [10.22.33.182]) by smtp.corp.redhat.com (Postfix) with ESMTP id 9D540492BE6; Thu, 7 Dec 2023 00:28:23 +0000 (UTC) From: David Malcolm To: gcc-patches@gcc.gnu.org Cc: David Malcolm Subject: [pushed] analyzer: fix taint false positives with UNKNOWN [PR112850] Date: Wed, 6 Dec 2023 19:28:22 -0500 Message-Id: <20231207002822.2498142-1-dmalcolm@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.10 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-11.7 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_H3, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_NONE, 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 X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1784580862956176040 X-GMAIL-MSGID: 1784580862956176040 PR analyzer/112850 reports a false positive from -Wanalyzer-tainted-allocation-size on the Linux kernel [1] where -fanalyzer complains that an allocation size is attacker-controlled despite the value being correctly sanitized against upper and lower limits. The root cause is that the expression is sufficiently complex to exceed the -param=analyzer-max-svalue-depth= threshold, currently at 12, with depth 13, and so it is treated as UNKNOWN. Hence the sanitizations are seen as comparisons of an UNKNOWN symbolic value against constants, and these were being ignored by the taint state machine. The expression in question is relatively typical for those seen in Linux kernel ioctl handlers, and I was surprised that it had exceeded the analyzer's default expression complexity limit. This patch addresses this problem in three ways: (a) the default value of the threshold parameter is increased, from 12 to 18, so that such expressions are precisely handled (b) adding a new -Wanalyzer-symbol-too-complex to warn when the symbol complexity limit is reached. This is off by default for users, and on by default in the test suite. (c) the taint state machine handles comparisons against UNKNOWN svalues by dropping all taint information on that execution path, so that if the complexity limit has been exceeded we don't generate false positives As well as fixing the taint false positive (PR analyzer/112850), the patch also fixes a couple of leak false positives seen on flex-generated scanners (PR analyzer/103546). [1] specifically, in sound/core/rawmidi.c's handler for SNDRV_RAWMIDI_STREAM_OUTPUT. Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu. Successful run of analyzer integration tests on x86_64-pc-linux-gnu. Pushed to trunk as r14-6239-g08b7462d3ad8e5. gcc/ChangeLog: PR analyzer/103546 PR analyzer/112850 * doc/invoke.texi: Add -Wanalyzer-symbol-too-complex. gcc/analyzer/ChangeLog: PR analyzer/103546 PR analyzer/112850 * analyzer.opt (-param=analyzer-max-svalue-depth=): Increase from 12 to 18. (Wanalyzer-symbol-too-complex): New. * diagnostic-manager.cc (null_assignment_sm_context::clear_all_per_svalue_state): New. * engine.cc (impl_sm_context::clear_all_per_svalue_state): New. * program-state.cc (sm_state_map::clear_all_per_svalue_state): New. * program-state.h (sm_state_map::clear_all_per_svalue_state): New decl. * region-model-manager.cc (region_model_manager::reject_if_too_complex): Add -Wanalyzer-symbol-too-complex. * sm-taint.cc (taint_state_machine::on_condition): Handle comparisons against UNKNOWN. * sm.h (sm_context::clear_all_per_svalue_state): New. gcc/testsuite/ChangeLog: PR analyzer/103546 PR analyzer/112850 * c-c++-common/analyzer/call-summaries-pr107158-2.c: Add -Wno-analyzer-symbol-too-complex. * c-c++-common/analyzer/call-summaries-pr107158.c: Likewise. * c-c++-common/analyzer/deref-before-check-pr109060-haproxy-cfgparse.c: Likewise. * c-c++-common/analyzer/feasibility-3.c: Add -Wno-analyzer-too-complex and -Wno-analyzer-symbol-too-complex. * c-c++-common/analyzer/flex-with-call-summaries.c: Add -Wno-analyzer-symbol-too-complex. Remove fail for PR analyzer/103546 leak false positive. * c-c++-common/analyzer/flex-without-call-summaries.c: Remove xfail for PR analyzer/103546 leak false positive. * c-c++-common/analyzer/infinite-recursion-3.c: Add -Wno-analyzer-symbol-too-complex. * c-c++-common/analyzer/null-deref-pr108251-smp_fetch_ssl_fc_has_early-O2.c: Likewise. * c-c++-common/analyzer/null-deref-pr108251-smp_fetch_ssl_fc_has_early.c: Likewise. * c-c++-common/analyzer/null-deref-pr108400-SoftEtherVPN-WebUi.c: Likewise. * c-c++-common/analyzer/null-deref-pr108806-qemu.c: Likewise. * c-c++-common/analyzer/null-deref-pr108830.c: Likewise. * c-c++-common/analyzer/pr94596.c: Likewise. * c-c++-common/analyzer/strtok-2.c: Likewise. * c-c++-common/analyzer/strtok-4.c: Add -Wno-analyzer-too-complex and -Wno-analyzer-symbol-too-complex. * c-c++-common/analyzer/strtok-cppreference.c: Likewise. * gcc.dg/analyzer/analyzer.exp: Add -Wanalyzer-symbol-too-complex to DEFAULT_CFLAGS. * gcc.dg/analyzer/attr-const-3.c: Add -Wno-analyzer-symbol-too-complex. * gcc.dg/analyzer/call-summaries-pr107072.c: Likewise. * gcc.dg/analyzer/doom-s_sound-pr108867.c: Likewise. * gcc.dg/analyzer/explode-4.c: Likewise. * gcc.dg/analyzer/null-deref-pr102671-1.c: Likewise. * gcc.dg/analyzer/null-deref-pr105755.c: Likewise. * gcc.dg/analyzer/out-of-bounds-curl.c: Likewise. * gcc.dg/analyzer/pr101503.c: Likewise. * gcc.dg/analyzer/pr103892.c: Add -Wno-analyzer-too-complex and -Wno-analyzer-symbol-too-complex. * gcc.dg/analyzer/pr94851-4.c: Add -Wno-analyzer-symbol-too-complex. * gcc.dg/analyzer/pr96860-1.c: Likewise. * gcc.dg/analyzer/pr96860-2.c: Likewise. * gcc.dg/analyzer/pr98918.c: Likewise. * gcc.dg/analyzer/pr99044-2.c: Likewise. * gcc.dg/analyzer/uninit-pr108806-qemu.c: Likewise. * gcc.dg/analyzer/use-after-free.c: Add -Wno-analyzer-too-complex and -Wno-analyzer-symbol-too-complex. * gcc.dg/plugin/plugin.exp: Add new tests for analyzer_kernel_plugin.c. * gcc.dg/plugin/taint-CVE-2011-0521-4.c: Update expected results. * gcc.dg/plugin/taint-CVE-2011-0521-5.c: Likewise. * gcc.dg/plugin/taint-CVE-2011-0521-6.c: Likewise. * gcc.dg/plugin/taint-CVE-2011-0521-5-fixed.c: Remove xfail. * gcc.dg/plugin/taint-pr112850-precise.c: New test. * gcc.dg/plugin/taint-pr112850-too-complex.c: New test. * gcc.dg/plugin/taint-pr112850-unsanitized.c: New test. * gcc.dg/plugin/taint-pr112850.c: New test. --- gcc/analyzer/analyzer.opt | 6 ++- gcc/analyzer/diagnostic-manager.cc | 5 ++ gcc/analyzer/engine.cc | 5 ++ gcc/analyzer/program-state.cc | 8 +++ gcc/analyzer/program-state.h | 1 + gcc/analyzer/region-model-manager.cc | 10 ++++ gcc/analyzer/sm-taint.cc | 14 +++++ gcc/analyzer/sm.h | 2 + gcc/doc/invoke.texi | 14 +++++ .../analyzer/call-summaries-pr107158-2.c | 2 +- .../analyzer/call-summaries-pr107158.c | 2 +- ...f-before-check-pr109060-haproxy-cfgparse.c | 2 + .../c-c++-common/analyzer/feasibility-3.c | 2 + .../analyzer/flex-with-call-summaries.c | 4 +- .../analyzer/flex-without-call-summaries.c | 3 +- .../analyzer/infinite-recursion-3.c | 2 +- ...f-pr108251-smp_fetch_ssl_fc_has_early-O2.c | 2 +- ...eref-pr108251-smp_fetch_ssl_fc_has_early.c | 1 + .../null-deref-pr108400-SoftEtherVPN-WebUi.c | 2 + .../analyzer/null-deref-pr108806-qemu.c | 2 + .../analyzer/null-deref-pr108830.c | 2 +- gcc/testsuite/c-c++-common/analyzer/pr94596.c | 3 ++ .../c-c++-common/analyzer/strtok-2.c | 2 + .../c-c++-common/analyzer/strtok-4.c | 2 + .../analyzer/strtok-cppreference.c | 2 + gcc/testsuite/gcc.dg/analyzer/analyzer.exp | 2 +- gcc/testsuite/gcc.dg/analyzer/attr-const-3.c | 2 +- .../gcc.dg/analyzer/call-summaries-pr107072.c | 2 +- .../gcc.dg/analyzer/doom-s_sound-pr108867.c | 2 +- gcc/testsuite/gcc.dg/analyzer/explode-4.c | 2 +- .../gcc.dg/analyzer/null-deref-pr102671-1.c | 2 +- .../gcc.dg/analyzer/null-deref-pr105755.c | 2 +- .../gcc.dg/analyzer/out-of-bounds-curl.c | 2 +- gcc/testsuite/gcc.dg/analyzer/pr101503.c | 2 +- gcc/testsuite/gcc.dg/analyzer/pr103892.c | 2 +- gcc/testsuite/gcc.dg/analyzer/pr94851-4.c | 2 +- gcc/testsuite/gcc.dg/analyzer/pr96860-1.c | 2 +- gcc/testsuite/gcc.dg/analyzer/pr96860-2.c | 2 +- gcc/testsuite/gcc.dg/analyzer/pr98918.c | 2 + gcc/testsuite/gcc.dg/analyzer/pr99044-2.c | 2 + .../gcc.dg/analyzer/uninit-pr108806-qemu.c | 2 + .../gcc.dg/analyzer/use-after-free.c | 2 + gcc/testsuite/gcc.dg/plugin/plugin.exp | 6 ++- .../gcc.dg/plugin/taint-CVE-2011-0521-4.c | 4 +- .../plugin/taint-CVE-2011-0521-5-fixed.c | 3 +- .../gcc.dg/plugin/taint-CVE-2011-0521-5.c | 4 +- .../gcc.dg/plugin/taint-CVE-2011-0521-6.c | 4 +- .../gcc.dg/plugin/taint-pr112850-precise.c | 50 ++++++++++++++++++ .../plugin/taint-pr112850-too-complex.c | 51 +++++++++++++++++++ .../plugin/taint-pr112850-unsanitized.c | 50 ++++++++++++++++++ gcc/testsuite/gcc.dg/plugin/taint-pr112850.c | 47 +++++++++++++++++ 51 files changed, 321 insertions(+), 32 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/plugin/taint-pr112850-precise.c create mode 100644 gcc/testsuite/gcc.dg/plugin/taint-pr112850-too-complex.c create mode 100644 gcc/testsuite/gcc.dg/plugin/taint-pr112850-unsanitized.c create mode 100644 gcc/testsuite/gcc.dg/plugin/taint-pr112850.c diff --git a/gcc/analyzer/analyzer.opt b/gcc/analyzer/analyzer.opt index a3c30caf2ab..d0fe5a43788 100644 --- a/gcc/analyzer/analyzer.opt +++ b/gcc/analyzer/analyzer.opt @@ -43,7 +43,7 @@ Common Joined UInteger Var(param_analyzer_max_recursion_depth) Init(2) Param The maximum number of times a callsite can appear in a call stack within the analyzer, before terminating analysis of a call that would recurse deeper. -param=analyzer-max-svalue-depth= -Common Joined UInteger Var(param_analyzer_max_svalue_depth) Init(12) Param +Common Joined UInteger Var(param_analyzer_max_svalue_depth) Init(18) Param The maximum depth of a symbolic value, before approximating the value as unknown. -param=analyzer-min-snodes-for-call-summary= @@ -262,6 +262,10 @@ Wanalyzer-use-of-uninitialized-value Common Var(warn_analyzer_use_of_uninitialized_value) Init(1) Warning Warn about code paths in which an uninitialized value is used. +Wanalyzer-symbol-too-complex +Common Var(warn_analyzer_symbol_too_complex) Init(0) Warning +Warn if expressions are too complicated for the analyzer to fully track. + Wanalyzer-too-complex Common Var(warn_analyzer_too_complex) Init(0) Warning Warn if the code is too complicated for the analyzer to fully explore. diff --git a/gcc/analyzer/diagnostic-manager.cc b/gcc/analyzer/diagnostic-manager.cc index ecd57376b54..38bd308a9a4 100644 --- a/gcc/analyzer/diagnostic-manager.cc +++ b/gcc/analyzer/diagnostic-manager.cc @@ -2043,6 +2043,11 @@ struct null_assignment_sm_context : public sm_context /* No-op. */ } + void clear_all_per_svalue_state () final override + { + /* No-op. */ + } + void on_custom_transition (custom_transition *) final override { } diff --git a/gcc/analyzer/engine.cc b/gcc/analyzer/engine.cc index 825b3af43fc..d2524e34f58 100644 --- a/gcc/analyzer/engine.cc +++ b/gcc/analyzer/engine.cc @@ -474,6 +474,11 @@ public: m_new_state->m_checker_states[m_sm_idx]->set_global_state (state); } + void clear_all_per_svalue_state () final override + { + m_new_state->m_checker_states[m_sm_idx]->clear_all_per_svalue_state (); + } + void on_custom_transition (custom_transition *transition) final override { transition->impl_transition (&m_eg, diff --git a/gcc/analyzer/program-state.cc b/gcc/analyzer/program-state.cc index 9bb81e6dddd..78f739ef5ef 100644 --- a/gcc/analyzer/program-state.cc +++ b/gcc/analyzer/program-state.cc @@ -526,6 +526,14 @@ sm_state_map::clear_any_state (const svalue *sval) m_map.remove (sval); } +/* Clear all per-svalue state within this state map. */ + +void +sm_state_map::clear_all_per_svalue_state () +{ + m_map.empty (); +} + /* Set the "global" state within this state map to STATE. */ void diff --git a/gcc/analyzer/program-state.h b/gcc/analyzer/program-state.h index c9b3aa0cbfc..ef1a2ad54a9 100644 --- a/gcc/analyzer/program-state.h +++ b/gcc/analyzer/program-state.h @@ -146,6 +146,7 @@ public: const svalue *origin, const extrinsic_state &ext_state); void clear_any_state (const svalue *sval); + void clear_all_per_svalue_state (); void set_global_state (state_machine::state_t state); state_machine::state_t get_global_state () const; diff --git a/gcc/analyzer/region-model-manager.cc b/gcc/analyzer/region-model-manager.cc index 921edc55868..b631bcb04d0 100644 --- a/gcc/analyzer/region-model-manager.cc +++ b/gcc/analyzer/region-model-manager.cc @@ -185,6 +185,16 @@ region_model_manager::reject_if_too_complex (svalue *sval) return false; } + pretty_printer pp; + pp_format_decoder (&pp) = default_tree_printer; + sval->dump_to_pp (&pp, true); + if (warning_at (input_location, OPT_Wanalyzer_symbol_too_complex, + "symbol too complicated: %qs", + pp_formatted_text (&pp))) + inform (input_location, + "max_depth %i exceeds --param=analyzer-max-svalue-depth=%i", + c.m_max_depth, param_analyzer_max_svalue_depth); + delete sval; return true; } diff --git a/gcc/analyzer/sm-taint.cc b/gcc/analyzer/sm-taint.cc index d01e3f03951..6b5d51c62af 100644 --- a/gcc/analyzer/sm-taint.cc +++ b/gcc/analyzer/sm-taint.cc @@ -1038,6 +1038,20 @@ taint_state_machine::on_condition (sm_context *sm_ctxt, if (stmt == NULL) return; + if (lhs->get_kind () == SK_UNKNOWN + || rhs->get_kind () == SK_UNKNOWN) + { + /* If we have a comparison against UNKNOWN, then + we've presumably hit the svalue complexity limit, + and we don't know what is being sanitized. + Give up on any taint already found on this execution path. */ + // TODO: warn about this + if (get_logger ()) + get_logger ()->log ("comparison against UNKNOWN; removing all taint"); + sm_ctxt->clear_all_per_svalue_state (); + return; + } + // TODO switch (op) { diff --git a/gcc/analyzer/sm.h b/gcc/analyzer/sm.h index 3ff9c260780..ef63d73a541 100644 --- a/gcc/analyzer/sm.h +++ b/gcc/analyzer/sm.h @@ -299,6 +299,8 @@ public: virtual state_machine::state_t get_global_state () const = 0; virtual void set_global_state (state_machine::state_t) = 0; + virtual void clear_all_per_svalue_state () = 0; + /* A vfunc for handling custom transitions, such as when registering a signal handler. */ virtual void on_custom_transition (custom_transition *transition) = 0; diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 332227d71f9..166db887e83 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -490,6 +490,7 @@ Objective-C and Objective-C++ Dialects}. -Wno-analyzer-tainted-divisor -Wno-analyzer-tainted-offset -Wno-analyzer-tainted-size +-Wanalyzer-symbol-too-complex -Wanalyzer-too-complex -Wno-analyzer-undefined-behavior-strtok -Wno-analyzer-unsafe-call-within-signal-handler @@ -10526,6 +10527,19 @@ Enabling this option effectively enables the following warnings: This option is only available if GCC was configured with analyzer support enabled. +@opindex Wanalyzer-symbol-too-complex +@opindex Wno-analyzer-symbol-too-complex +@item -Wanalyzer-symbol-too-complex +If @option{-fanalyzer} is enabled, the analyzer uses various heuristics +to attempt to track the state of memory, but these can be defeated by +sufficiently complicated code. + +By default, the analysis silently stops tracking values of expressions +if they exceed the threshold defined by +@option{--param analyzer-max-svalue-depth=@var{value}}, and falls back +to an imprecise representation for such expressions. +The @option{-Wanalyzer-symbol-too-complex} option warns if this occurs. + @opindex Wanalyzer-too-complex @opindex Wno-analyzer-too-complex @item -Wanalyzer-too-complex diff --git a/gcc/testsuite/c-c++-common/analyzer/call-summaries-pr107158-2.c b/gcc/testsuite/c-c++-common/analyzer/call-summaries-pr107158-2.c index 4561e10cafd..b395623ccca 100644 --- a/gcc/testsuite/c-c++-common/analyzer/call-summaries-pr107158-2.c +++ b/gcc/testsuite/c-c++-common/analyzer/call-summaries-pr107158-2.c @@ -1,4 +1,4 @@ -/* { dg-additional-options "-fanalyzer-call-summaries -Wno-analyzer-too-complex" } */ +/* { dg-additional-options "-fanalyzer-call-summaries -Wno-analyzer-too-complex -Wno-analyzer-symbol-too-complex" } */ /* { dg-skip-if "c++98 has no noreturn attribute" { c++98_only } } */ #ifdef __cplusplus diff --git a/gcc/testsuite/c-c++-common/analyzer/call-summaries-pr107158.c b/gcc/testsuite/c-c++-common/analyzer/call-summaries-pr107158.c index d4cf079cef8..de705836249 100644 --- a/gcc/testsuite/c-c++-common/analyzer/call-summaries-pr107158.c +++ b/gcc/testsuite/c-c++-common/analyzer/call-summaries-pr107158.c @@ -1,4 +1,4 @@ -/* { dg-additional-options "-fanalyzer-call-summaries" } */ +/* { dg-additional-options "-fanalyzer-call-summaries -Wno-analyzer-symbol-too-complex" } */ typedef __SIZE_TYPE__ size_t; enum { _ISspace = ((5) < 8 ? ((1 << (5)) << 8) : ((1 << (5)) >> 8)) }; diff --git a/gcc/testsuite/c-c++-common/analyzer/deref-before-check-pr109060-haproxy-cfgparse.c b/gcc/testsuite/c-c++-common/analyzer/deref-before-check-pr109060-haproxy-cfgparse.c index 1d28e10747c..c4561fcd8a7 100644 --- a/gcc/testsuite/c-c++-common/analyzer/deref-before-check-pr109060-haproxy-cfgparse.c +++ b/gcc/testsuite/c-c++-common/analyzer/deref-before-check-pr109060-haproxy-cfgparse.c @@ -1,5 +1,7 @@ /* Reduced from haproxy-2.7.1's cfgparse.c. */ +/* { dg-additional-options "-Wno-analyzer-too-complex -Wno-analyzer-symbol-too-complex" } */ + typedef __SIZE_TYPE__ size_t; extern int diff --git a/gcc/testsuite/c-c++-common/analyzer/feasibility-3.c b/gcc/testsuite/c-c++-common/analyzer/feasibility-3.c index 2fcd064e801..06194f85069 100644 --- a/gcc/testsuite/c-c++-common/analyzer/feasibility-3.c +++ b/gcc/testsuite/c-c++-common/analyzer/feasibility-3.c @@ -1,6 +1,8 @@ /* Reduced and adapted from Linux: fs/proc/inode.c: proc_reg_open (GPL v2.0). */ +/* { dg-additional-options "-Wno-analyzer-too-complex -Wno-analyzer-symbol-too-complex" } */ + /* Types. */ typedef unsigned char u8; diff --git a/gcc/testsuite/c-c++-common/analyzer/flex-with-call-summaries.c b/gcc/testsuite/c-c++-common/analyzer/flex-with-call-summaries.c index 45edacf0e53..963a84bc9ab 100644 --- a/gcc/testsuite/c-c++-common/analyzer/flex-with-call-summaries.c +++ b/gcc/testsuite/c-c++-common/analyzer/flex-with-call-summaries.c @@ -5,6 +5,7 @@ /* { dg-skip-if "" { "avr-*-*" } } */ /* { dg-additional-options "-fanalyzer-call-summaries" } */ /* { dg-additional-options "-Wno-analyzer-too-complex" } */ +/* { dg-additional-options "-Wno-analyzer-symbol-too-complex" } */ /* A lexical scanner generated by flex */ @@ -885,8 +886,7 @@ static int yy_get_next_buffer (void) } else /* Can't grow it, we don't own it. */ - b->yy_ch_buf = NULL; /* { dg-bogus "leak" "" { xfail *-*-* } } */ - /* TODO: leak false positive: PR analyzer/103546. */ + b->yy_ch_buf = NULL; /* { dg-bogus "leak" "PR analyzer/103546" } */ if ( ! b->yy_ch_buf ) YY_FATAL_ERROR( diff --git a/gcc/testsuite/c-c++-common/analyzer/flex-without-call-summaries.c b/gcc/testsuite/c-c++-common/analyzer/flex-without-call-summaries.c index 5369f7685c2..b1c23312137 100644 --- a/gcc/testsuite/c-c++-common/analyzer/flex-without-call-summaries.c +++ b/gcc/testsuite/c-c++-common/analyzer/flex-without-call-summaries.c @@ -886,8 +886,7 @@ static int yy_get_next_buffer (void) } else /* Can't grow it, we don't own it. */ - b->yy_ch_buf = NULL; /* { dg-bogus "leak" "" { xfail *-*-* } } */ - /* TODO: leak false positive: PR analyzer/103546. */ + b->yy_ch_buf = NULL; /* { dg-bogus "leak" "PR analyzer/103546" */ if ( ! b->yy_ch_buf ) YY_FATAL_ERROR( diff --git a/gcc/testsuite/c-c++-common/analyzer/infinite-recursion-3.c b/gcc/testsuite/c-c++-common/analyzer/infinite-recursion-3.c index 68c4fa396ca..2ae20a1108a 100644 --- a/gcc/testsuite/c-c++-common/analyzer/infinite-recursion-3.c +++ b/gcc/testsuite/c-c++-common/analyzer/infinite-recursion-3.c @@ -1,4 +1,4 @@ -/* { dg-additional-options "-fno-analyzer-call-summaries -Wno-analyzer-too-complex" } */ +/* { dg-additional-options "-fno-analyzer-call-summaries -Wno-analyzer-too-complex -Wno-analyzer-symbol-too-complex" } */ struct node { diff --git a/gcc/testsuite/c-c++-common/analyzer/null-deref-pr108251-smp_fetch_ssl_fc_has_early-O2.c b/gcc/testsuite/c-c++-common/analyzer/null-deref-pr108251-smp_fetch_ssl_fc_has_early-O2.c index c46ffe91a6b..c1c8e6f6a39 100644 --- a/gcc/testsuite/c-c++-common/analyzer/null-deref-pr108251-smp_fetch_ssl_fc_has_early-O2.c +++ b/gcc/testsuite/c-c++-common/analyzer/null-deref-pr108251-smp_fetch_ssl_fc_has_early-O2.c @@ -1,7 +1,7 @@ /* Reduced from haproxy's src/ssl_sample.c */ /* { dg-require-effective-target ptr_eq_long } */ -/* { dg-additional-options "-O2" } */ +/* { dg-additional-options "-O2 -Wno-analyzer-symbol-too-complex" } */ union sample_value { long long int sint; diff --git a/gcc/testsuite/c-c++-common/analyzer/null-deref-pr108251-smp_fetch_ssl_fc_has_early.c b/gcc/testsuite/c-c++-common/analyzer/null-deref-pr108251-smp_fetch_ssl_fc_has_early.c index ef34a76c50d..c5f1fa42e6f 100644 --- a/gcc/testsuite/c-c++-common/analyzer/null-deref-pr108251-smp_fetch_ssl_fc_has_early.c +++ b/gcc/testsuite/c-c++-common/analyzer/null-deref-pr108251-smp_fetch_ssl_fc_has_early.c @@ -1,6 +1,7 @@ /* Reduced from haproxy's src/ssl_sample.c */ /* { dg-require-effective-target ptr_eq_long } */ +/* { dg-additional-options "-Wno-analyzer-symbol-too-complex" } */ union sample_value { long long int sint; diff --git a/gcc/testsuite/c-c++-common/analyzer/null-deref-pr108400-SoftEtherVPN-WebUi.c b/gcc/testsuite/c-c++-common/analyzer/null-deref-pr108400-SoftEtherVPN-WebUi.c index 1151d622519..9dcf7aa31f1 100644 --- a/gcc/testsuite/c-c++-common/analyzer/null-deref-pr108400-SoftEtherVPN-WebUi.c +++ b/gcc/testsuite/c-c++-common/analyzer/null-deref-pr108400-SoftEtherVPN-WebUi.c @@ -1,4 +1,6 @@ /* Reduced from SoftEtherVPN's src/Cedar/WebUI.c. */ +/* { dg-additional-options "-Wno-analyzer-symbol-too-complex" } */ + #include "../../gcc.dg/analyzer/analyzer-decls.h" typedef int (COMPARE)(void *p1, void *p2); typedef unsigned int UINT; diff --git a/gcc/testsuite/c-c++-common/analyzer/null-deref-pr108806-qemu.c b/gcc/testsuite/c-c++-common/analyzer/null-deref-pr108806-qemu.c index f7f6923927f..16ef6574d2f 100644 --- a/gcc/testsuite/c-c++-common/analyzer/null-deref-pr108806-qemu.c +++ b/gcc/testsuite/c-c++-common/analyzer/null-deref-pr108806-qemu.c @@ -1,5 +1,7 @@ /* Reduced from qemu-7.2.0's hw/intc/omap_intc.c */ +/* { dg-additional-options "-Wno-analyzer-symbol-too-complex" } */ + #include "../../gcc.dg/analyzer/analyzer-decls.h" typedef unsigned char __uint8_t; diff --git a/gcc/testsuite/c-c++-common/analyzer/null-deref-pr108830.c b/gcc/testsuite/c-c++-common/analyzer/null-deref-pr108830.c index 0c95148ebd5..1cb1ebe65f9 100644 --- a/gcc/testsuite/c-c++-common/analyzer/null-deref-pr108830.c +++ b/gcc/testsuite/c-c++-common/analyzer/null-deref-pr108830.c @@ -1,6 +1,6 @@ /* Reduced from apr-1.7.0/tables/apr_hash.c: 'apr_hash_merge' */ -/* { dg-additional-options "-Wno-analyzer-too-complex" } */ +/* { dg-additional-options "-Wno-analyzer-too-complex -Wno-analyzer-symbol-too-complex" } */ #include "../../gcc.dg/analyzer/analyzer-decls.h" diff --git a/gcc/testsuite/c-c++-common/analyzer/pr94596.c b/gcc/testsuite/c-c++-common/analyzer/pr94596.c index 10ea549924e..0d6240941d7 100644 --- a/gcc/testsuite/c-c++-common/analyzer/pr94596.c +++ b/gcc/testsuite/c-c++-common/analyzer/pr94596.c @@ -17,6 +17,9 @@ */ #include "../../gcc.dg/analyzer/analyzer-decls.h" + +/* { dg-additional-options "-Wno-analyzer-symbol-too-complex" } */ + typedef __SIZE_TYPE__ size_t; #ifndef __cplusplus diff --git a/gcc/testsuite/c-c++-common/analyzer/strtok-2.c b/gcc/testsuite/c-c++-common/analyzer/strtok-2.c index 0336bf0cfe9..f34b4a7198a 100644 --- a/gcc/testsuite/c-c++-common/analyzer/strtok-2.c +++ b/gcc/testsuite/c-c++-common/analyzer/strtok-2.c @@ -1,3 +1,5 @@ +/* { dg-additional-options "-Wno-analyzer-symbol-too-complex" } */ + #include "../../gcc.dg/analyzer/analyzer-decls.h" extern char *strtok (char *str, const char *delim) diff --git a/gcc/testsuite/c-c++-common/analyzer/strtok-4.c b/gcc/testsuite/c-c++-common/analyzer/strtok-4.c index b6b7d49e3c3..793c7fcb7f4 100644 --- a/gcc/testsuite/c-c++-common/analyzer/strtok-4.c +++ b/gcc/testsuite/c-c++-common/analyzer/strtok-4.c @@ -1,3 +1,5 @@ +/* { dg-additional-options "-Wno-analyzer-too-complex -Wno-analyzer-symbol-too-complex" } */ + #include "../../gcc.dg/analyzer/analyzer-decls.h" extern char *strtok (char *str, const char *delim); diff --git a/gcc/testsuite/c-c++-common/analyzer/strtok-cppreference.c b/gcc/testsuite/c-c++-common/analyzer/strtok-cppreference.c index a2e912341d6..a396c643f11 100644 --- a/gcc/testsuite/c-c++-common/analyzer/strtok-cppreference.c +++ b/gcc/testsuite/c-c++-common/analyzer/strtok-cppreference.c @@ -11,6 +11,8 @@ should be released under an equivalent license so that everyone could benefit from the modified versions. " */ +/* { dg-additional-options " -Wno-analyzer-too-complex -Wno-analyzer-symbol-too-complex" } */ + #define __STDC_WANT_LIB_EXT1__ 0 #include #include diff --git a/gcc/testsuite/gcc.dg/analyzer/analyzer.exp b/gcc/testsuite/gcc.dg/analyzer/analyzer.exp index cedf3c0466f..ba5aa680fc7 100644 --- a/gcc/testsuite/gcc.dg/analyzer/analyzer.exp +++ b/gcc/testsuite/gcc.dg/analyzer/analyzer.exp @@ -30,7 +30,7 @@ if [info exists DEFAULT_CFLAGS] then { } # If a testcase doesn't have special options, use these. -set DEFAULT_CFLAGS "-fanalyzer -Wanalyzer-too-complex -fanalyzer-call-summaries" +set DEFAULT_CFLAGS "-fanalyzer -Wanalyzer-too-complex -Wanalyzer-symbol-too-complex -fanalyzer-call-summaries" if { [istarget "*-*-darwin*" ] } { # On macOS, system headers redefine by default some macros (memcpy, diff --git a/gcc/testsuite/gcc.dg/analyzer/attr-const-3.c b/gcc/testsuite/gcc.dg/analyzer/attr-const-3.c index fc8527a5d0e..11238a77a65 100644 --- a/gcc/testsuite/gcc.dg/analyzer/attr-const-3.c +++ b/gcc/testsuite/gcc.dg/analyzer/attr-const-3.c @@ -1,7 +1,7 @@ /* Verify that we handle unknown values passed to __attribute__ ((const)) (by imposing a complexity limit). */ -/* { dg-additional-options "--param analyzer-max-svalue-depth=4" } */ +/* { dg-additional-options "--param analyzer-max-svalue-depth=4 -Wno-analyzer-symbol-too-complex" } */ #include "analyzer-decls.h" diff --git a/gcc/testsuite/gcc.dg/analyzer/call-summaries-pr107072.c b/gcc/testsuite/gcc.dg/analyzer/call-summaries-pr107072.c index 6e583d0228f..f59318b428f 100644 --- a/gcc/testsuite/gcc.dg/analyzer/call-summaries-pr107072.c +++ b/gcc/testsuite/gcc.dg/analyzer/call-summaries-pr107072.c @@ -1,5 +1,5 @@ /* { dg-require-effective-target int32plus } */ -/* { dg-additional-options "-fanalyzer-call-summaries --param analyzer-min-snodes-for-call-summary=0" } */ +/* { dg-additional-options "-fanalyzer-call-summaries --param analyzer-min-snodes-for-call-summary=0 -Wno-analyzer-symbol-too-complex" } */ /* There need to be at least two calls to a function for the call-summarization code to be used. diff --git a/gcc/testsuite/gcc.dg/analyzer/doom-s_sound-pr108867.c b/gcc/testsuite/gcc.dg/analyzer/doom-s_sound-pr108867.c index ae58f03d3b3..fdc21a2bec3 100644 --- a/gcc/testsuite/gcc.dg/analyzer/doom-s_sound-pr108867.c +++ b/gcc/testsuite/gcc.dg/analyzer/doom-s_sound-pr108867.c @@ -1,6 +1,6 @@ /* Reduced from Doom's linuxdoom-1.10/s_sound.c, which is GPLv2 or later. */ -/* { dg-additional-options "-fno-analyzer-call-summaries -Wno-analyzer-too-complex" } */ +/* { dg-additional-options "-fno-analyzer-call-summaries -Wno-analyzer-too-complex -Wno-analyzer-symbol-too-complex" } */ /* { dg-require-effective-target size32plus } */ typedef struct _IO_FILE FILE; diff --git a/gcc/testsuite/gcc.dg/analyzer/explode-4.c b/gcc/testsuite/gcc.dg/analyzer/explode-4.c index 874b1e9c300..a98dfb56bf5 100644 --- a/gcc/testsuite/gcc.dg/analyzer/explode-4.c +++ b/gcc/testsuite/gcc.dg/analyzer/explode-4.c @@ -3,7 +3,7 @@ conjured_svalues whilst handling a long chain of external function calls. */ -/* { dg-additional-options "-Wno-implicit-function-declaration -Wno-int-conversion -Wno-analyzer-too-complex" } */ +/* { dg-additional-options "-Wno-implicit-function-declaration -Wno-int-conversion -Wno-analyzer-too-complex -Wno-analyzer-symbol-too-complex" } */ #define NULL ((void *)0) typedef unsigned char uint8_t; diff --git a/gcc/testsuite/gcc.dg/analyzer/null-deref-pr102671-1.c b/gcc/testsuite/gcc.dg/analyzer/null-deref-pr102671-1.c index 3fe061bdbd8..65c7bac1f7e 100644 --- a/gcc/testsuite/gcc.dg/analyzer/null-deref-pr102671-1.c +++ b/gcc/testsuite/gcc.dg/analyzer/null-deref-pr102671-1.c @@ -1,5 +1,5 @@ /* { dg-require-effective-target ptr_eq_long } */ -/* { dg-additional-options "-O2 -Wno-shift-count-overflow" } */ +/* { dg-additional-options "-O2 -Wno-shift-count-overflow -Wno-analyzer-symbol-too-complex" } */ struct lisp; union vectorlike_header { long size; }; diff --git a/gcc/testsuite/gcc.dg/analyzer/null-deref-pr105755.c b/gcc/testsuite/gcc.dg/analyzer/null-deref-pr105755.c index 2b0ba292e00..5375b4dd6f6 100644 --- a/gcc/testsuite/gcc.dg/analyzer/null-deref-pr105755.c +++ b/gcc/testsuite/gcc.dg/analyzer/null-deref-pr105755.c @@ -1,5 +1,5 @@ /* { dg-require-effective-target int32plus } */ -/* { dg-additional-options "-Wno-analyzer-too-complex -O2" } */ +/* { dg-additional-options "-Wno-analyzer-too-complex -Wno-analyzer-symbol-too-complex -O2" } */ typedef long int ptrdiff_t; typedef long int EMACS_INT; diff --git a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-curl.c b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-curl.c index e34b572966e..d14661cbc6a 100644 --- a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-curl.c +++ b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-curl.c @@ -1,4 +1,4 @@ -/* { dg-additional-options "-O2" } */ +/* { dg-additional-options "-O2 -Wno-analyzer-symbol-too-complex" } */ #include /* Reduced from curl lib/smb.c. */ diff --git a/gcc/testsuite/gcc.dg/analyzer/pr101503.c b/gcc/testsuite/gcc.dg/analyzer/pr101503.c index 16faf6eac2f..cc4d801d8a6 100644 --- a/gcc/testsuite/gcc.dg/analyzer/pr101503.c +++ b/gcc/testsuite/gcc.dg/analyzer/pr101503.c @@ -1,4 +1,4 @@ -/* { dg-additional-options "--param analyzer-max-svalue-depth=0" } */ +/* { dg-additional-options "--param analyzer-max-svalue-depth=0 -Wno-analyzer-symbol-too-complex" } */ int val; diff --git a/gcc/testsuite/gcc.dg/analyzer/pr103892.c b/gcc/testsuite/gcc.dg/analyzer/pr103892.c index d16cd83c472..a17c3b7e119 100644 --- a/gcc/testsuite/gcc.dg/analyzer/pr103892.c +++ b/gcc/testsuite/gcc.dg/analyzer/pr103892.c @@ -1,4 +1,4 @@ -/* { dg-additional-options "-O2" } */ +/* { dg-additional-options "-O2 -Wno-analyzer-too-complex -Wno-analyzer-symbol-too-complex" } */ /* C only: C++ FE optimizes argstr_get_word completely away and therefore the number of SN diminishes compared to C, diff --git a/gcc/testsuite/gcc.dg/analyzer/pr94851-4.c b/gcc/testsuite/gcc.dg/analyzer/pr94851-4.c index 2a15a5d7f5b..a5130c59cb0 100644 --- a/gcc/testsuite/gcc.dg/analyzer/pr94851-4.c +++ b/gcc/testsuite/gcc.dg/analyzer/pr94851-4.c @@ -1,4 +1,4 @@ -/* { dg-additional-options "-O2" } */ +/* { dg-additional-options "-O2 -Wno-analyzer-symbol-too-complex" } */ #include diff --git a/gcc/testsuite/gcc.dg/analyzer/pr96860-1.c b/gcc/testsuite/gcc.dg/analyzer/pr96860-1.c index 8f298ec04e7..8be30b3a6da 100644 --- a/gcc/testsuite/gcc.dg/analyzer/pr96860-1.c +++ b/gcc/testsuite/gcc.dg/analyzer/pr96860-1.c @@ -1,5 +1,5 @@ /* { dg-require-effective-target int128 } */ -/* { dg-additional-options "--param analyzer-max-svalue-depth=0" } */ +/* { dg-additional-options "--param analyzer-max-svalue-depth=0 -Wno-analyzer-symbol-too-complex" } */ void x7 (void) { diff --git a/gcc/testsuite/gcc.dg/analyzer/pr96860-2.c b/gcc/testsuite/gcc.dg/analyzer/pr96860-2.c index 90a818cb283..d12b9a1e1fa 100644 --- a/gcc/testsuite/gcc.dg/analyzer/pr96860-2.c +++ b/gcc/testsuite/gcc.dg/analyzer/pr96860-2.c @@ -1,4 +1,4 @@ -/* { dg-additional-options "--param analyzer-max-svalue-depth=0" } */ +/* { dg-additional-options "--param analyzer-max-svalue-depth=0 -Wno-analyzer-symbol-too-complex" } */ void x7 (void) { diff --git a/gcc/testsuite/gcc.dg/analyzer/pr98918.c b/gcc/testsuite/gcc.dg/analyzer/pr98918.c index ac626ba1f30..c3bbce3e6ec 100644 --- a/gcc/testsuite/gcc.dg/analyzer/pr98918.c +++ b/gcc/testsuite/gcc.dg/analyzer/pr98918.c @@ -1,3 +1,5 @@ +/* { dg-additional-options "-Wno-analyzer-symbol-too-complex" } */ + #include struct marker { diff --git a/gcc/testsuite/gcc.dg/analyzer/pr99044-2.c b/gcc/testsuite/gcc.dg/analyzer/pr99044-2.c index fd71d35d7e4..f7badb92f44 100644 --- a/gcc/testsuite/gcc.dg/analyzer/pr99044-2.c +++ b/gcc/testsuite/gcc.dg/analyzer/pr99044-2.c @@ -1,3 +1,5 @@ +/* { dg-additional-options "-Wno-analyzer-symbol-too-complex" } */ + struct node { struct node *next; diff --git a/gcc/testsuite/gcc.dg/analyzer/uninit-pr108806-qemu.c b/gcc/testsuite/gcc.dg/analyzer/uninit-pr108806-qemu.c index 34fe802f495..09272011128 100644 --- a/gcc/testsuite/gcc.dg/analyzer/uninit-pr108806-qemu.c +++ b/gcc/testsuite/gcc.dg/analyzer/uninit-pr108806-qemu.c @@ -5,6 +5,8 @@ struct omap_intr_handler_bank_s* bank; */ +/* { dg-additional-options "-Wno-analyzer-symbol-too-complex" } */ + typedef unsigned char __uint8_t; typedef unsigned int __uint32_t; typedef unsigned long int __uint64_t; diff --git a/gcc/testsuite/gcc.dg/analyzer/use-after-free.c b/gcc/testsuite/gcc.dg/analyzer/use-after-free.c index d7e4bc2c6ca..76a85f56335 100644 --- a/gcc/testsuite/gcc.dg/analyzer/use-after-free.c +++ b/gcc/testsuite/gcc.dg/analyzer/use-after-free.c @@ -1,3 +1,5 @@ +/* { dg-additional-options "-Wno-analyzer-too-complex -Wno-analyzer-symbol-too-complex" } */ + #include #include "analyzer-decls.h" diff --git a/gcc/testsuite/gcc.dg/plugin/plugin.exp b/gcc/testsuite/gcc.dg/plugin/plugin.exp index f098a327d31..f0b4bb7a051 100644 --- a/gcc/testsuite/gcc.dg/plugin/plugin.exp +++ b/gcc/testsuite/gcc.dg/plugin/plugin.exp @@ -162,7 +162,11 @@ set plugin_test_list [list \ taint-CVE-2011-0521-5.c \ taint-CVE-2011-0521-5-fixed.c \ taint-CVE-2011-0521-6.c \ - taint-antipatterns-1.c } \ + taint-antipatterns-1.c \ + taint-pr112850.c \ + taint-pr112850-precise.c \ + taint-pr112850-too-complex.c \ + taint-pr112850-unsanitized.c } \ { analyzer_cpython_plugin.c \ cpython-plugin-test-no-Python-h.c \ cpython-plugin-test-PyList_Append.c \ diff --git a/gcc/testsuite/gcc.dg/plugin/taint-CVE-2011-0521-4.c b/gcc/testsuite/gcc.dg/plugin/taint-CVE-2011-0521-4.c index 06b3468fca5..e268a8eab8f 100644 --- a/gcc/testsuite/gcc.dg/plugin/taint-CVE-2011-0521-4.c +++ b/gcc/testsuite/gcc.dg/plugin/taint-CVE-2011-0521-4.c @@ -32,9 +32,9 @@ int test_1(struct file *file, unsigned int cmd, unsigned long arg) if (info->num > 1) return -EINVAL; av7110->ci_slot[info->num].num = info->num; /* { dg-warning "attacker-controlled value" } */ - av7110->ci_slot[info->num].type = FW_CI_LL_SUPPORT(av7110->arm_app) ? /* { dg-warning "attacker-controlled value" } */ + av7110->ci_slot[info->num].type = FW_CI_LL_SUPPORT(av7110->arm_app) ? CA_CI_LINK : CA_CI; - memcpy(info, &av7110->ci_slot[info->num], sizeof(ca_slot_info_t)); /* { dg-warning "attacker-controlled value" } */ + memcpy(info, &av7110->ci_slot[info->num], sizeof(ca_slot_info_t)); } copy_to_user((void __user *)arg, parg, sizeof(sbuf)); diff --git a/gcc/testsuite/gcc.dg/plugin/taint-CVE-2011-0521-5-fixed.c b/gcc/testsuite/gcc.dg/plugin/taint-CVE-2011-0521-5-fixed.c index 076ada3a20a..b39e693da63 100644 --- a/gcc/testsuite/gcc.dg/plugin/taint-CVE-2011-0521-5-fixed.c +++ b/gcc/testsuite/gcc.dg/plugin/taint-CVE-2011-0521-5-fixed.c @@ -39,8 +39,7 @@ int test_1(struct file *file, unsigned int cmd, unsigned long arg) av7110->ci_slot[info->num].num = info->num; av7110->ci_slot[info->num].type = FW_CI_LL_SUPPORT(av7110->arm_app) ? CA_CI_LINK : CA_CI; - memcpy(info, &av7110->ci_slot[info->num], sizeof(ca_slot_info_t)); /* { dg-bogus "use of attacker-controlled value in array lookup without bounds checking" "" { xfail *-*-* } } */ - // FIXME: why the above false +ve? + memcpy(info, &av7110->ci_slot[info->num], sizeof(ca_slot_info_t)); /* { dg-bogus "use of attacker-controlled value in array lookup without bounds checking" } */ } copy_to_user((void __user *)arg, &sbuf, sizeof(sbuf)); diff --git a/gcc/testsuite/gcc.dg/plugin/taint-CVE-2011-0521-5.c b/gcc/testsuite/gcc.dg/plugin/taint-CVE-2011-0521-5.c index e27ee469df8..fe216c0a3c4 100644 --- a/gcc/testsuite/gcc.dg/plugin/taint-CVE-2011-0521-5.c +++ b/gcc/testsuite/gcc.dg/plugin/taint-CVE-2011-0521-5.c @@ -37,9 +37,9 @@ int test_1(struct file *file, unsigned int cmd, unsigned long arg) __analyzer_dump_state ("taint", info->num); /* { dg-warning "has_ub" } */ av7110->ci_slot[info->num].num = info->num; /* { dg-warning "use of attacker-controlled value '\\*info\\.num' in array lookup without checking for negative" } */ - av7110->ci_slot[info->num].type = FW_CI_LL_SUPPORT(av7110->arm_app) ? /* { dg-warning "use of attacker-controlled value '\\*info\\.num' in array lookup without checking for negative" } */ + av7110->ci_slot[info->num].type = FW_CI_LL_SUPPORT(av7110->arm_app) ? CA_CI_LINK : CA_CI; - memcpy(info, &av7110->ci_slot[info->num], sizeof(ca_slot_info_t)); /* { dg-warning "use of attacker-controlled value in array lookup without bounds checking" } */ + memcpy(info, &av7110->ci_slot[info->num], sizeof(ca_slot_info_t)); } copy_to_user((void __user *)arg, &sbuf, sizeof(sbuf)); diff --git a/gcc/testsuite/gcc.dg/plugin/taint-CVE-2011-0521-6.c b/gcc/testsuite/gcc.dg/plugin/taint-CVE-2011-0521-6.c index fea70ee5761..5b68de32470 100644 --- a/gcc/testsuite/gcc.dg/plugin/taint-CVE-2011-0521-6.c +++ b/gcc/testsuite/gcc.dg/plugin/taint-CVE-2011-0521-6.c @@ -34,9 +34,9 @@ int test_1(struct file *file, unsigned int cmd, unsigned long arg) //__analyzer_break (); av7110->ci_slot[info->num].num = info->num; /* { dg-warning "use of attacker-controlled value '\\*info\\.num' in array lookup without bounds checking" } */ - av7110->ci_slot[info->num].type = FW_CI_LL_SUPPORT(av7110->arm_app) ? /* { dg-warning "use of attacker-controlled value '\\*info\\.num' in array lookup without bounds checking" } */ + av7110->ci_slot[info->num].type = FW_CI_LL_SUPPORT(av7110->arm_app) ? CA_CI_LINK : CA_CI; - memcpy(info, &av7110->ci_slot[info->num], sizeof(ca_slot_info_t)); /* { dg-warning "use of attacker-controlled value in array lookup without bounds checking" } */ + memcpy(info, &av7110->ci_slot[info->num], sizeof(ca_slot_info_t)); } copy_to_user((void __user *)arg, &sbuf, sizeof(sbuf)); diff --git a/gcc/testsuite/gcc.dg/plugin/taint-pr112850-precise.c b/gcc/testsuite/gcc.dg/plugin/taint-pr112850-precise.c new file mode 100644 index 00000000000..558f0fb1a8a --- /dev/null +++ b/gcc/testsuite/gcc.dg/plugin/taint-pr112850-precise.c @@ -0,0 +1,50 @@ +/* Reduced from false positive in Linux kernel in sound/core/rawmidi.c. + + Use a value of --param=analyzer-max-svalue-depth= high enough to avoid + UNKNOWN svalues; make sure we don't get false positives with this case. */ + +/* { dg-do compile } */ +/* { dg-options "-fanalyzer -O2 -Wanalyzer-symbol-too-complex --param=analyzer-max-svalue-depth=13" } */ +/* { dg-require-effective-target analyzer } */ + +typedef unsigned long __kernel_ulong_t; +typedef __kernel_ulong_t __kernel_size_t; +typedef __kernel_size_t size_t; +typedef unsigned int gfp_t; + +extern unsigned long copy_from_user(void* to, const void* from, unsigned long n); + +extern +__attribute__((__alloc_size__(1))) +__attribute__((__malloc__)) void* +kvzalloc(size_t size, gfp_t flags); + +struct snd_rawmidi_params +{ + int stream; + size_t buffer_size; +}; + +char *newbuf; + +static int +resize_runtime_buffer(struct snd_rawmidi_params* params) +{ + if (params->buffer_size < 32 || params->buffer_size > 1024L * 1024L) /* { dg-bogus "symbol too complicated" } */ + return -22; + newbuf = kvzalloc(params->buffer_size, /* { dg-bogus "use of attacker-controlled value '\\*params.buffer_size' as allocation size without upper-bounds checking" "PR analyzer/112850" } */ + (((gfp_t)(0x400u | 0x800u)) | ((gfp_t)0x40u) | ((gfp_t)0x80u))); + if (!newbuf) + return -12; + return 0; +} + +long +snd_rawmidi_ioctl(unsigned long arg) +{ + void* argp = (void*)arg; + struct snd_rawmidi_params params; + if (copy_from_user(¶ms, argp, sizeof(struct snd_rawmidi_params))) + return -14; + return resize_runtime_buffer(¶ms); +} diff --git a/gcc/testsuite/gcc.dg/plugin/taint-pr112850-too-complex.c b/gcc/testsuite/gcc.dg/plugin/taint-pr112850-too-complex.c new file mode 100644 index 00000000000..2a4ee8197c3 --- /dev/null +++ b/gcc/testsuite/gcc.dg/plugin/taint-pr112850-too-complex.c @@ -0,0 +1,51 @@ +/* Reduced from false positive in Linux kernel in sound/core/rawmidi.c. + + With --param=analyzer-max-svalue-depth=12, the value being compared + at the sanitization is too complex and becomes UNKNOWN; make sure + this doesn't lead to a false positive. */ + +/* { dg-do compile } */ +/* { dg-options "-fanalyzer -O2 -Wanalyzer-symbol-too-complex --param=analyzer-max-svalue-depth=12" } */ +/* { dg-require-effective-target analyzer } */ + +typedef unsigned long __kernel_ulong_t; +typedef __kernel_ulong_t __kernel_size_t; +typedef __kernel_size_t size_t; +typedef unsigned int gfp_t; + +extern unsigned long copy_from_user(void* to, const void* from, unsigned long n); + +extern +__attribute__((__alloc_size__(1))) +__attribute__((__malloc__)) void* +kvzalloc(size_t size, gfp_t flags); + +struct snd_rawmidi_params +{ + int stream; + size_t buffer_size; +}; + +char *newbuf; + +static int +resize_runtime_buffer(struct snd_rawmidi_params* params) +{ + if (params->buffer_size < 32 || params->buffer_size > 1024L * 1024L) /* { dg-warning "symbol too complicated" } */ + return -22; + newbuf = kvzalloc(params->buffer_size, /* { dg-bogus "use of attacker-controlled value '\\*params.buffer_size' as allocation size without upper-bounds checking" "PR analyzer/112850" } */ + (((gfp_t)(0x400u | 0x800u)) | ((gfp_t)0x40u) | ((gfp_t)0x80u))); + if (!newbuf) + return -12; + return 0; +} + +long +snd_rawmidi_ioctl(unsigned long arg) +{ + void* argp = (void*)arg; + struct snd_rawmidi_params params; + if (copy_from_user(¶ms, argp, sizeof(struct snd_rawmidi_params))) + return -14; + return resize_runtime_buffer(¶ms); +} diff --git a/gcc/testsuite/gcc.dg/plugin/taint-pr112850-unsanitized.c b/gcc/testsuite/gcc.dg/plugin/taint-pr112850-unsanitized.c new file mode 100644 index 00000000000..e46fcb6c8a1 --- /dev/null +++ b/gcc/testsuite/gcc.dg/plugin/taint-pr112850-unsanitized.c @@ -0,0 +1,50 @@ +/* Reduced from false positive in Linux kernel in sound/core/rawmidi.c, + with sanitization removed to make it a true positive. + + Verify that we detect this (with default params). */ + +/* { dg-do compile } */ +/* { dg-options "-fanalyzer -O2 -Wanalyzer-too-complex" } */ +/* { dg-require-effective-target analyzer } */ + +typedef unsigned long __kernel_ulong_t; +typedef __kernel_ulong_t __kernel_size_t; +typedef __kernel_size_t size_t; +typedef unsigned int gfp_t; + +extern unsigned long copy_from_user(void* to, const void* from, unsigned long n); + +extern +__attribute__((__alloc_size__(1))) +__attribute__((__malloc__)) void* +kvzalloc(size_t size, gfp_t flags); + +struct snd_rawmidi_params +{ + int stream; + size_t buffer_size; +}; + +char *newbuf; + +static int +resize_runtime_buffer(struct snd_rawmidi_params* params) +{ + /* No sanitization, so we should complain. */ + + newbuf = kvzalloc(params->buffer_size, /* { dg-warning "use of attacker-controlled value '\\*params.buffer_size' as allocation size without upper-bounds checking" "PR analyzer/112850" } */ + (((gfp_t)(0x400u | 0x800u)) | ((gfp_t)0x40u) | ((gfp_t)0x80u))); + if (!newbuf) + return -12; + return 0; +} + +long +snd_rawmidi_ioctl(unsigned long arg) +{ + void* argp = (void*)arg; + struct snd_rawmidi_params params; + if (copy_from_user(¶ms, argp, sizeof(struct snd_rawmidi_params))) + return -14; + return resize_runtime_buffer(¶ms); +} diff --git a/gcc/testsuite/gcc.dg/plugin/taint-pr112850.c b/gcc/testsuite/gcc.dg/plugin/taint-pr112850.c new file mode 100644 index 00000000000..6fa1d0f9bd4 --- /dev/null +++ b/gcc/testsuite/gcc.dg/plugin/taint-pr112850.c @@ -0,0 +1,47 @@ +/* Reduced from false positive in Linux kernel in sound/core/rawmidi.c. */ + +/* { dg-do compile } */ +/* { dg-options "-fanalyzer -O2 -Wanalyzer-symbol-too-complex" } */ +/* { dg-require-effective-target analyzer } */ + +typedef unsigned long __kernel_ulong_t; +typedef __kernel_ulong_t __kernel_size_t; +typedef __kernel_size_t size_t; +typedef unsigned int gfp_t; + +extern unsigned long copy_from_user(void* to, const void* from, unsigned long n); + +extern +__attribute__((__alloc_size__(1))) +__attribute__((__malloc__)) void* +kvzalloc(size_t size, gfp_t flags); + +struct snd_rawmidi_params +{ + int stream; + size_t buffer_size; +}; + +char *newbuf; + +static int +resize_runtime_buffer(struct snd_rawmidi_params* params) +{ + if (params->buffer_size < 32 || params->buffer_size > 1024L * 1024L) /* { dg-bogus "symbol too complicated" } */ + return -22; + newbuf = kvzalloc(params->buffer_size, /* { dg-bogus "use of attacker-controlled value '\\*params.buffer_size' as allocation size without upper-bounds checking" "PR analyzer/112850" } */ + (((gfp_t)(0x400u | 0x800u)) | ((gfp_t)0x40u) | ((gfp_t)0x80u))); + if (!newbuf) + return -12; + return 0; +} + +long +snd_rawmidi_ioctl(unsigned long arg) +{ + void* argp = (void*)arg; + struct snd_rawmidi_params params; + if (copy_from_user(¶ms, argp, sizeof(struct snd_rawmidi_params))) + return -14; + return resize_runtime_buffer(¶ms); +}