<!DOCTYPE article PUBLIC "-//NLM//DTD JATS (Z39.96) Journal Archiving and Interchange DTD v1.0 20120330//EN" "JATS-archivearticle1.dtd">
<article xmlns:xlink="http://www.w3.org/1999/xlink">
  <front>
    <journal-meta>
      <journal-title-group>
        <journal-title>Proceedings of the SQAMIA</journal-title>
      </journal-title-group>
      <issn pub-type="ppub">1613-0073</issn>
    </journal-meta>
    <article-meta>
      <title-group>
        <article-title>Survey on Static Analysis Tools of Python Programs</article-title>
      </title-group>
      <contrib-group>
        <contrib contrib-type="author">
          <string-name>HRISTINA GULABOVSKA</string-name>
          <email>hristina@gulab.me</email>
        </contrib>
        <contrib contrib-type="author">
          <string-name>ZOLTA´ N PORKOL A´B</string-name>
        </contrib>
        <contrib contrib-type="author">
          <string-name>Eo¨tvo¨s Lora´ nd University</string-name>
        </contrib>
      </contrib-group>
      <pub-date>
        <year>2019</year>
      </pub-date>
      <volume>8</volume>
      <fpage>22</fpage>
      <lpage>25</lpage>
      <abstract>
        <p>Static program analysis is a popular software technique performed by automated tools for verifying large scale software systems. It works without executing the program, just analyzing the source code and applying various heuristics to nd possible errors, code smells and style discrepancies. Programming languages with strong static type system, like C, C++, Java are the usual targets of static analysis, as their type system provides additional information for the analyzer. However, there is a growing demand for applying static analysis for dynamically typed languages, like Python. In this paper we overview the current methods and tools available for static analysis on Python code base and describe some new research directions.</p>
      </abstract>
    </article-meta>
  </front>
  <body>
    <sec id="sec-1">
      <title>1. INTRODUCTION</title>
      <p>3:2</p>
    </sec>
    <sec id="sec-2">
      <title>H. Gulabovska and Z. Porkola´b</title>
      <p>
        system is still not sufficiently supported by static analysis tools. Python is very attractive
implementing Machine Learning and Cloud based applications among others, and in July 2019 it is already the
third most popular language by the
        <xref ref-type="bibr" rid="ref30">Tiobe index [Tiobe 2019</xref>
        ].
      </p>
      <p>In this paper we investigate how static analysis methods could be adapted for Python based software
systems. The authors believe that in spite of the difficulties caused by the dynamic type system many
of the methods applied for the classical languages could be utilized for Python too.</p>
      <p>This paper is organized as follows. We discuss the most important analysis techniques in Section 2.
We take a survey on static analysis tools used for the Python programming language in Section 3. In
Section 4 we evaluate the tools according some typical use cases. This paper concludes in Section 5.</p>
    </sec>
    <sec id="sec-3">
      <title>2. METHODS OF STATIC ANALYSIS</title>
      <p>In this section we will overview the most frequently used methods of static analysis for modern
programming languages. It is not our goal here to go to very deep technical details, but we intend to
compare the advantages and the limitations of each methods. We will cover only methods which are
(1) implemented at least for one programming language (2) based only on the source code, i.e. we will
not discuss methods, where the user has to supply invariants or semantics of the program.</p>
      <p>All static methods apply heuristics, which means that sometimes they may underestimate or
overestimate the program behavior. In practice this means static analysis tools sometimes do not report
existing issues which situation is called as false negative, and sometimes they report correct code
erroneously as a problem, which is called as false positive. Therefore, all reports need to be reviewed by a
professional who has to decide whether the report stands.</p>
      <p>Here we face an interesting human challenge. Unlike the theoretical program verification methods,
we do not strive to minimize the false negatives, i.e. try to find all possible issues, but we aspire to
minimize the false positives. If the tool produces a large number of false positives, the necessary review
process takes unreasonable large effort by the developers, meanwhile they also lose their trust in the
analyser tool.</p>
    </sec>
    <sec id="sec-4">
      <title>2.1 Pattern matching</title>
      <p>In this method the source code is first converted to a canonical format, i.e. all branches are converted
to simple one liner if-else format, loops to a simple while-command format, comparison expressions
are reordered to less-then and less-equal format. The developers express the various issues to detect
as regular expressions. The tool tries to match this regular expression to every line in the source and
reports each matches.</p>
      <p>Earlier versions of CppCheck [Marjama¨ ki 2013] used pattern matching to find issues in C and C++
programs. Experiences with the tool report relatively low level of false positives, as well-written regular
expressions have easy to predict results. Apart of the low false positive rate, additional advantage of
pattern matching is working on non-complete source, even if we cannot recompile the software system.
This means that the method can be applied to software under construction, or when we have only
partial information on the system.</p>
      <p>In the same time this method has several disadvantages too. As regular expressions are context free
grammars, we are restricted to find issues based on information in the close locality of the problem.
Having no knowledge about declarations we could not use type information. We cannot use name and
overload resolution, cannot follow function calls and generally we have weak understanding on the
overall program structure. As a summary, we can consider pattern matching based approaches as easy
entry-level methods [Moene 2014].</p>
    </sec>
    <sec id="sec-5">
      <title>2.2 AST matchers</title>
      <p>
        To provide the necessary context information to the analysis we can use the Abstract Syntax Tree
