Skip to content
Tags give the ability to mark specific points in history as being important
  • static-analysis-staging
    Introduce an extensible static analyzer
    
    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 ensure that operations on coroutine_fn
        pointers make sense, like assignment and indirect calls, and patch 6
        fixes some problems detected by the check. (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, but 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.