From patchwork Sat Jul 2 11:33:23 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alberto Faria X-Patchwork-Id: 1651460 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=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=LI1AKHd/; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4LZqjZ0rNqz9s07 for ; Sat, 2 Jul 2022 21:34:40 +1000 (AEST) Received: from localhost ([::1]:58668 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1o7bOW-0002rM-Sy for incoming@patchwork.ozlabs.org; Sat, 02 Jul 2022 07:34:36 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:51742) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1o7bNg-0002lC-2U for qemu-devel@nongnu.org; Sat, 02 Jul 2022 07:33:44 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]:22313) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1o7bNc-0007L9-3g for qemu-devel@nongnu.org; Sat, 02 Jul 2022 07:33:42 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1656761618; 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=hLIsv8YXWSPNmuFuxOSDw1RgICEIM3EL0Jsivzvy8FE=; b=LI1AKHd/APhfbMGK+26LiipqE5AdHdOeRCpK5Qus8LjP5plvGH6pKW/suqq2c9evYxKIH6 Qn+BoGGJhciNEYDhzXoO+NUuJUfNsRjp7ATdQzNwqUnp7OCYBcskOL/EUct/SsZ3K0eRdo kWFKoX7Jf68CttGCZCT7Q+54wKz71c0= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-450-VdCQA_HbOrC79CCgJ82ZjQ-1; Sat, 02 Jul 2022 07:33:37 -0400 X-MC-Unique: VdCQA_HbOrC79CCgJ82ZjQ-1 Received: from smtp.corp.redhat.com (int-mx09.intmail.prod.int.rdu2.redhat.com [10.11.54.9]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 03936801231; Sat, 2 Jul 2022 11:33:37 +0000 (UTC) Received: from fedora.redhat.com (unknown [10.39.194.114]) by smtp.corp.redhat.com (Postfix) with ESMTP id B70C0492C3B; Sat, 2 Jul 2022 11:33:32 +0000 (UTC) From: Alberto Faria To: qemu-devel@nongnu.org Cc: Paolo Bonzini , qemu-block@nongnu.org, "Denis V. Lunev" , Emanuele Giuseppe Esposito , Stefan Hajnoczi , Ronnie Sahlberg , Hanna Reitz , Stefano Garzarella , Kevin Wolf , Peter Xu , Alberto Garcia , John Snow , Eric Blake , Fam Zheng , Markus Armbruster , Vladimir Sementsov-Ogievskiy , Peter Lieven , Alberto Faria Subject: [RFC 0/8] Introduce an extensible static analyzer Date: Sat, 2 Jul 2022 12:33:23 +0100 Message-Id: <20220702113331.2003820-1-afaria@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.85 on 10.11.54.9 Received-SPF: pass client-ip=170.10.133.124; envelope-from=afaria@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -21 X-Spam_score: -2.2 X-Spam_bar: -- X-Spam_report: (-2.2 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.082, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" This series introduces a static analyzer for QEMU. It consists of a single static-analyzer.py script that relies on libclang's Python bindings, and provides a common framework on which arbitrary static analysis checks can be developed and run against QEMU's code base. Summary of the series: - Patch 1 adds the base static analyzer, along with a simple check that finds static functions whose return value is never used, and patch 2 fixes some occurrences of this. - Patch 3 adds a check to ensure that non-coroutine_fn functions don't perform direct calls to coroutine_fn functions, and patch 4 fixes some violations of this rule. - Patch 5 adds a check to enforce coroutine_fn restrictions on function pointers, namely around assignment and indirect calls, and patch 6 fixes some problems it detects. (Implementing this check properly is complicated, since AFAICT annotation attributes cannot be applied directly to types. This part still needs a lot of work.) - Patch 7 introduces a no_coroutine_fn marker for functions that should not be called from coroutines, makes generated_co_wrapper evaluate to no_coroutine_fn, and adds a check enforcing this rule. Patch 8 fixes some violations that it finds. The current primary motivation for this work is enforcing rules around block layer coroutines, which is why most of the series focuses on that. However, the static analyzer is intended to be sufficiently generic to satisfy other present and future QEMU static analysis needs. This is very early work-in-progress, and a lot is missing. One notable omission is build system integration, including keeping track of which translation units have been modified and need re-analyzing. Performance is bad, but there is a lot of potential for optimization, such as avoiding redundant AST traversals. Switching to C libclang is also a possibility, although Python makes it easy to quickly prototype new checks, which should encourage adoption and contributions. The script takes a path to the build directory, and any number of paths to directories or files to analyze. Example run on a 12-thread laptop: $ time ./static-analyzer.py build block block/commit.c:525:15: non-coroutine_fn function calls coroutine_fn block/nbd.c:206:5: non-coroutine_fn function calls coroutine_fn [...] block/ssh.c:1167:13: non-coroutine_fn function calls coroutine_fn block/nfs.c:229:27: non-coroutine_fn function calls coroutine_fn Analyzed 79 translation units. real 0m45.277s user 7m55.496s sys 0m1.445s You will need libclang's Python bindings to run this. On Fedora, `dnf install python3-clang` should suffice. Alberto Faria (8): Add an extensible static analyzer Drop some unused static function return values static-analyzer: Enforce coroutine_fn restrictions for direct calls Fix some direct calls from non-coroutine_fn to coroutine_fn static-analyzer: Enforce coroutine_fn restrictions on function pointers Fix some coroutine_fn indirect calls and pointer assignments block: Add no_coroutine_fn marker Avoid calls from coroutine_fn to no_coroutine_fn block/block-backend.c | 15 +- block/copy-before-write.c | 3 +- block/dirty-bitmap.c | 6 +- block/file-posix.c | 6 +- block/io.c | 34 +- block/iscsi.c | 3 +- block/parallels.c | 4 +- block/qcow2-bitmap.c | 6 +- block/qcow2-refcount.c | 2 +- block/qcow2.h | 14 +- block/qed-table.c | 2 +- block/qed.c | 8 +- block/quorum.c | 5 +- block/vmdk.c | 4 +- block/vpc.c | 9 +- block/vvfat.c | 11 +- include/block/block-common.h | 2 +- include/block/block-io.h | 7 +- include/block/block_int-common.h | 12 +- include/qemu/coroutine.h | 25 + static-analyzer.py | 890 +++++++++++++++++++++++++++++++ 21 files changed, 987 insertions(+), 81 deletions(-) create mode 100755 static-analyzer.py