(AST). AST is the usual internal data structure used by the front-end phase of the compilers [
        <xref ref-type="bibr" rid="ref1">Aho et al.
1986</xref>
        ]. Basically, the AST is a lossless representation of the program; it encodes the structure of the
program, the declarations, the variable usages, function calls, etc. Frequently, the AST is also decorated
with type information and contains connections between declarations (types, functions, variables) and
their usage.
      </p>
      <p>This representation is suitable for catching errors that the simple pattern matching is unable to
detect. These issues include heap allocation using the wrong size, some erroneous implicit conversions,
inconsistent design rules, like hurting the rule of three/five in C++ and it proved to be strong enough
to detect even some misuses of the STL API.</p>
      <p>
        Such AST based checks are usually relatively fast. Some rules can even be implemented using a
single traversal of the AST. That makes it possible to implement such checks as editor plug-ins. External
tools, like the
        <xref ref-type="bibr" rid="ref6 ref7">Clang Tidy [Clang Tidy 2019</xref>
        ] uses AST matching for most of its checks.
      </p>
      <p>While the AST matcher method is more powerful than the simple pattern matching, it has some
disadvantages too. To build up a valid AST requires a complete, syntactically correct source file. To
resolve external module dependences we need some additional information not represented in the
source itself, like include path for C/C++ programs, CLASSPATH for Java or BASE DIR in Python.
That usually means, we have to integrate the static analysis tool into the build system which can
be painful. Another shortage of the AST matcher method, that it cannot reason about the possible
program states which can be dependant from input values, function parameters.</p>
    </sec>
    <sec id="sec-6">
      <title>2.3 Symbolic execution</title>
      <p>
        Executing abstract interpretation [Cousot and Cousot 1977] the tool reasons about the possible values
of variables at a certain program point. Symbolic execution [Hampapuram et al. 2005; King 1976] is
a path-sensitive abstract interpretation method. During symbolic execution we interpret the source
code, but instead of using the exact (unknown) run-time values of the variables we use symbolic values
and gradually build up constraints on their possible values. Memory locations and their connections
(e.g. a pointer pointing to some variable, structs and their fields) are represented by a sophisticated
hierarchic
        <xref ref-type="bibr" rid="ref3">al memory model [Xu et al. 2010</xref>
        ]. A constraint solver can reason about these values and is
used to exclude unviable execution paths. Most of the high end proprietary analysis tools, like
CodeSonar [
        <xref ref-type="bibr" rid="ref15">GrammaTech 2019</xref>
        ], Klocwork [
        <xref ref-type="bibr" rid="ref27">Roguewave 2019</xref>
        ], and Coverity [
        <xref ref-type="bibr" rid="ref29">Synopsys 2019</xref>
        ] as well as open
source products like the
        <xref ref-type="bibr" rid="ref6 ref7">Clang Static Analyzer [Clang SA 2019</xref>
        ], and Infer [Calcagno and Distefano
2011] use this method.
      </p>
      <p>Symbolic execution is the most powerful method for static analysis as it makes profit from the
program structure, the type system, the data flow information and is able to follow function calls.
However, there is a price for this. To represent the internal state of the analysis, the analyzer uses a data
structure called the exploded graph [Reps et al. 1995]. Each vertex of this graph is a (symbolic state,
program point) pair. The edges of the graph are transitions between vertices. This graph is
exponential in the number of control branches (conditions) of the program. This could be critical, especially for
loops, which are represented as unrolled set of conditions and statements. This factor makes symbolic
execution also the most resource expensive (in memory and execution time) method.
3:4</p>
    </sec>
    <sec id="sec-7">
      <title>3. THE CURRENT TOOL LANDSCAPE OF PYTHON STATIC ANALYSIS</title>
      <p>Here we give a brief overview of the current most commonly used static analysis tools in Python.</p>
    </sec>
    <sec id="sec-8">
      <title>3.1 Pylint</title>
      <p>
        PyLint [
        <xref ref-type="bibr" rid="ref19">Logilab 2003</xref>
        ] is so far the most popular Python static analysis tool which is free and capable of
not only catching logical errors, but also warns regarding specific coding standards, offers details about
code complexity and suggests for simple refactoring. It is working by building an abstract syntax tree
with the help of the Astroid [
        <xref ref-type="bibr" rid="ref20">Logilab 2019</xref>
        ]. Also, Pylint allows developers to write own plugins for
specific checks which enables them easily to extend the tool. It is used by a several popular IDEs and
frameworks mainly for in-time static analysis of the code, some of which: PyCharm, VSCode, Django,
Eclipse with PyDev etc. PyLint popularity and reliability is shown through its use at Google as one of
the leader tech companies. For the static analysis of its Python codebase, Google is mostly relying on
PyLint, while having a common decision how to avoid some of its imperfections. [
        <xref ref-type="bibr" rid="ref14">Google 2018</xref>
        ].
      </p>
    </sec>
    <sec id="sec-9">
      <title>3.2 Pyflakes</title>
      <p>
        Pyflakes [
        <xref ref-type="bibr" rid="ref24">PyCQA 2014</xref>
        ] focuses only on the logical errors and does not complain about code style or
