Welcome. In this session, we will see how to use a static analysis tool to analyze the software that we built. We will be working with a tool called Infer. It's used in many big companies such as Facebook, Amazon, and many others and it does many of the things that we talked about earlier, such as finding errors like null pointer exceptions, leakage of resources like open files that have not been closed, reachability of certain annotations if there are missing logs or log guards and various concurrency-induced race conditions such as read and write interference and so on. Infer can work with various languages such as Java, C, or C++, and Objective-C. Perhaps, the easiest way to look at it is to see Infer in action through an example. So, let us try Infer in the browser. So, here is a small program just to demonstrate various concepts and the errors that Infer can figure. So, here is a small program, where doesNotCauseNPE() may call a method a.method() and there is also another mayCauseNPE() that can cause a method called the method a.method(), another routine to show how resource leaks can be detected and a simple Hello Infer World program. So, here we have three files with some source code. In this case, we are using a web-based IDE to build and run and analyze our program. So, we just compile it. Compilation is successful. Everything went through the compilers, no errors that the compiler found. But when you run the program, it prints "Hello Infer World", you don't see any apparent issues here either. So, let us analyze the program and Infer runs this analysis on the source code and provides an output. And this list, a couple of potential errors, two places where it found resource leaks, and one potential null dereference. So, let us examine what that could be. So, Infer usually gives useful information with the surrounding context about what could happen and when. Here in this case, in line 27 of the file Hello.java, that is in fact an annotation comment before that saying that fix this point there could be null for the "a" object, but it is not checked and in line 27, the method, a.method() is called. So, if you look at line 25, a is instantiated with Pointers.mayReturnNull. So, potentially that could be a method that returns a possible null pointer array. So, if we dereference and call the method at this point and if that path is executed, there could be a null pointer exception that's thrown. The other two instances of errors, are resource leaks. In this case, in line 37 there is a stream.write(). And in the finally clause, there is a note saying that the stream should be closed but that's not done. Infer figures that it's indeed the case, that's possible and so there is a resource source leak and similarly on line 59, there is another resource leak that's reported. So, that's kind of the overview of the kinds of errors that Infer could detect. Of course, there are many more capabilities and much more analysis that could be run with Infer. So to use Infer, the best place is to start with the Getting Started guide. There is quite a wealth of documentation about how to install and run Infer. Depending on the kind of platform that you're running in you have different instructions to install the tool. And the user guide explains how Infer works. Essentially, there are two phases to an Infer run. The capture phase, where the compilation commands that you use in your build system are captured by Infer to translate the files to its own internal representation so that it can do the analysis. And there is the analysis phase. In this phase, the captured information that Infer has stored in Infer-out, are then processed by various analysis tools within Infer and each function and method is analyzed and when there are errors, those are recorded and reported. All the information is stored under your working directory and each of these steps can be run separately. Perhaps, the simplest way to run is using the simple Run command. So let us see how it works. So, I have Infer installed and we are in a project, microwave_gradle, we have used this project for other exercises in this series. I am first doing a "$ gradle clean", to get directly cleaned of all the output files produced by the compilers. Now, I am going to run "$ infer run --", followed by my "gradle" build command. In this case, I'm just going to compile the Java files. So, I'm going to use the "compileJava" task for gradle. So, what Infer does, is it understands the gradle build process and inserts itself into the process to capture the information. In this case, we ran both the capture and analysis phase and what we got is the output at the end of running Infer and in this case, it reports three potential thread safety violations. In each of these cases, there is some variable that is read and that variable could be written to in other methods and perhaps, this could be run in different threads, because some of the methods are synchronized and some aren't. So Infer says there is a potential violation, maybe there is a background thread that is, for example, updating the ticks while this thread is reading the ticks value. Such errors are usually very difficult to catch with traditional testing techniques. So, as an example of how to run other analyses that are a part of Infer, let us see a slightly different analysis. Again, I'm going to "clean" it, start from a clean state, "$ infer run" and in this case, I'm going to say, run the "--eradicate" analyzer which looks for null pointers and null pointer accesses. Again, "gradle compileJava". Again, it goes through the steps, runs some captures. The compilation shows progress in terms of files and methods being analyzed. Now, while in this case, we got one other potential error, that Infer inferred. So it's called the ERADICATE_PARAMETER_NOT_NULLABLE. So, what it's saying is the Microwave constructor, in this case, takes the ModeController and the DisplayController and the third argument, if you remember, is the list of preset settings like pizza and soup and so on. And usually, you expect a bunch of those presets defined and instantiated when the Microwave object is instantiated. But the second constructor that I added, provides a null object, which means it says there is no preset. Presumably, it's thinking and the thinking being that, if you provide no objects as presets, there won't be any presets, the microwave should still function. But there is potential that for this object field to be accessed, the presets may be accessed in other methods. In this case, Infer figures that the expectation of null for this argument hasn't been explicitly specified, so it expects all these arguments to be non-null. And because null is passed, it's flagging this error. These programs are syntactically correct, semantically valid and oftentimes may run without any errors. But alerting the user to these errors, can make developers think about the consequences and perhaps, address some of the bugs that might otherwise escape. So, we will do a small exercise with the Infer tool to do some analysis and find bugs.