standards. It works by parsing the source file, instead of importing and it is a bit faster than PyLint,
since it examines the syntax tree of each file individually. As a consequence, it is more limited in the
types of issues that it can check. Its main focus is not to emit false positives which has its advantages,
but as a disadvantage of this strict focus, some typical errors are not reported at all.
Flake8 [Cordasco 2016] is a wrapper around Pyflakes, pycodestyle and mccabe [Cordasco 2017]. It is
mostly used by those who like Pyflakes but also want to get stylistic checks. The code style is checked
against PEP8 .
      </p>
      <p>Frosted [Crosley 2014] is a fork of pyflakes which focuses on more open contribution development from
the outside public.</p>
      <p>Pycodestyle [Rocholl 2006] strictly checks only the code style against the style conventions in PEP8. It
is usually used in combination with the other tools which are looking for logical errors and warnings.
3.3 flake8</p>
    </sec>
    <sec id="sec-10">
      <title>3.4 Frosted</title>
    </sec>
    <sec id="sec-11">
      <title>3.5 Pycodestyle 3.6</title>
    </sec>
    <sec id="sec-12">
      <title>Mypy</title>
      <p>Even though it is still considered experimental and optional static checker, Mypy [Lehtosalo 2016]
proves itself to be highly effective, especially in type checking. It focuses on combining the benefits of
dynamic typing and static typing. It has a powerful type system that in some cases, as discussed later
in this paper, it catches type errors that are not caught by any of the common Python static analysis
tools.</p>
    </sec>
    <sec id="sec-13">
      <title>3.7 PySym</title>
      <p>PySym [Dahlgren 2016] is an experimental Python package capable of a symbolic manipulation on
a minimal scope. None of the previously mentioned tools are in contact with this package, nor with
symbolic execution in general as a method of static analysis. Therefore, it is decided to be considered
in this paper in the further investigation of symbolic execution in Python static analysis tools.
PyExZ3 [Ball and Daniel 2015] is a tool which as part of the research on “Deconstructing Dynamic
Symbolic Execution” [Ball and Daniel 2015], adds to the exploration of the dynamic symbolic execution
(DSE) through a minimalist implementation of DSE for Python. With symbolic execution not being a
common topic in the present static analysis field of Python, the authors of this paper believe they can
rely on the PyExZ3 tool for further experimentation on dynamic symbolic execution in Python with the
goal to improve the Python static analysis tool set.</p>
      <p>On Figure 1 we summarize the connections between the Python static analysis tools.</p>
    </sec>
    <sec id="sec-14">
      <title>4. EVALUATION</title>
      <p>Here we evaluate the tools by (1) which methods they use, (2) how mature they are, (3) what kind of
problems they detect.</p>
    </sec>
    <sec id="sec-15">
      <title>4.1 Typical Python bugs and error tested</title>
      <p>It is true that the compiler relies on static analysis, similar to these tools in order to generate its
warnings during compilation time. However, its primary task is to translate a compilable code from
high-level programming language to a lower level language, and the attention to its essential
characteristic – the compilation time, makes it less capable of doing static analysis than the “third-party”
static analysis tools. Python compiler misses all of the following discussed bugs and errors. Here is a
short overview of the dummy code snippets used as a test examples of typical logical errors and bugs,
used in this study to analyze and test the power of the static analysis tools in Python.</p>
      <p>4.1.1 Referencing undefined variables. Very often in Python it happens that due to a typing
mistake, an undefined variable is referenced. However, due to the dynamic nature of the language, such
bugs don not get discovered up until runtime and when they are referenced. Example code for testing
this bug with the static analysis tools of Python:
1 import sys
2
3 message = ” Hello there ! ”
4 i f ” greetMe ” in sys . argv :
5 print ( mesage )
6 print ( ” This code i s fine , no problems . ” )</p>
      <p>It can be noticed that at the line 6 the variable “mesage” is mistyped, and does not refer to the string
“Hello there!” even though it looks similar. It is possible that error like this might not appear even
during runtime. For example if this Python code is run without the “–greetMe” as an argument, then
the code will just print out “This code is fine, no problems.” without errors or warnings.</p>
      <p>4.1.2 Too many positional arguments. The following dummy code beside the “too many positional
arguments” error in the call of the method getAge, has 3 more issues. The getAge method itself does
not have a “self ” argument. Further, the platform variable is undefined, this is similar to the previous
example. And the last issue the sys package is imported but never used. Unused imports might slow
down the program.</p>
      <p>4.1.3 Passing parameter of a different type then intended. Since Python is a dynamic language
variables do not have types in Python, but rather values do, and the type of the values as well as the
purpose for what an object can be used is decided during runtime. Python annotations were introduced
to add hints for the type of a variable, however the type annotations issues are not caught by the
compiler, so it is of a big importance for the other static analysis tools to discover that. The following
code snippet is used to test the tools against and describes the importance of type annotations in
Python:</p>
      <p>Considering the sum function here, Python compiler does not report any issue, but during runtime
the program throws an error which explains function sum can not be called with string since int and
str types can not be sum up together with the + operator in Python.</p>
      <p>1 import sys
2
3 c l a s s Person :
4
5
6
7
8
9
10
11
12
13
14
15
16
1 def sum( x : int , y : i n t ) :
2 return x + y
3 print (sum( 3 , 4 ) )
4 print (sum( 3 , ’ 4 ’ ) )
def i n i t ( s e l f , first name , last name , age ) :
s e l f . first name = first name
s e l f . last name = last name
s e l f . age = age
i f ”Windows” in platform . platform ( ) :</p>
      <p>print ( ”You ’ re using Windows ! ” )
s e l f . age = s e l f . getAge ( 1 , 2 , 3)
def getAge ( t h i s ) :
return ” 18 ”
4.1.4 Non-existing class member. The following example is used to test the tools against a code
which refers to an unexisting class member. As it can be seen, the program tries to print the
PERSON1’s height, but height does not exists as an attribute in the class Person.</p>
      <p>1 c l a s s Person ( ) :
2 def i n i t ( s e l f , name, age ) :
3 s e l f . name = name
4 s e l f . age = age
5 PERSON1 = Person ( ” Hristina ” , 23)
6 print (PERSON1. age )
7 print (PERSON1. height )
1 def outer ( ) :
2 x=3
3 def inner ( ) :
4 print ( x )
5 inner ( )
6 outer ( )
7 inner ( )
4.1.5 Nested function call. A call to a nested function is a big logical error, but still the Python
compiler does not generate any warning about it. The following dummy code is used to test the static
analysis tools against call of a nested function outside its scope:</p>
      <p>4.1.6 Closure bugs. In Python, Closure is a concept that allows function object to remember values
in enclosing scopes even if they are not present in memory.
1 def greet ( greet word , name) :
2 print ( greet word , name)
3 greeters = l i s t ( )
4 names = [ ” Kiki ” , ” Riki ” , ” Joe ” ]
5 f o r name in names :
6 greeters . append ( lambda x : greet ( x , name) )
7
8 f o r greeter in greeters :
9 greeter ( ” Hi ” )</p>
      <p>The following is an example code used to test the Python static analysis tools against a closure
bugs in Python which is not reported by the Python compiler and the program runs just fine, with an
unexpected output:
3:8
We may expect that this code would printout:</p>
      <p>But instead it is printing:
4.2 Test results discussion
1 Hi Kiki
2 Hi Riki
3 Hi Joe
1 Hi Joe
2 Hi Joe
3 Hi Joe
# Typical error
1. Referencing undefined variables
2. Too many positional arguments
3. Passing a parameter of a different type then intended
4. Nonexistent class members
5. Nested function call
6. Closure bugs</p>
      <p>On Table I we summarize our test results. The accent of the discussed code tests is mostly put on
the logical errors that are slipping into Python developers everyday work, thus at this point, code style
focused static analysis tools (such as Pycodestyle) are not considered in the result table. This result
discussion is based on catching-coverage of the logical errors, confirming if the tool’s behavior is as it is
described in their documentation as well as a general overview of spotted pros and cons of each of the
tools used against the test code examples. Currently, just a short general overview of the output format
of the tools is given, but since this is also an important aspect of the tool’s functionality, especially when
they are used against a bigger Python code based, more detailed analysis of this will take part further
in the study. To clarify, all the tools are tested while in their default configuration. The results might
differ if the tool’s configuration is separately tuned according the code tested.</p>
      <p>Upon initial inspection of the table results, Pylint outperformed the other tools when run against
the described test examples. It gave the most accurate reports and it was also the most descriptive
in the generated output. However, if we look at the output format and style (which is not the focus of
the table results at present), it is apparent that in many cases Pylint is “too talkative”, meaning the
output can quickly get noisy and not so easily readable as the code base expands. Yet, the convenience
of Pylint is again proven as it is the only tool that reports the errors “Too many positional arguments”
and “Closure bugs”, which are easily made mistakes and the first one is especially trivial, but left to
be caught during runtime, which is much more expensive. As such, they are of a great importance to
the static analysis and the tools clearly need a support in their improvement. The “Closure bug” is a
bit more complex. Closure in Python is an important concept and it is prone to bugs which in many
cases, shown in the dummy test example as well, is hardly caught even during runtime. Such errors
can take even days of debugging and manual reviews by the developers. This is notably true for bugs
hiding in the Python closure concept. The authors believe that with the implementations of symbolic
execution, the Closure is one of the concepts in Python that might see great improvements regarding
static analysis by moving it ahead from the current benefits of the AST approach.</p>
      <p>There is only one test case where Pylint did not report any warning nor error, and to a positive
surprise, Mypy was the only tool that caught it. This was a type annotation related bug where Mypy
proved that even though it is still considered as an experimental tool and far from the commonly
preferred Pylint, it justified its focus to perform well on type annotation errors. This makes Mypy an
essential static analysis tool to be considered in a Python code that uses type annotations gain on the
benefits of the predefined variable types, which is not in the core of Python as a dynamic programming
language. The importance of type annotation static analysis is shown in the “Passing parameter of a
different type then intended” example and its “sum” function. Seeing that analyzing type annotations
is one important point of the static analysis tools that needs to be improved, and at the same time
noticing that the tools lack the symbolic execution as a method technique behind the scenes which
seems to be a great factor of this improvement, encourages author’s further directions of the research
to go towards implementing and testing symbolic execution in Python static analysis. On the brighter
side of the results table, there are two tests that were covered with a warning report by all of the static
analysis tools under test. These are “Referencing undefined variables” and “Nested function call”, both
of which are quite trivial errors. The example “Referencing undefined variables” in a strictly typed
language such as C, C++ and Java, this will be immediately reported by the compiler, but since Python
is a dynamically typed language, its compiler does not catch it. Thus, this is one of the crucial moments
for the Python static analyzers to shine up above the Python compiler. Anyhow, the strong believe that
symbolic execution can improve the performance even in the most crucial and trivial examples, stays
alive and will be considered in the future of this research.</p>
      <p>Since the focus now is in the logical errors caught by the static analysis tools, it is important to notice
that Pyflakes and flake8 are expected to, and they do give, the same results in the table. This is mainly
because flake8 just combines pyflakes, pycodestyle and mccabe, so they have the same approach in
catching the logical errors. However, noticing that Pyflakes did not catch many of the logical errors
that were caught by the other tools, knowing that as a tool it focuses mostly on the logical errors
avoiding the style reports, it raises a lot of questions. Moreover, leaves the believes that its very strict
avoidance of false negative error, adds more cons than pros to its convenience as a static analysis
tool, since because of this, many errors were left not reported at all. Frosted as a tool during this test
examples did not show that catches any different errors than what Pyflakes and flake8 caught, which
is to a certain degree expectable, since it is a fork of pyflakes, with the main difference being that its
open to a public development.</p>
      <p>To sum up this brief introductory discussion and analysis of the existing Python static analysis tools,
it can be said that there is no tool presently that can stand alone as the best of all. Best results at the
moment would be achieved when using several of the existing tools at the same time, thanks to their
manually configurable and customizable capabilities. Exploring Python symbolic execution further in
the research, promises that would bring great improvements in the currently existing Python static
analysis world.</p>
    </sec>
    <sec id="sec-16">
      <title>5. CONCLUSION</title>
      <p>Static analysis is a powerful technique to validate large software systems in the early phase of the
Continuous Integration (CI) loop. There are sophisticated methods for analyzing mainstream languages
with static type system, like C, C++ and Java. The current support for the Python programming
language is way behind. Tools are in experimental phase and lacking large development communities.
The main reason is the dynamic nature of the language which makes harder to apply the usual
analyzer techniques. However, this can be improved as tools can step forward from the current AST based
methods. The most promising direction is symbolic execution, which can handle the dynamic language
features in a more straightforward way. The authors suggest future researches to implement further
symbolic execution techniques and test them in industrial environment.</p>
    </sec>
  </body>
  <back>
    <ref-list>
      <ref id="ref1">
        <mixed-citation>
          <string-name>
            <given-names>A. V.</given-names>
            <surname>Aho</surname>
          </string-name>
          ,
          <string-name>
            <given-names>R.</given-names>
            <surname>Sethi</surname>
          </string-name>
          , and
          <string-name>
            <given-names>J. D.</given-names>
            <surname>Ullman</surname>
          </string-name>
          .
          <year>1986</year>
          .
          <article-title>Compilers principles, techniques, and tools</article-title>
          . Addison-Wesley, Reading, MA.
        </mixed-citation>
      </ref>
      <ref id="ref2">
        <mixed-citation>
          <string-name>
            <given-names>Thomas</given-names>
            <surname>Ball</surname>
          </string-name>
          and
          <string-name>
            <given-names>Jakub</given-names>
            <surname>Daniel</surname>
          </string-name>
          .
          <year>2015</year>
          .
          <article-title>Deconstructing Dynamic Symbolic Execution</article-title>
          .
          <source>Proceedings of the 2014 Marktoberdorf Summer School on Dependable Software Systems Engineering MSR-TR-2015-95 (January</source>
          <year>2015</year>
          ). https://www.microsoft.com/ en-us/research/publication/deconstructing-dynamic
          <string-name>
            <surname>-</surname>
          </string-name>
          symbolic-execution/
        </mixed-citation>
      </ref>
      <ref id="ref3">
        <mixed-citation>
          <string-name>
            <given-names>Al</given-names>
            <surname>Bessey</surname>
          </string-name>
          ,
          <string-name>
            <given-names>Ken</given-names>
            <surname>Block</surname>
          </string-name>
          , Ben Chelf, Andy Chou, Bryan Fulton, Seth Hallem, Charles Henri-Gros,
          <string-name>
            <given-names>Asya</given-names>
            <surname>Kamsky</surname>
          </string-name>
          ,
          <string-name>
            <surname>Scott McPeak</surname>
            ,
            <given-names>and Dawson</given-names>
          </string-name>
          <string-name>
            <surname>Engler</surname>
          </string-name>
          .
          <year>2010</year>
          .
          <article-title>A Few Billion Lines of Code Later: Using Static Analysis to Find Bugs in the Real World</article-title>
          .
          <source>Commun. ACM 53</source>
          ,
          <issue>2</issue>
          (Feb.
          <year>2010</year>
          ),
          <fpage>66</fpage>
          -
          <lpage>75</lpage>
          . DOI:http://dx.doi.org/10.1145/1646353.1646374
        </mixed-citation>
      </ref>
      <ref id="ref4">
        <mixed-citation>
          <string-name>
            <given-names>Barry</given-names>
            <surname>Boehm and Victor R. Basili</surname>
          </string-name>
          .
          <year>2001</year>
          .
          <source>Software Defect Reduction Top 10 List. Computer 34</source>
          , 1 (Jan.
          <year>2001</year>
          ),
          <fpage>135</fpage>
          -
          <lpage>137</lpage>
          . DOI:http://dx.doi.org/10.1109/2.962984
        </mixed-citation>
      </ref>
      <ref id="ref5">
        <mixed-citation>
          <string-name>
            <given-names>Cristiano</given-names>
            <surname>Calcagno</surname>
          </string-name>
          and
          <string-name>
            <given-names>Dino</given-names>
            <surname>Distefano</surname>
          </string-name>
          .
          <year>2011</year>
          .
          <article-title>Infer: An automatic program verifier for memory safety of C programs</article-title>
          .
          <source>In NASA Formal Methods Symposium</source>
          . Springer,
          <fpage>459</fpage>
          -
          <lpage>465</lpage>
          .
        </mixed-citation>
      </ref>
      <ref id="ref6">
        <mixed-citation>
          <string-name>
            <surname>Clang</surname>
            <given-names>SA</given-names>
          </string-name>
          .
          <year>2019</year>
          . Clang Static Analyzer. (
          <year>2019</year>
          ). https://clang-analyzer.llvm.org/.
        </mixed-citation>
      </ref>
      <ref id="ref7">
        <mixed-citation>
          <string-name>
            <given-names>Clang</given-names>
            <surname>Tidy</surname>
          </string-name>
          .
          <year>2019</year>
          . Clang-Tidy.
          <article-title>(</article-title>
          <year>2019</year>
          ). https://clang.llvm.org/extra/clang-tidy/ (last accessed:
          <fpage>28</fpage>
          -
          <lpage>02</lpage>
          -
          <year>2019</year>
          ).
        </mixed-citation>
      </ref>
      <ref id="ref8">
        <mixed-citation>
          <string-name>
            <given-names>Ian</given-names>
            <surname>Cordasco</surname>
          </string-name>
          .
          <year>2016</year>
          .
          <article-title>Flake8 documentation</article-title>
          . (
          <year>2016</year>
          ). http://flake8.pycqa.org/en/latest/.
        </mixed-citation>
      </ref>
      <ref id="ref9">
        <mixed-citation>
          <string-name>
            <given-names>Ian</given-names>
            <surname>Cordasco</surname>
          </string-name>
          .
          <year>2017</year>
          .
          <article-title>Mccabe documentation</article-title>
          . (
          <year>2017</year>
          ). https://pypi.org/project/mccabe/.
        </mixed-citation>
      </ref>
      <ref id="ref10">
        <mixed-citation>
          <string-name>
            <given-names>Patrick</given-names>
            <surname>Cousot</surname>
          </string-name>
          and
          <string-name>
            <given-names>Radhia</given-names>
            <surname>Cousot</surname>
          </string-name>
          .
          <year>1977</year>
          .
          <article-title>Abstract interpretation: a unified lattice model for static analysis of programs by construction or approximation of fixpoints</article-title>
          .
          <source>In Proceedings of the 4th ACM SIGACT-SIGPLAN symposium on Principles of programming languages. ACM</source>
          ,
          <volume>238</volume>
          -
          <fpage>252</fpage>
          .
        </mixed-citation>
      </ref>
      <ref id="ref11">
        <mixed-citation>
          <string-name>
            <given-names>Timothy</given-names>
            <surname>Crosley</surname>
          </string-name>
          .
          <year>2014</year>
          .
          <article-title>Frosted documentation</article-title>
          . (
          <year>2014</year>
          ). https://pypi.org/project/frosted/.
        </mixed-citation>
      </ref>
      <ref id="ref12">
        <mixed-citation>
          <string-name>
            <given-names>Bjo¨rn I.</given-names>
            <surname>Dahlgren</surname>
          </string-name>
          .
          <year>2016</year>
          .
          <article-title>Pysym documentation</article-title>
          . (
          <year>2016</year>
          ). https://pythonhosted.org/pysym/.
        </mixed-citation>
      </ref>
      <ref id="ref13">
        <mixed-citation>
          <string-name>
            <given-names>Artem</given-names>
            <surname>Dergachev</surname>
          </string-name>
          .
          <year>2016</year>
          .
          <article-title>Clang Static Analyzer: A Checker Developer's</article-title>
          <string-name>
            <surname>Guide.</surname>
          </string-name>
          (
          <year>2016</year>
          ). https://github.com/haoNoQ/ clang-analyzer-guide (last accessed:
          <fpage>28</fpage>
          -
          <lpage>02</lpage>
          -
          <year>2019</year>
          ).
        </mixed-citation>
      </ref>
      <ref id="ref14">
        <mixed-citation>
          <string-name>
            <surname>Google</surname>
          </string-name>
          .
          <year>2018</year>
          .
          <article-title>Google Python Style Guide</article-title>
          . (
          <year>2018</year>
          ). http://google.github.io/styleguide/pyguide.html.
        </mixed-citation>
      </ref>
      <ref id="ref15">
        <mixed-citation>
          <string-name>
            <surname>GrammaTech.</surname>
          </string-name>
          <year>2019</year>
          . CodeSonar. (
          <year>2019</year>
          ). https://www.grammatech.com/products/codesonar (last accessed:
          <fpage>28</fpage>
          -
          <lpage>02</lpage>
          -
          <year>2019</year>
          ).
        </mixed-citation>
      </ref>
      <ref id="ref16">
        <mixed-citation>
          <string-name>
            <given-names>Hari</given-names>
            <surname>Hampapuram</surname>
          </string-name>
          ,
          <string-name>
            <given-names>Yue</given-names>
            <surname>Yang</surname>
          </string-name>
          , and
          <string-name>
            <surname>Manuvir Das</surname>
          </string-name>
          .
          <year>2005</year>
          .
          <article-title>Symbolic Path Simulation in Path-sensitive Dataflow Analysis</article-title>
          .
          <source>SIGSOFT Softw. Eng. Notes 31</source>
          ,
          <issue>1</issue>
          (Sept.
          <year>2005</year>
          ),
          <fpage>52</fpage>
          -
          <lpage>58</lpage>
          . DOI:http://dx.doi.org/10.1145/1108768.1108808
        </mixed-citation>
      </ref>
      <ref id="ref17">
        <mixed-citation>
          <string-name>
            <given-names>James C.</given-names>
            <surname>King</surname>
          </string-name>
          .
          <year>1976</year>
          .
          <article-title>Symbolic Execution and Program Testing</article-title>
          .
          <source>Commun. ACM 19</source>
          ,
          <issue>7</issue>
          (
          <year>July 1976</year>
          ),
          <fpage>385</fpage>
          -
          <lpage>394</lpage>
          . DOI:http://dx.doi.org/10.1145/360248.360252
        </mixed-citation>
      </ref>
      <ref id="ref18">
        <mixed-citation>
          <string-name>
            <given-names>Jukka</given-names>
            <surname>Lehtosalo</surname>
          </string-name>
          .
          <year>2016</year>
          .
          <article-title>Mypy documentation</article-title>
          . (
          <year>2016</year>
          ). https://mypy.readthedocs.io/en/latest/.
        </mixed-citation>
      </ref>
      <ref id="ref19">
        <mixed-citation>
          <string-name>
            <surname>Logilab</surname>
          </string-name>
          .
          <year>2003</year>
          .
          <article-title>Pylint documentation</article-title>
          . (
          <year>2003</year>
          ). http://pylint.pycqa.org/en/latest/.
        </mixed-citation>
      </ref>
      <ref id="ref20">
        <mixed-citation>
          <string-name>
            <surname>Logilab</surname>
          </string-name>
          .
          <year>2019</year>
          .
          <article-title>Astroid documentation</article-title>
          . (
          <year>2019</year>
          ). https://astroid.readthedocs.io/en/latest/.
        </mixed-citation>
      </ref>
      <ref id="ref21">
        <mixed-citation>
          Daniel Marjama¨ ki.
          <year>2013</year>
          .
          <article-title>CppCheck: a tool for static C/C++ code analysis</article-title>
          .
          <source>(</source>
          <year>2013</year>
          ). http://cppcheck.sourceforge.net/
        </mixed-citation>
      </ref>
      <ref id="ref22">
        <mixed-citation>
          <string-name>
            <given-names>Martin</given-names>
            <surname>Moene</surname>
          </string-name>
          .
          <year>2014</year>
          .
          <article-title>Search with CppCheck</article-title>
          .
          <source>Overload Journal</source>
          <volume>120</volume>
          (
          <year>2014</year>
          ). https://accu.org/index.php/journals/1898
        </mixed-citation>
      </ref>
      <ref id="ref23">
        <mixed-citation>
          <string-name>
            <given-names>Nicholas</given-names>
            <surname>Nethercote</surname>
          </string-name>
          and
          <string-name>
            <given-names>Julian</given-names>
            <surname>Seward</surname>
          </string-name>
          .
          <year>2007</year>
          .
          <article-title>Valgrind: A Framework for Heavyweight Dynamic Binary Instrumentation</article-title>
          .
          <source>SIGPLAN Not</source>
          .
          <volume>42</volume>
          ,
          <issue>6</issue>
          (
          <year>June 2007</year>
          ),
          <fpage>89</fpage>
          -
          <lpage>100</lpage>
          . DOI:http://dx.doi.org/10.1145/1273442.1250746
        </mixed-citation>
      </ref>
      <ref id="ref24">
        <mixed-citation>
          <string-name>
            <surname>PyCQA.</surname>
          </string-name>
          <year>2014</year>
          .
          <article-title>Pyflakes documentation</article-title>
          . (
          <year>2014</year>
          ). https://pypi.org/project/pyflakes/.
        </mixed-citation>
      </ref>
      <ref id="ref25">
        <mixed-citation>
          <string-name>
            <given-names>Thomas</given-names>
            <surname>Reps</surname>
          </string-name>
          , Susan Horwitz, and
          <string-name>
            <given-names>Mooly</given-names>
            <surname>Sagiv</surname>
          </string-name>
          .
          <year>1995</year>
          .
          <article-title>Precise Interprocedural Dataflow Analysis via Graph Reachability</article-title>
          .
          <source>In Proceedings of the 22Nd ACM SIGPLAN-SIGACT Symposium on Principles of Programming Languages (POPL '95)</source>
          . ACM, New York, NY, USA,
          <fpage>49</fpage>
          -
          <lpage>61</lpage>
          . DOI:http://dx.doi.org/10.1145/199448.199462
        </mixed-citation>
      </ref>
      <ref id="ref26">
        <mixed-citation>
          <string-name>
            <given-names>Johann C.</given-names>
            <surname>Rocholl</surname>
          </string-name>
          .
          <year>2006</year>
          .
          <article-title>Pycodestyle documentation</article-title>
          . (
          <year>2006</year>
          ). http://pycodestyle.pycqa.org/en/latest/.
        </mixed-citation>
      </ref>
      <ref id="ref27">
        <mixed-citation>
          <string-name>
            <surname>Roguewave. 2019. Klocwork.</surname>
          </string-name>
          (
          <year>2019</year>
          ). https://www.roguewave.com/products-services/klocwork (last accessed:
          <fpage>28</fpage>
          -
          <lpage>02</lpage>
          -
          <year>2019</year>
          ).
        </mixed-citation>
      </ref>
      <ref id="ref28">
        <mixed-citation>
          <string-name>
            <given-names>Konstantin</given-names>
            <surname>Serebryany</surname>
          </string-name>
          , Derek Bruening, Alexander Potapenko, and
          <string-name>
            <given-names>Dmitry</given-names>
            <surname>Vyukov</surname>
          </string-name>
          .
          <year>2012</year>
          .
          <article-title>AddressSanitizer: A Fast Address Sanity Checker</article-title>
          .
          <source>In Proceedings of the 2012 USENIX Conference on Annual Technical Conference (USENIX ATC'12)</source>
          .
          <source>USENIX Association</source>
          , Berkeley, CA, USA,
          <fpage>28</fpage>
          -
          <lpage>28</lpage>
          . http://dl.acm.org/citation.cfm?id=
          <volume>2342821</volume>
          .
          <fpage>2342849</fpage>
        </mixed-citation>
      </ref>
      <ref id="ref29">
        <mixed-citation>
          <string-name>
            <surname>Synopsys. 2019. Coverity.</surname>
          </string-name>
          (
          <year>2019</year>
          ). https://scan.coverity.com/ (last accessed:
          <fpage>28</fpage>
          -
          <lpage>02</lpage>
          -
          <year>2019</year>
          ).
        </mixed-citation>
      </ref>
      <ref id="ref30">
        <mixed-citation>
          <string-name>
            <given-names>Tiobe. 2019. TIOBE</given-names>
            <surname>Programming Community</surname>
          </string-name>
          <string-name>
            <surname>Index</surname>
          </string-name>
          ,
          <year>July 2019</year>
          . (
          <year>2019</year>
          ). http://www.tiobe.com/index.php/content/paperinfo/tpci/ index.html accessed 02-July-
          <year>2019</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref31">
        <mixed-citation>
          <string-name>
            <given-names>Zhongxing</given-names>
            <surname>Xu</surname>
          </string-name>
          ,
          <string-name>
            <given-names>Ted</given-names>
            <surname>Kremenek</surname>
          </string-name>
          ,
          <string-name>
            <given-names>and Jian</given-names>
            <surname>Zhang</surname>
          </string-name>
          .
          <year>2010</year>
          .
          <article-title>A Memory Model for Static Analysis of C Programs</article-title>
          .
          <source>In Proceedings of the 4th International Conference on Leveraging Applications of Formal Methods, Verification, and Validation - Volume Part I (ISoLA'10)</source>
          . Springer-Verlag, Berlin, Heidelberg,
          <fpage>535</fpage>
          -
          <lpage>548</lpage>
          . http://dl.acm.org/citation.cfm?id=
          <volume>1939281</volume>
          .
          <fpage>1939332</fpage>
        </mixed-citation>
      </ref>
      <ref id="ref32">
        <mixed-citation>
          <string-name>
            <given-names>Anna</given-names>
            <surname>Zaks</surname>
          </string-name>
          and
          <string-name>
            <given-names>Jordan</given-names>
            <surname>Rose</surname>
          </string-name>
          .
          <year>2012</year>
          .
          <article-title>Building a Checker in 24 hours</article-title>
          . (
          <year>2012</year>
          ). https://www.youtube.com/watch?v=
          <fpage>kdxlsP5QVPw</fpage>
          .
        </mixed-citation>
      </ref>
    </ref-list>
  </back>
</article>