master
markma 3 years ago
parent 09fba4a0b5
commit f8dfc1ce1f

@ -0,0 +1,9 @@
[buildfile]
includes = //DEFS
[project]
ignore = .git, .ml, .mli
[java]
source_level = 8
target_level = 8

@ -0,0 +1,47 @@
---
AccessModifierOffset: -1
AlignEscapedNewlinesLeft: true
AlignTrailingComments: false
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
AlwaysBreakBeforeMultilineStrings: true
AlwaysBreakTemplateDeclarations: true
BinPackArguments: false
BinPackParameters: false
BreakBeforeBinaryOperators: false
BreakBeforeBraces: Attach
BreakConstructorInitializersBeforeComma: false
ColumnLimit: 80
CommentPragmas: '^@atd'
ConstructorInitializerAllOnOneLineOrOnePerLine: true
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
DerivePointerAlignment: false
ExperimentalAutoDetectBinPacking: true
IndentCaseLabels: true
IndentFunctionDeclarationAfterType: false
IndentWidth: 2
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCSpaceBeforeProtocolList: false
PenaltyBreakBeforeFirstCallParameter: 10
PenaltyBreakComment: 1000
PenaltyBreakFirstLessLess: 20
PenaltyBreakString: 1000
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 200
PointerAlignment: Left
SortIncludes: false
SpaceAfterControlStatementKeyword: true
SpaceBeforeAssignmentOperators: true
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: false
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
Standard: Cpp11
TabWidth: 8
UseTab: Never
...

1
.gitattributes vendored

@ -0,0 +1 @@
website/** linguist-documentation

@ -0,0 +1,49 @@
name: Deploy
on:
push:
branches:
- "master"
paths:
- "website/**"
jobs:
deploy:
runs-on: ubuntu-latest
if: github.repository == 'facebook/infer'
env:
working-directory: website
node-version: 14.x
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Use Node.js ${{ env.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ env.node-version }}
- name: Get yarn cache directory
id: yarn
run: echo "::set-output name=dir::$(yarn cache dir)"
- name: Restore yarn cache
uses: actions/cache@v2
with:
path: ${{ steps.yarn.outputs.dir }}
key: ${{ runner.os }}-yarn-${{ hashFiles('website/yarn.lock') }}
- name: Install packages
working-directory: ${{ env.working-directory }}
run: yarn --frozen-lockfile
- name: Deploy to GitHub Pages
working-directory: ${{ env.working-directory }}
run: |
git config --global user.email "${GITHUB_ACTOR}@users.noreply.github.com"
git config --global user.name "${GITHUB_ACTOR}"
echo "machine github.com login ${GITHUB_ACTOR} password ${{ secrets.GITHUB_TOKEN }}" > ~/.netrc
GIT_USER=${GITHUB_ACTOR} yarn deploy

@ -0,0 +1,189 @@
name: Install
on:
- push
- pull_request
jobs:
create-release:
name: Create release
runs-on: ubuntu-latest
outputs:
upload-url: ${{ steps.create-release.outputs.upload_url }}
steps:
- name: Create Release
id: create-release
if: startsWith(github.ref, 'refs/tags/v')
uses: actions/create-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ github.ref }}
release_name: Infer version ${{ github.ref }}
draft: true
prerelease: false
body: |
BEFORE PUBLISHING CHECKLIST:
1. From the commit tagged on GitHub, create and push a new version of the website with "make new-website-version" (see website/README.md for how to test).
2. Consider deleting the oldest documentation version (see Docusaurus 2 documentation for details).
3. Fill in the changelog below to go on GitHub.
4. Download the release tarballs and test that the binaries works.
5. Fill in the shasums by running the command at the end of the release text.
--- PUBLISH GITHUB RELEASE HERE ---
6. At some point, copy the GitHub changelog to Changelog.md in the repo.
7. Tweet.
--- DELETE EVERYTHING ABOVE THIS LINE ---
This is a binary release of Infer for Linux and MacOS. To use it follow these [instructions](http://fbinfer.com/docs/getting-started).
- new feature 1
- new feature 2
The sha256 checksums of the tarballs are:
```
$ shasum -a 256 infer-*-v<VERSION GOES HERE>.tar.xz
DOWNLOAD BOTH TARBALLS AND PUT RESULT OF THE ABOVE COMMAND HERE BEFORE PUBLISHING
```
build:
name: Build Infer
needs: create-release
strategy:
fail-fast: false
matrix:
os:
- macOS-latest
- ubuntu-latest
ocaml-version:
- 4.12.0
runs-on: ${{ matrix.os }}
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Install Required Apt Packages for Ubuntu
run: |
sudo apt install libmpfr-dev libsqlite3-dev ninja-build
sudo apt clean
if: runner.os == 'Linux'
- name: Install Required Brew Packages for MacOS
run: brew install automake jq ninja pkg-config lzlib
if: runner.os == 'macOS'
- name: Compute hash of clang installation
id: clang-hash
run: |
echo "::set-output name=value::$(./facebook-clang-plugins/clang/setup.sh --clang-hash)"
- name: Attempt to get clang from the cache
id: cache-clang
uses: actions/cache@v2
with:
path: facebook-clang-plugins/clang/install
key: clang-${{ runner.os }}-${{ steps.clang-hash.outputs.value }}
- name: Record that the clang cache was hit
if: steps.cache-clang.outputs.cache-hit == 'true'
run: ./facebook-clang-plugins/clang/setup.sh --only-record-install
- name: Build clang on cache misses
if: steps.cache-clang.outputs.cache-hit != 'true'
run: |
./facebook-clang-plugins/clang/src/prepare_clang_src.sh
./facebook-clang-plugins/clang/setup.sh --ninja --sequential-link
- name: Attempt to get opam tree from the cache
uses: actions/cache@v2
with:
path: ~/.opam
key: opam-${{ runner.os }}-${{ hashFiles('opam/infer.opam.locked') }}
- name: Use OCaml ${{ matrix.ocaml-version }}
uses: avsm/setup-ocaml@v1
with:
ocaml-version: ${{ matrix.ocaml-version }}
- run: ./build-infer.sh --yes all
- run: make install BUILD_MODE=opt
if: runner.os == 'macOS'
- run: |
sudo make install BUILD_MODE=opt
# restore permissions after root build
sudo chown $USER: -R .
if: runner.os == 'Linux'
- name: Test infer
run: |
eval $(opam env)
{
echo 'class FailingTest {'
echo ' String mayReturnNull(int i) {'
echo ' if (i > 0) {'
echo ' return "Hello, Infer!";'
echo ' }'
echo ' return null;'
echo ' }'
echo ' int mayCauseNPE() {'
echo ' String s = mayReturnNull(0);'
echo ' return s.length();'
echo ' }'
echo '}'
} > FailingTest.java
{
echo " class PassingTest {"
echo " String mayReturnNull(int i) {"
echo " if (i > 0) {"
echo ' return "Hello, Infer!";'
echo " }"
echo " return null;"
echo " }"
echo " int mayCauseNPE() {"
echo " String s = mayReturnNull(0);"
echo " return s == null ? 0 : s.length();"
echo " }"
echo " }"
} > PassingTest.java
# first command should exit with status 2
infer --fail-on-issue -P -- javac FailingTest.java || if [[ $? -ne 2 ]]; then exit 1; fi
infer --fail-on-issue -P -- javac PassingTest.java
{
echo "#include <stdio.h>"
echo "int main()"
echo "{ int *s = NULL; *s = 42; return 0; } "
} > FailingTest.c
{
echo "#include <stdio.h>"
echo "int main()"
echo "{ int *s = NULL; if (s != NULL) { *s = 42; } return 0; }"
} > PassingTest.c
# first command should exit with status 2
infer --fail-on-issue -P -- clang -c FailingTest.c || if [[ $? -ne 2 ]]; then exit 1; fi
infer --fail-on-issue -P -- clang -c PassingTest.c
- name: Build release tarball
id: build-release
if: startsWith(github.ref, 'refs/tags/v')
run: |
./scripts/create_binary_release.sh "$(echo '${{ github.ref }}' | rev | cut -d / -f 1 | rev)"
- name: Upload Release Asset
if: startsWith(github.ref, 'refs/tags/v')
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ needs.create-release.outputs.upload-url }}
asset_path: ${{ steps.build-release.outputs.tarball-path }}
asset_name: ${{ steps.build-release.outputs.tarball-path }}
asset_content_type: application/x-gtar

216
.gitignore vendored

@ -0,0 +1,216 @@
# Generated files #
###################
*.pyc
*.specs
*.cm*
*.o
*~
*.swp
*.annot
*.class
*.log
*.orig
*.rej
.#*
# generated by build and tests
/_build
/_build_logs
/infer/lib/erlang/infer_parse_transform/_build
/infer/tests/codetoanalyze/java/*/codetoanalyze
_build_infer
*.exp.test*
*.dot.test
*.test.dot
*.test.txt
duplicates.txt
*.ast.sh
*.ast.bdump
*.ast.biniou
/infer/tests/build_systems/buck_flavors_deterministic/capture_hash-*.sha
/infer/tests/build_systems/buck_flavors_diff/src/hello.c
/infer/tests/build_systems/buck_clang_test_determinator/diff.mod.test
/infer/tests/build_systems/buck_export_changed_functions/diff.mod.test
/infer/tests/build_systems/clang_compilation_db_escaped/compile_commands.json
/infer/tests/build_systems/clang_compilation_db_relpath/compile_commands.json
/infer/tests/build_systems/clang_test_determinator/*.test
/infer/tests/build_systems/export_changed_functions/*.test
/infer/tests/build_systems/clang_with_MD_flag/hello.d
/infer/tests/build_systems/codetoanalyze/mvn/**/target/
/infer/tests/build_systems/codetoanalyze/ndk-build/hello_app/libs/
/infer/tests/build_systems/codetoanalyze/ndk-build/hello_app/obj/
/infer/tests/build_systems/codetoanalyze/path with spaces/
/infer/tests/build_systems/codetoanalyze/rebar3/erl_hi/_build
/infer/tests/build_systems/codetoanalyze/utf8_*n_pwd
/infer/tests/build_systems/codetoanalyze/xcodebuild/simple_app/app_built
/infer/tests/build_systems/codetoanalyze/xcodebuild/simple_app/build/
/infer/tests/build_systems/diff/src
/infer/tests/build_systems/diff_*/src
/infer/tests/build_systems/differential_*/**/*.class
/infer/tests/build_systems/differential_*/**/Diff*.java
/infer/tests/build_systems/differential_*/**/Diff*.m
/infer/tests/build_systems/fb_differential_*/**/Diff*.java
/infer/tests/build_systems/fb_differential_*/**/Diff*.m
/infer/tests/build_systems/incremental_analysis_remove_file/src
/infer/tests/build_systems/incremental_analysis_cost_change/src
/infer/tests/build_systems/incremental_analysis_add_procedure/src
/infer/tests/build_systems/java_test_determinator/*.test
/infer/tests/build_systems/java_source_parser/*.test
/infer/tests/codetoanalyze/dotnet/*/*.json
/infer/tests/codetoanalyze/erlang/**/_build
/_release
/infer-source
# Docusaurus
/website/.docusaurus/
/website/node_modules
/website/build/
# generated by oUnit
/oUnit-all.cache
# autoconf-generated stuff
/acinclude.m4
/aclocal.m4
/autom4te.cache
/config.status
/m4/__GENERATED__*.m4
/configure
/Makefile.autoconf
/.buckversion
/.buck-java11
/.buckjavaversion
/*/.gitignore
/*/*/.gitignore
# IntelliJ files
/scripts/.idea/
/infer/tests/.idea/dictionaries
/infer/tests/.idea/inspectionProfiles
/infer/tests/.idea/tasks.xml
/infer/tests/.idea/uiDesigner.xml
/infer/tests/.idea/workspace.xml
/infer/tests/.idea/runConfigurations
/infer/tests/.idea/copyright/profiles_settings.xml
# VS code
.vscode/
.lsp-buck-out/
.lsp.buckd/
# Eclipse settings files
ocaml.prefs
/infer/.paths
/infer/src/.paths
org.eclipse.core.resources.prefs
# Arcanist
/arcanist/.phutil_module_cache
# MacOS generated files
.DS_Store
# Directories and files generated by Infer
infer-sources.tar.gz
infer-osx-*.tar.xz
infer-linux64-*.tar.xz
infer-out*
# Directories generated by buck
buck-out/
.buckd/
#other
/infer/man/man1/*.1
/infer/man/man1/*.1.gz
/infer/src/base/Version.ml
/infer/models/java/models/
/infer/models/models.jar
/infer/lib/java/models.jar
/infer/lib/models.sql
/infer/models/java/bootclasspath
/infer/models/c/out/
/infer/models/cpp/out/
/infer/models/objc/out/
/infer/lib/specs/c_models
/infer/lib/specs/clang_models
/infer/lib/specs/cpp_models
/infer/lib/specs/objc_models
/infer/lib/specs/clean_models
/infer/etc/clang_ast.dict
/infer/src/toplevel.mlpack
/external_repo
# atdgen generated files
/infer/src/atd/*_j.ml
/infer/src/atd/*_j.mli
/infer/src/atd/*_t.ml
/infer/src/atd/*_t.mli
/infer/src/atd/clang_*.ml
/infer/src/atd/clang_*.mli
# intelliJ files
/infer/src/backend/.projectSettings
/infer/annotations/annot_classes/
/infer/annotations/annotations.jar
/infer/annotations/annotations-src.jar
infer/src/.project
/dependencies/ocamldot/ocamldot
/dependencies/ocamldot/ocamldot.ml
/infer/src/mod_dep.dot
/infer/src/mod_dep.pdf
# generated by Maven
/infer/annotations/target
# generated by Erlang/Rebar3
*.beam
*.plt
*.swo
.erlang.cookie
.eunit
.rebar
.rebar3
ebin
erl_crash.dump
rebar.lock
rebar3.crashdump
# dune
/infer/_build
/infer/dune-workspace
/infer/src/dune.common
/infer/src/dune
/infer/src/al/dune
/infer/src/clang/dune
/infer/src/integration/dune
/infer/src/java/dune
/infer/src/nullsafe/unit/dune
/infer/src/opensource/dune
/infer/src/unit/dune
.merlin
# generated when looking for dead code
/infer/src/deadcode/.depend
/infer/src/deadcode/all_ml_files
/infer/src/deadcode/all_ml_files_copied
/infer/src/deadcode/all_mli_files
/infer/src/deadcode/all_mli_files_copied
/infer/src/deadcode/*.ml
/infer/src/deadcode/*.mli
/infer/src/deadcode/dune
_opam
_coverage
# facebook-clang-plugins
/facebook-clang-plugins/clang-ocaml/.depend
/facebook-clang-plugins/clang-ocaml/build
/facebook-clang-plugins/clang/install
/facebook-clang-plugins/clang/installed.version
/facebook-clang-plugins/clang/src/download
/facebook-clang-plugins/libtooling/build
/facebook-clang-plugins/xcode/*

@ -0,0 +1,11 @@
{
"force-delete-results-dir": true,
"siof-safe-methods": ["getGlobalNonPODAllowListed", "allow_listed::getGlobalNonPOD",
"allow_listed::TemplatedObject::getGlobalNonPOD"],
"skip-translation": [
{
"language": "Java",
"source_contains": "_SHOULD_BE_SKIPPED_"
}
]
}

@ -0,0 +1 @@
infer/src/.ocamlformat

@ -0,0 +1,45 @@
# Open Source Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to make participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment include:
Using welcoming and inclusive language
Being respectful of differing viewpoints and experiences
Gracefully accepting constructive criticism
Focusing on what is best for the community
Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
The use of sexualized language or imagery and unwelcome sexual attention or advances
Trolling, insulting/derogatory comments, and personal or political attacks
Public or private harassment
Publishing others private information, such as a physical or electronic address, without explicit permission
Other conduct which could reasonably be considered inappropriate in a professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
## Scope
This Code of Conduct applies within all project spaces, and it also applies when an individual is representing the project or its community in public spaces. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at opensource-conduct@fb.com. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the projects leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
[homepage]: https://www.contributor-covenant.org

@ -0,0 +1,230 @@
# Contribution Guidelines
## Reporting Issues
If you encounter a problem when using infer or if you have any questions, please open a
[GitHub issue](https://github.com/facebook/infer/issues/).
## Hacking on the Code
We welcome contributions via [pull requests on GitHub](https://github.com/facebook/infer/pulls).
### Development Dependencies
You'll want to install a few more dependencies to comfortably hack on the infer codebase. Simply
run:
```sh
make devsetup
```
### Building Infer for Development
- The default build mode ("dev") makes all build warnings *fatal*. If you want the build to ignore
warnings, for example to be able to test an infer executable before polishing the code to remove
warnings, you can build in "dev-noerror" mode with `make BUILD_MODE=dev-noerror`.
- Faster edit/build cycle when working on OCaml code inside infer/src/: build inside infer/src/
(skips building the models after infer has been built), and build only what is needed for type
checking with `make -j -C infer/src check`. You need to have run `make -j` at some point before.
- Alternatively, if you want to test your changes on a small example, build in bytecode mode:
`make -j -C infer/src byte`.
- In general, `make` commands from the root of the repository make sure that dependencies are in a
consistent and up-to-date state (e.g., they rebuild infer and the models before running steps that
use infer), while running `make` commands from within subdirectories generally assumes that
dependencies are already up-to-date.
For instance, running `make direct_java_biabduction_test` will rebuild infer and the models if
necessary before running the test, but running `make -C infer/tests/codetoanalyze/java/biabduction/ test`
will just execute the test.
### Debugging OCaml Code
- Printf-debug using `Logging.debug_dev`. It comes with a warning so
that you don't accidentally push code with calls to `debug_dev` to
the repo.
- Browse the documentation of OCaml modules in your browser with `make doc`
- When using `ocamldebug`, and in particular when setting break points
with `break @ <module> <line>` don't forget that an infer module `M`
is in reality called `InferModules__M`, or `InferBase__M`, or
... See the html documentation of the OCaml modules from `make doc`
if you're unsure of a module name.
```console
$ ledit ocamldebug infer/bin/infer.bc.exe
(ocd) break @ InferModules__InferAnalyze 100
Breakpoint 1 at 9409684: file backend/InferAnalyze.ml, line 99, characters 18-78
```
- To test the infer OCaml code you can use the OCaml toplevel. To
build the OCaml toplevel with the infer modules pre-loaded, run
`make toplevel` and follow the instructions.
To pass infer options to the toplevel, use `INFER_ARGS`, for
instance: `INFER_ARGS=--debug^-o^infer-out-foo`.
Many operations require the results directory and database to be
initialized with `ResultsDir.assert_results_dir ""`.
## Contributor License Agreement
We require contributors to sign our Contributor License Agreement. In
order for us to review and merge your code, please sign up at
https://code.facebook.com/cla. If you have any questions, please drop
us a line at cla@fb.com.
You are also expected to follow the [Code of Conduct](CODE_OF_CONDUCT.md), so please read that if you are a new contributor.
Thanks!
## Coding Style
### All Languages
- Indent with spaces, not tabs.
- Line width limit is 100 characters.
- In general, follow the style of surrounding code.
### OCaml
- The module IStd (infer/src/istd/IStd.ml) is automatically opened in every file. Beware that this
can cause weird errors such as:
```
$ pwd
/somewhere/infer/infer/src
$ cat base/toto.ml
let b = List.mem true [true; false]
$ make
[...]
File "base/toto.ml", line 1, characters 17-21:
Error: This variant expression is expected to have type 'a list
The constructor true does not belong to type list
```
- All modules open `IStd` using `open! IStd`. This is to make that fact more explicit (there's also
the compilation flag mentioned above), and also it helps merlin find the right types. In
particular this also opens `Core.Std`.
- Do not add anything to `IStd` unless you have a compelling reason to do so, for instance if you
find some utility function is missing and is not provided by
[`Core`](https://ocaml.janestreet.com/ocaml-core/latest/doc/core/).
- Polymorphic equality is disabled; use type-specific equality instead, even for primitive types
(e.g., `Int.equal`). However, if your module uses a lot of polymorphic variants with no arguments
you may safely `open PolyVariantEqual`.
If you try and use polymorphic equality `=` in your code you will get a compilation error, such as:
```
Error: This expression has type int but an expression was expected of type
[ `no_polymorphic_compare ]
```
- Alias and use `module L = Logging` for all your logging needs. Refer to its API in Logging.mli for
documentation.
- Check that your code compiles without warnings with `make -j test_build` (this also runs as part
of `make test`).
- Apart from `IStd` and `PolyVariantEqual`, refrain from globally `open`ing modules. Using
local open instead when it improves readability: `let open MyModule in ...`.
- Avoid the use of module aliases, except for the following commonly-aliased modules. Use
module aliases consistently (e.g., do not alias `L` to a module other than `Logging`).
```OCaml
module CLOpt = CommandLineOption
module F = Format
module L = Logging
module MF = MarkupFormatter
```
- Use `[@@deriving compare]` to write comparison functions whenever possible. Watch out for
[this issue](https://github.com/ocaml-ppx/ppx_deriving/issues/116) when writing
`type nonrec t = t [@@deriving compare]`.
- Use `let equal_foo = [%compare.equal : foo]` to write equality functions whenever possible.
- Use named arguments whenever the purpose of the argument is not immediately obvious. In
particular, use named arguments for boolean and integer parameters unless the name of the function
mentions them explicitly. Also use named arguments to disambiguate between several arguments of
the same type.
- Use named arguments for functions taken as argument; it is common to name a function argument
`f`. For instance: `List.map : 'a list -> f:('a -> 'b) -> 'b list`.
- In modules defining a type `t`, functions that take an argument of that type should generally have
that argument come first, except for for optional arguments: `val f : ?optional:bool -> t -> ...`.
- Use the `_hum` suffix to flag functions that output human-readable strings.
- Format code with [ocamlformat](https://github.com/ocaml-ppx/ocamlformat).
### C/C++/Objective-C
Follow `clang-format` (see ".clang-format" at the root of the repository).
## Testing your Changes
- Make sure infer builds: `make -j test_build`. Refer to the [installation
document](https://github.com/facebook/infer/blob/master/INSTALL.md) for details.
- Run the tests: `make -j 4 test` (adjust 4 to the number of cores available of your machine). The
tests (almost) all consist of the same three ingredients:
1. Some source code to run infer on.
2. An "issues.exp" file where each line represents one item of output of the test. For most tests,
one line is one issue reported by infer.
3. A `Makefile` that orchestrates the test, for instance running infer on the source code and
comparing the results with issues.exp using `diff`.
- If your changes modified some of the expected outputs and if the changes make sense, you can
update the expected test results by running `make test-replace`.
- If relevant, add a test for your change.
- To add a test that infer finds (or does not find) a particular issue, add your test in
"infer/tests/codetoanalyze/{language}/{analyzer}/". Look at the `Makefile` in that directory and
make sure it runs your test. "{analyzer}" is often an infer analyzer (as in
`infer -a {analyzer}`), with some special cases:
- "errors" is "infer"
- "frontend" is a mode where the expected output is the result of the translation of the program
by infer's clang frontend into infer's intermediate representation.
Name the procedures in your test following these conventions:
- Test procedures where the analyzer should report an error should end with the suffix `Bad`.
- Test procedures where the analyzer should not report an error should end with the suffix `Ok`.
- Test procedures documenting current limitations of the analyzer should have the prefix `FP_`
(for "false positive") or `FN_` (for "false negative") and a comment explaining why the analyzer
gets the wrong answer.
- To add a test that a certain build system integration or a command-line option works in a certain
way, add a test in "infer/tests/build_systems/".
- If you created a new Makefile for your test, add it to the root "Makefile", either to the
`DIRECT_TESTS` (first case) or to the `BUILD_SYSTEMS_TESTS` variable (second case). Gate the
test appropriately if it depends on Java or Clang or Xcode (see how other tests do it).
- It can be useful to look at the debug HTML output of infer to see the detail of the symbolic
execution. For instance:
```sh
$ infer --debug -- clang -c examples/hello.c
$ firefox infer-out/captured/hello.c.*.html
```
## Updating infer.opam and infer.opam.locked
tl; dr: Run `make opam/infer.opam.locked`.
infer.opam.locked records fixed versions of the opam dependencies known to work with infer and to respect
the constraints in opam. This prevents unpredictable breakages of infer or its dependencies,
especially for infer releases, for which it is more difficult to change their package constraints
after the fact.
To add an opam package or update its version constraints, edit 'infer.opam' then run `make infer.opam.locked`.

@ -0,0 +1,3 @@
Kihong Heo <khheo@ropas.snu.ac.kr>
Sungkeun Cho <skcho@ropas.snu.ac.kr>
Kwangkeun Yi <kwang@ropas.snu.ac.kr>

@ -0,0 +1,290 @@
## Version 1.1.0
### Frontends
- New [JSON input format for SIL](https://github.com/facebook/infer/pull/1361). This new format was contributed from [Infer#](https://github.com/microsoft/infersharp), whose C# frontend for Infer [emits SIL as JSON using this format](https://github.com/microsoft/infersharp/wiki/InferSharp:-A-Scalable-Code-Analytics-Tool-for-.NET).
### Build System Integrations
- Clang upgraded to version 11.0
### Checkers
- [Liveness](https://fbinfer.com/docs/checker-liveness/): properly handle exceptional control flow
- [Pulse](https://fbinfer.com/docs/checker-pulse/):
- Added preliminary Java support
- New [Uninitialized value bug type](https://fbinfer.com/docs/all-issue-types/#pulse_uninitialized_value), aiming to replace the previous [Uninit](https://fbinfer.com/docs/checker-uninit/) checker as this one is inter-procedural and more precise.
- [OPTIONAL_EMPTY_ACCESS](https://fbinfer.com/docs/all-issue-types/#optional_empty_access) is now enabled by default
- **NEW checker** [Topl](https://fbinfer.com/docs/checker-topl/)(early alpha): An experimental checker framework: write your own analysis as a state machine representing a temporal property over multiple memory objects at once, eg to write a taint analysis. Topl is based on Pulse.
- Miscellaneous improvements to cost, inferbo, nullsafe, racerd, starvation
## Version 1.0.0
### Checkers
[AL](https://fbinfer.com/docs/checker-linters) is now deprecated and may be removed in future versions.
[Annotation Reachability](https://fbinfer.com/docs/checker-annotation-reachability)
- reporting format improvements (the trace is no longer included in the report text, only as metadata)
[Biabduction](https://fbinfer.com/docs/checker-biabduction)
- disable some less-used bug types
[Eradicate](https://fbinfer.com/docs/checker-eradicate)
- remove "Field not mutable" check
[RacerD](https://fbinfer.com/docs/checker-racerd)
- Now defaults to "angelic" ownership: an unknown function is assumed to return owned objects.
- No more reports on races on paths rooted on temporary or local variables, as these are unreliably modelled.
[Litho Required Properties](https://fbinfer.com/docs/checker-litho-required-props): *new Java checker* to check that all non-optional @Props have been specified when constructing Litho components.
[Self in Block](https://fbinfer.com/docs/checker-self-in-block): *new Objective-C checker* to detect when an Objective-C block incorrectly captures self
[Starvation](https://fbinfer.com/docs/checker-starvation)
- New experimental "global" analysis mode. Enable with `--starvation-whole-program`
Miscellaneous improvements to most checkers, in particular [Annotation Reachability](https://fbinfer.com/docs/checker-annotation-reachability), [Cost Analysis](https://fbinfer.com/docs/checker-cost), [Eradicate](https://fbinfer.com/docs/checker-eradicate), [Inefficient Keyset Iterator](https://fbinfer.com/docs/checker-inefficient-keyset-iterator), [InferBO](https://fbinfer.com/docs/checker-bufferoverrun), [Pulse](https://fbinfer.com/docs/checker-pulse), [RacerD](https://fbinfer.com/docs/checker-racerd), [Starvation](https://fbinfer.com/docs/checker-starvation), and [Uninitialized Value](https://fbinfer.com/docs/checker-uninit).
### Build System Integrations
- The Gradle integration now captures Java files in parallel
- New Buck integration for Java, enable with `--buck-java-flavor`
- Clang upgraded to version 9.0
### Command Line Interface
- **New subcommand** [`infer help`](https://fbinfer.com/docs/man-infer-help) to display information about checkers and issue types.
- **New subcommand** [`infer debug`](https://fbinfer.com/docs/man-infer-debug) that replaces the uses of `infer explore` not related to reported issues.
- `--debug` no longer disables filtering, you have to pass `-g -F` to get the previous behaviour back.
- All disk artefacts (except the Java type environment) are now stored in the SQLite database in infer-out/results.db. The contents of the database can be explored with `infer debug`.
- Changed how to select the Buck integration. The old command line interface is still supported but is now deprecated.
- clang via "flavors", activated with `--flavors`, now with `--buck-clang`
- clang via "compilation DB", activated with `--buck-compilation-database`, unchanged
- Java via "genrule", activated with `--genrule-master-mode`, now with `--buck-java`
- Java "without genrules", used to be activated by not specifying any other Buck mode, **deleted**
- In addition, there is a new Java integration, activated with `--buck-java-flavor`
- The textual version of the report infer-out/bugs.txt has moved to infer-out/report.txt. The bugs.txt file is still created with dummy contents to allow for a smooth transition.
- Removed the `--report-hook` option.
- Properly terminate on `Control-C` instead of sometimes leaving around zombie processes.
- Spec files (summaries) are now stored in the database. Explore with `infer debug --procedures --procedures-summary`.
### Documentation
- Revamped online documentation for bug types and checkers. See the [list of all issue types](https://fbinfer.com/docs/all-issue-types) and the pages for each checker. The `infer help` command can be used locally to also get this information and more.
- Access the documentation for previous and future versions [online](https://fbinfer.com/docs/versions).
- The https://fbinfer.com/ website now [uses Docusaurus 2](https://github.com/facebook/infer/pull/1190).
### Internal Changes
- Folded the facebook-clang-plugins sub-repo inside the infer repository; there is no more git submodule for it.
- Improve internal documentation of [OCaml source code](https://fbinfer.com/odoc/1.0.0/infer/infer.html).
- Build with OCaml 4.11.1 and dune 2.7.1
- Migrated our Python 2 code to OCaml
- Split the infer OCaml source code into individual dune libraries.
- Better defaults for SQLite, and a write daemon to reduce contention.
- New analysis schedulers that speed up the analysis phase. Enable with `--scheduler callgraph` or `--scheduler restart`.
- Infer no longer builds by default in "opt" mode (optimised, using OCamls flambda pass). The default is now "dev", which does not include as many optimisations (hence builds faster) and turns warnings into errors.
- The starvation checker is now based on SIL instead of HIL.
## Version 0.17.0
- There's a new `--inefficient-keyset-iterator` checker for finding inefficient uses of Java's keyset iterators that retrieve both key and value (on by default).
- Complete the set of Android thread annotations and Java nullability annotations. Updated artifacts are available on [Maven Central](https://search.maven.org/artifact/com.facebook.infer.annotation/infer-annotation/0.17.0/jar).
- `--starvation` is now on by default. This analysis catches problems with threads not being able to make progress due to locking issues, incorrect scheduling priorities, etc. For instance, on Android calling Future.get from a UiThread without a sensible timeout will be flagged as a starvation issue.
- New Objective-C linter for calls to `@optional` methods: `UNSAFE_CALL_TO_OPTIONAL_METHOD`, enabled by default.
- A new call-graph scheduler (`--call-graph-schedule`) improves performance of the analysis phase of Infer, especially when the number of files to analyze is less than available CPUs.
- A new flag `--oom-threshold` allows to throttle the analysis when the amount of free memory is below the provided threshold.
- New genrule based Buck/Java integration is much faster than the previous one, use with `--genrule-master-mode`.
- Infer's internal clang is now in version 8.0.0.
- Update to javalib 3.1 provides better compatibility with Java 9 and Java 11. Refer to [their change log](https://github.com/javalib-team/javalib/blob/master/CHANGELOG) for more details.
- Infer can now be built and run on MacOS Mojave without fiddling with `SDKROOT` (although you still might need it with non-standard toolchain setup).
- [β] __Pulse__ is a new experimental lifetime analysis for C++, give it a try with `--pulse`. Beware that it doesn't report much yet.
- `--ownership` checker was superseded by Pulse and removed.
## Version 0.16.0
Backend analyses:
- A brand new analysis to compute the runtime cost of methods and functions: passing `--cost` (off by default) to Infer will output a costs-report.json file describing, among others, the computational complexity of each function in the code using the big-O notation, eg `O(1)`, `O(list.length)`, ...
- The deadlock detection analysis has been ported to C++ and Objective-C and mainly focuses on self-deadlocks (taking a mutex twice). Activate with `--starvation` (off by default).
- The data race detector RacerD has been ported to Objective-C and detects races on fields protected by a C++ mutex. It reports "Thread Safety Violation" and "GuardedBy Violation" errors on Java and "Lock Consistency Violation" on C++ and Objective-C. Activate with `--racerd` (on by default).
- A progress bar is displayed while the analysis is running
- Countless improvements and tweaks, in particular in RacerD and in analyses for C++.
Frontends:
- Infer now ships with clang version 7.0.1
- Support for Java up to version 11
## Version 0.15.0
- switch infer license to MIT
- publish binaries
- [clang] lots of improvements to the frontend
## Version 0.14.0
- New checker: `--ownership` detects a subset of use-after-free issues due to bad manual memory management. This is a rough prototype of Rust-style borrow checker for C++. (enabled by default, C++)
- New checker: `--uninit` detects uses of uninitialized values (enabled by default, C/C++/Objective-C)
- New checker: `--racerd` now also detects inconsistent lock usage in C++. Also improved the lock domain to reduce false positives for all languages.
- Improved C++ support: destructors are now properly translated; addresses and pointers are handled more precisely
- Improved retain cycles detection (Objective-C)
- Upgraded the internal clang to clang 7
- [internal] SQLite is being used to store some of infer's analysis artefacts instead of storing them in files on disk. This improves analysis speed and reduces load on the OS.
## Version 0.13.1
This is a fix for the 0.13.0 release, whose build broke due to changes in opam.
## Version 0.13.0
- Infer now runs multiple checkers at the same time by default, including the biabduction analysis that was the previous and only default. In particular, we are pleased to introduce [RacerD](http://fbinfer.com/docs/racerd.html) for race detection in Java. The following checkers are activated by default: annotation reachability (Java), biabduction (C/C++/ObjC, Java), fragment retains view (Java), immutable cast (Java), liveness (C/C++/ObjC), printf args (Java), quandary (C/C++/ObjC, Java), RacerD (C/C++/ObjC, Java), SIOF (C/C++/ObjC). Each checker may report several issue types.
- Upgraded to clang 5.0
- Richer DSL for writing linters ([AL](http://fbinfer.com/docs/linters.html)), and a new default linter for `const` pointers in Objective-C
- Lots of perf improvements and bug fixes, and improved logging
Please note the following breaking changes:
- `-a eradicate` is now simply `--eradicate` and can run alongside other checkers
- `inferTraceBugs` is now the `explore` subcommand: `infer explore --help`
- infer now depends on sqlite
## Version 0.12.1
Hotfix release to update infer's opam dependencies to cope with upgrades of cppo in opam (in particular, #718).
## Version 0.12.0
- introduces *subcommands* and man pages for all subcommands
- This release introduces **AL**, a language for writing linters against the clang AST. AL lets you check [syntactic properties](http://fbinfer.com/docs/linters-bug-types.html) of source code by traversing the AST of the program. Using the included domain-specific language (DSL), you can [write your own set of checks](http://fbinfer.com/docs/linters.html).
## Version 0.11.0
- [Java] ThreadSafety analyzer is now on by default; run it with `infer -a checkers ...`. This checker will try and detect races (unprotected concurrent accesses with at least one write) in classes bearing the `@ThreadSafe` annotation.
- Infer now builds using OCaml 4.04.0.
## Version 0.10.0
- [Clang] C++ support.
- [Clang] Improved support for cmake and Xcode compilation databases. Use with `infer --compilation-database compile_commands.json` (for cmake and Buck), or with `infer --compilation-database-escaped compile_commands.json` (for xcbuild and xcpretty).
- [C++] New [SIOF Checker](http://fbinfer.com/docs/experimental-checkers.html).
- [iOS] New [linter for target SDK version](http://fbinfer.com/docs/linters-bug-types.html#UNAVAILABLE_API_IN_SUPPORTED_IOS_SDK). Use with `infer --iphoneos-target-sdk-version <min version you support> ...` or with `infer -a linters --iphoneos-target-sdk-version <min version you support> ...`.
- [Java] New [Thread Safety Checker](http://fbinfer.com/docs/experimental-checkers.html).
- [Java] Smarter analysis of dynamic dispatch.
- [Java] Improved Maven integration.
- [Java] `@SuppressWarnings` support removed. Use `@SuppressLint` instead. `android.annotation.SuppressLint` is only available on Android, but do let us know if that is an issue for you.
## Version 0.9.5
fix for #577
## Version 0.9.4.1
hotfix: https://github.com/facebook/infer/commit/9393c4f533c153e4c6f984c0752d1b08a4fa1e50
## Version 0.9.4
- [Java] preliminary support for Java 8: infer no longer skips methods containing Java 8 code
- [clang] support for clang compilation databases
- [Xcode] more robust integration using the compilation database (requires [xcpretty](https://github.com/supermarin/xcpretty))
- [iOS] added checks for some of the [ComponentKit best practices](http://componentkit.org/docs/never-subclass-components.html)
- lots of under-the-hood improvements, including perf improvements and bug fixes
## Version 0.9.3
- Fix issues with using Infer with Clang 4.0 and Xcode 8
- Various fixes and performance improvements
## Version 0.9.2
No changelog.
## Version 0.9.1
- enable packaging via Homebrew
- fix an issue with locales
## Version 0.9.0
- lots of perf improvements and fixes across all analyses (thanks to everyone who reported issues and made pull requests!)
- [experimental] C++ language support. See `--cxx` in `infer --help`. This is still in heavy development and only includes a few bug types. Feedback welcome!
## Version 0.8.1
- [Objective-C and C] upgrade clang to version 3.8.0
- [all] bugfixes
## Version 0.8.0
- New `--reactive` mode to rapidly analyze the effects of a code change. Be sure to check out [the documentation of the new workflow](http://fbinfer.com/docs/infer-workflow.html#global-default-and-differential-workflows). As a result, the incremental mode (`--incremental`) is now deprecated.
- New XML output, compatible with output from other static analyzers, eg [PMD](https://pmd.github.io/). To use it, pass the `--pmd-xml` flag to Infer (see `infer --help`).
- Use `@SuppressWarnings("infer")` in your Java projects to annotate methods or classes where Infer shouldn't report.
- This release incorporates a number of contributions (#284 #289 #300 #301) and addresses a number of issues (#279 #281 #283 #288 #291 #294).
## Version 0.7.0
- addresses a number of bugs, eg #270 #274 #275 #276
- [all] add summary of the analysis results at the end of the console output
- [android] new ["Fragment retains View" checker](http://fbinfer.com/docs/checkers-bug-types.html)
## Version 0.6.0
- [android] fixed intermittent infinite loop
- [iOS] new check for [capturing](http://fbinfer.com/docs/infer-bug-types.html#CXX_REFERENCE_CAPTURED_IN_OBJC_BLOCK) a C++ reference in an Objective-C block
## Version 0.5.0
- [android] detection of context leaks
- [android] support for `@PerformanceCritical` and `@Expensive` method annotations. Infer will check that an expensive method is never called during the execution of a performance critical method (run it with `infer -a checkers -- ...`).
- [iOS] new check to catch strong delegate properties, likely to create retain cycles
- [iOS] new check to catch direct accesses to atomic properties, which can cause race conditions
- [all] performance improvements all-around
## Version 0.4.0
No changelog.
## Version 0.3.0
No changelog.
## Version 0.2.0
- [java] analyze class files with $$ in the name (closes #3 more)
- [java] don't fail on compilation warnings (closes #18)
- [clang] support __nullable et al. (closes #4)
- add an Infer:Checkers for printf arguments
## Version 0.1.1
- [java] no more crash on class names containing "$$" (closes #3)
- [java] model for `assert` (closes #68)
- [objective-c] support for `@import` (closes #2)
- [c family] Infer now always reports on the right line numbers (closes #31)
- [c family] fix c++ compilation errors (closes #37)
## Version 0.1.0
Initial release

@ -0,0 +1,7 @@
#Files in infer/bin/
## Top-level commands
*infer* : Main command to run Infer. Check out the docs for instructions on how to use it.
*infer-<command>* : Infer subcommands. Running `infer-<command> [options]` is the same as running `infer <command> [options]`.

@ -0,0 +1,111 @@
# How to install Infer from source
## Binary versions
We provide a binary release of Infer. We encourage you to use this
release as compiling infer's dependencies is time-consuming. Follow
the instructions in our [Getting
Started](http://fbinfer.com/docs/getting-started/#get-infer)
page to install Infer.
## Infer dependencies for MacOSX
Here are the prerequisites to be able to compile Infer on MacOSX. This
is required to compile everything from source.
- opam >= 2.0.0 (instructions [here](https://opam.ocaml.org/doc/Install.html#OSX))
- sqlite
- pkg-config
- Java (only needed for the Java analysis)
- CMake (only needed for the C/Objective-C analysis)
- Ninja (optional, if you wish to use sequential linking when building the
C/Objective-C analysis)
- clang in Xcode command line tools. You can install them with the command
`xcode-select --install` (only needed for the C/Objective-C analysis)
- Xcode >= 6.1 (only needed for the C/Objective-C analysis)
- autoconf >= 2.63 and automake >= 1.11.1 (if building from git)
- gmp
- mpfr
You can install some of these dependencies using
[Homebrew](http://brew.sh/):
```sh
brew install autoconf automake cmake opam pkg-config sqlite gmp mpfr
brew cask install java
```
## Infer dependencies for Linux
Here are the prerequisites to be able to compile Infer on Linux. This
is required to compile everything from source.
- opam >= 2.0.0
- pkg-config
- Java (only needed for the Java analysis)
- gcc >= 5.X or clang >= 3.4 (only needed for the C/Objective-C analysis)
- autoconf >= 2.63 and automake >= 1.11.1 (if building from git)
- CMake (only needed for the C/Objective-C analysis)
- Ninja (optional, if you wish to use sequential linking when building the
C/Objective-C analysis)
See also the distro-specific instructions for Ubuntu and Debian below.
## Install Infer from source
Run the following commands to get Infer up and running:
```sh
# Checkout Infer
git clone https://github.com/facebook/infer.git
cd infer
# Compile Infer
./build-infer.sh java
# install Infer system-wide...
sudo make install
# ...or, alternatively, install Infer into your PATH
export PATH=`pwd`/infer/bin:$PATH
```
Replace `./build-infer.sh java` with `./build-infer.sh clang` to build
the C and Objective-C analyzer from source. Beware that this command
may take a really long time because it will compile a custom version
of clang. This custom version is used by Infer to parse C and
Objective-C source code.
See `./build-infer.sh --help` for more options, eg `./build-infer.sh`
on its own will build the analyzers for both Java and C/ObjC.
## Install Infer from source without opam
If for some reason you prefer to install Infer's OCaml dependencies by
some means other than opam, you can still compile Infer by running:
```sh
./autogen.sh
./configure # Disable Java or C/C++/ObjC analyzers with --disable-java-analyzers or --disable-c-analyzers
make
# install Infer system-wide...
sudo make install
# ...or, alternatively, install Infer into your PATH
export PATH=`pwd`/infer/bin:$PATH
```
## How to install the dependencies on Linux
See the Dockerfile in docker/ for inspiration. It includes the
dependencies needed to build Infer on Debian 9 (stretch).
### Setting up opam
Get opam from your distribution, or from the
[opam website](http://opam.ocaml.org/doc/Install.html#Binarydistribution).
The OCaml dependencies needed by Infer are automatically handled by
opam when running `./build-infer.sh`.

@ -0,0 +1,10 @@
Please make sure your issue is not addressed in the [FAQ](https://fbinfer.com/docs/support#troubleshooting).
Please include the following information:
- [ ] The version of infer from `infer --version`.
- [ ] Your operating system and version, for example "Debian 9", "MacOS High Sierra", whether you are using Docker, etc.
- [ ] Which command you ran, for example `infer -- make`.
- [ ] The full output in a paste, for instance a [gist](https://gist.github.com/).
- [ ] If possible, a minimal example to reproduce your problem (for instance, some code where
infer reports incorrectly, together with the way you run infer to reproduce the incorrect
report).

@ -0,0 +1,21 @@
MIT License
Copyright (c) Facebook, Inc. and its affiliates.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

1022
Makefile

File diff suppressed because it is too large Load Diff

@ -0,0 +1,101 @@
# Copyright (c) Facebook, Inc. and its affiliates.
#
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.
@SET_MAKE@
ANT = @ANT@
ATDGEN = @ATDGEN@
bindir = @bindir@
BUCK = @BUCK@
BUILD_C_ANALYZERS = @BUILD_C_ANALYZERS@
BUILD_ERLANG_ANALYZERS = @BUILD_ERLANG_ANALYZERS@
BUILD_JAVA_ANALYZERS = @BUILD_JAVA_ANALYZERS@
BUILD_PLATFORM = @BUILD_PLATFORM@
CAML_LD_LIBRARY_PATH = @CAML_LD_LIBRARY_PATH@
CC = @CC@
CFLAGS = @CFLAGS@
CLANG_INCLUDES = @CLANG_INCLUDES@
CLANG_PREFIX = @CLANG_PREFIX@
CMAKE = @CMAKE@
CPATH = @CPATH@
CPP = @CPP@
CXX = @CXX@
CXXFLAGS = @CXXFLAGS@
# this is useless but autoconf is picky...
datarootdir = @datarootdir@
EMACS = @EMACS@
ENABLE_OCAMLOPT_CUSTOM_CC = @ENABLE_OCAMLOPT_CUSTOM_CC@
ENABLE_OCAML_BINANNOT = @ENABLE_OCAML_BINANNOT@
exec_prefix = @exec_prefix@
GNU_SED = @GNU_SED@
HAS_OBJC = @HAS_OBJC@
INFER_MAJOR = @INFER_MAJOR@
INFER_MAN_LAST_MODIFIED = @INFER_MAN_LAST_MODIFIED@
INFER_MINOR = @INFER_MINOR@
INFER_PATCH = @INFER_PATCH@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_NAME_TOOL = @INSTALL_NAME_TOOL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
IS_FACEBOOK_TREE = @IS_FACEBOOK_TREE@
IS_RELEASE_TREE = @IS_RELEASE_TREE@
JAVA_MAJOR_VERSION = @JAVA_MAJOR_VERSION@
JAVAC = @JAVAC@
LDD = @LDD@
LDFLAGS = @LDFLAGS@
libdir = @libdir@
# override in your `make` command to make the install relocatable
libdir_relative_to_bindir = $(libdir)
LIBRARY_PATH = @LIBRARY_PATH@
LIBS = @LIBS@
mandir = @mandir@
MENHIR = @MENHIR@
MKDIR_P_CMD = case "@MKDIR_P@" in \
./*) printf "$(ROOT_DIR)/@MKDIR_P@\n";; \
*) printf "@MKDIR_P@\n";; \
esac
MKDIR_P = $(shell $(MKDIR_P_CMD))
MVN = @MVN@
NCPU = @NCPU@
NDKBUILD = @NDKBUILD@
NINJA = @NINJA@
OCAMLBUILD = @OCAMLBUILD@
OCAMLC = @OCAMLC@
OCAMLFIND = @OCAMLFIND@
OCAMLFORMAT_EXE = @OCAMLFORMAT@
OCAMLLEX = @OCAMLLEX@
OCAMLOPT = @OCAMLOPT@
OPAM = @OPAM@
OPAMROOT = @OPAMROOT@
OPAMSWITCH = @OPAMSWITCH@
OTOOL = @OTOOL@
PATCHELF = @PATCHELF@
PATH = @PATH@
prefix = @prefix@
REBAR3 = @REBAR3@
SDKROOT = @SDKROOT@
SHASUM = @SHASUM@
USER_JAVA_HOME = @USER_JAVA_HOME@
UTOP = @UTOP@
WINDOWS_BUILD = @WINDOWS_BUILD@
XCODE_BASE = @XCODE_BASE@
XCODE_SELECT = @XCODE_SELECT@
XCPRETTY = @XCPRETTY@
XCRUN = @XCRUN@
ifneq (,$(findstring s,$(MAKEFLAGS)))
# quiet mode
LN_S = @LN_S@
else
LN_S = @LN_S@ -v
endif
# Export parts of the config relevant to running other programs
export PATH := $(PATH)
export CPATH := $(CPATH)
export LIBRARY_PATH := $(LIBRARY_PATH)
export CAML_LD_LIBRARY_PATH := $(CAML_LD_LIBRARY_PATH)
export OPAMROOT := $(OPAMROOT)
export SDKROOT := $(SDKROOT)

@ -0,0 +1,211 @@
# Copyright (c) Facebook, Inc. and its affiliates.
#
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.
ORIG_SHELL = $(shell echo "$$SHELL")
SHELL = bash -e -o pipefail -u
ORIG_SHELL_PATH = $(shell printf "%s" "$$PATH")
# Make infer crash a bit more often to detect issues in the way we call infer within this repo, eg,
# using deprecated options.
export INFER_STRICT_MODE=1
include $(ROOT_DIR)/Makefile.autoconf
# possible values:
# - dev: flambda optimizations disabled, build warnings are errors
# - dev-noerror: flambda optimizations disabled, build warnings do not fail the build
# - opt: flambda optimizations enabled, build warnings do not fail the build
BUILD_MODE = dev
DUNE_BUILD = dune build --profile=$(BUILD_MODE)
PLATFORM = $(shell uname)
COPY = cp -f
COPY_DIR = cp -Rf
REMOVE = rm -f
REMOVE_DIR = rm -rf
ABSOLUTE_ROOT_DIR = $(shell cd $(ROOT_DIR) && pwd)
DEPENDENCIES_DIR = $(ABSOLUTE_ROOT_DIR)/dependencies
DOCKER_DIR = $(ABSOLUTE_ROOT_DIR)/docker
EXAMPLES_DIR = $(ABSOLUTE_ROOT_DIR)/examples
INFER_DIR = $(ABSOLUTE_ROOT_DIR)/infer
FCP_DIR = $(ABSOLUTE_ROOT_DIR)/facebook-clang-plugins
M4_DIR = $(ABSOLUTE_ROOT_DIR)/m4
SCRIPT_DIR = $(ABSOLUTE_ROOT_DIR)/scripts
WEBSITE_DIR = $(ABSOLUTE_ROOT_DIR)/website
FCP_CLANG_OCAML_DIR = $(FCP_DIR)/clang-ocaml
ANNOTATIONS_DIR = $(INFER_DIR)/annotations
BIN_DIR = $(INFER_DIR)/bin
ETC_DIR = $(INFER_DIR)/etc
LIB_DIR = $(INFER_DIR)/lib
MAN_DIR = $(INFER_DIR)/man
MODELS_DIR = $(INFER_DIR)/models
JAVA_BUILTINS_DIR = $(MODELS_DIR)/java/builtins
JAVA_MODELS_DIR = $(MODELS_DIR)/java/src
SRC_DIR = $(INFER_DIR)/src
BUILD_DIR = $(INFER_DIR)/_build
JAVA_LIB_DIR = $(LIB_DIR)/java
INFER_BIN = $(BIN_DIR)/infer
INFER_COMMANDS = \
infer-analyze \
infer-capture \
infer-compile \
infer-debug \
infer-explore \
infer-help \
infer-report \
infer-reportdiff \
infer-run \
INFERTOP_BIN = $(BIN_DIR)/infertop.bc.exe
INFERUNIT_BIN = $(BIN_DIR)/inferunit.bc.exe
CHECKCOPYRIGHT_BIN = $(BIN_DIR)/checkCopyright
INFER_CREATE_TRACEVIEW_LINKS = InferCreateTraceViewLinks
INFER_CREATE_TRACEVIEW_LINKS_BIN = $(BIN_DIR)/$(INFER_CREATE_TRACEVIEW_LINKS)
INFER_COMMAND_MANUALS = $(INFER_COMMANDS:%=$(MAN_DIR)/man1/%.1)
INFER_COMMAND_TEXT_MANUALS = $(INFER_COMMANDS:%=$(MAN_DIR)/man1/%.txt)
INFER_MANUAL = $(MAN_DIR)/man1/infer.1
INFER_GROFF_MANUALS = $(INFER_COMMAND_MANUALS) $(INFER_MANUAL)
INFER_GROFF_MANUALS_GZIPPED = $(INFER_GROFF_MANUALS:=.gz)
INFER_TEXT_MANUAL = $(MAN_DIR)/man1/infer.txt
INFER_FULL_TEXT_MANUAL = $(MAN_DIR)/man1/infer-full.txt
INFER_TEXT_MANUALS = $(INFER_COMMAND_TEXT_MANUALS) $(INFER_TEXT_MANUAL) $(INFER_FULL_TEXT_MANUAL)
INFER_MANUALS = $(INFER_GROFF_MANUALS) $(INFER_TEXT_MANUALS)
ifeq ($(BUILD_JAVA_ANALYZERS),yes)
JAVA_HOME=$(USER_JAVA_HOME)
endif
# marker to keep track of when models have been rebuilt
MODELS_RESULTS_FILE = $(LIB_DIR)/models.sql
ANDROID_JAR = $(LIB_DIR)/java/android/android-23.jar
GUAVA_JAR = $(DEPENDENCIES_DIR)/java/guava/guava-23.0.jar
INFER_ANNOTATIONS_JAR = $(ANNOTATIONS_DIR)/annotations.jar
JACKSON_JAR = $(DEPENDENCIES_DIR)/java/jackson/jackson-2.2.3.jar
JSR_305_JAR = $(DEPENDENCIES_DIR)/java/jsr-305/jsr305.jar
JAVA_MODELS_JAR = $(LIB_DIR)/java/models.jar
JAVA_DEPS_NO_MODELS = \
$(ANDROID_JAR) $(GUAVA_JAR) $(JACKSON_JAR) $(JSR_305_JAR) $(INFER_ANNOTATIONS_JAR) \
$(INFER_BIN)
JAVA_DEPS = $(JAVA_DEPS_NO_MODELS) $(JAVA_MODELS_JAR) $(MODELS_RESULTS_FILE)
CLANG_DEPS_NO_MODELS = $(INFER_BIN)
CLANG_DEPS = $(CLANG_DEPS_NO_MODELS) $(MODELS_RESULTS_FILE)
XCODE_ISYSROOT_SUFFIX = Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk
ifeq ($(wildcard $(XCODE_BASE)/$(XCODE_ISYSROOT_SUFFIX)),)
XCODE_ISYSROOT_SUFFIX = SDKs/MacOSX.sdk
endif
ifeq ($(HAS_OBJC),yes)
XCODE_ISYSROOT = $(XCODE_BASE)/$(XCODE_ISYSROOT_SUFFIX)
endif
define copy_or_same_file
$(COPY) "$(1)" "$(2)" || diff -q "$(1)" "$(2)"
endef
INTERACTIVE = $(shell [ -t 0 ] && echo 1)
SILENT = $(findstring s,$(filter-out -%,$(firstword $(MAKEFLAGS))))
ifeq (1,$(INTERACTIVE))
TERM_ERROR = $(shell printf '\e[31;1m')
TERM_INFO = $(shell printf '\e[;1m')
TERM_SUCCESS = $(shell printf '\e[;2m')
TERM_RESET = $(shell printf '\e[0m')
endif
ifneq ($(VERBOSE),1)
# quiet
QUIET = @
endif
MAKE := $(MAKE) INTERACTIVE=$(INTERACTIVE)
# check if pid_max can be found else default to whatever
KERNEL_PID_MAX_FILE = /proc/sys/kernel/pid_max
MAX_PID_SIZE = $(shell \
[ -r $(KERNEL_PID_MAX_FILE) ] \
&& echo $$(( $$(wc -m < $(KERNEL_PID_MAX_FILE)) - 1 )) \
|| echo 5)
# Arguments:
# $(1) is a string describing the command
# $(2) is the command to run
#
ifeq ($(VERBOSE),1)
define silent_on_success
$(2)
endef
else
# Run and time the command and redirect its stdout and stderr to files. Display info about the
# command only in case of error. Try to be as helpful as possible in the error case.
#
# The PID of the process is used in the names of the output files, and as a prefix for each error
# message so that it's possible to piece error messages together even when they are interleaved with
# other messages from concurrent `make` processes.
#
# Detect if we are already wrapped inside a silent_on_success call and try not to clutter the output
# too much in that case.
define silent_on_success
if [ -n "$${INSIDE_SILENT_ON_SUCCESS-}" ]; then \
echo '*** inner $(1)'; \
echo '*** inner command: $(2)'; \
echo '*** inner CWD: $(CURDIR)'; \
($(2)); \
exit $$?; \
fi; \
export INSIDE_SILENT_ON_SUCCESS=1; \
HASH="$$$$"; \
UNIX_START_DATE=$$(date +"%s"); \
HUMAN_START_DATE=$$(date +"%H:%M:%S"); \
if [ -z $(SILENT) ]; then \
printf '[%s][%$(MAX_PID_SIZE)s] $(TERM_INFO)%s...$(TERM_RESET)\n' \
"$$HUMAN_START_DATE" "$$HASH" "$(1)"; \
fi; \
$(MKDIR_P) $(ABSOLUTE_ROOT_DIR)/_build_logs; \
ERRCODE=0; \
($(2)) 1>$(ABSOLUTE_ROOT_DIR)/_build_logs/cmd-$$HASH.out \
2>$(ABSOLUTE_ROOT_DIR)/_build_logs/cmd-$$HASH.err \
|| ERRCODE=$$?; \
if [ $$ERRCODE != 0 ]; then \
echo "$(TERM_ERROR)[*ERROR**][$$HASH] *** ERROR '$(1)'$(TERM_RESET)" >&2; \
echo "$(TERM_ERROR)[*ERROR**][$$HASH] *** command: '$(2)'$(TERM_RESET)" >&2; \
echo "$(TERM_ERROR)[*ERROR**][$$HASH] *** CWD: '$(CURDIR)'$(TERM_RESET)" >&2; \
echo "$(TERM_ERROR)[*ERROR**][$$HASH] *** stdout:$(TERM_RESET)" >&2; \
sed -e "s/^\(.*\)$$/$(TERM_ERROR)[*ERROR**][$$HASH]$(TERM_RESET) \1/" \
$(ABSOLUTE_ROOT_DIR)/_build_logs/cmd-$$HASH.out; >&2; \
echo "$(TERM_ERROR)[*ERROR**][$$HASH] *** stderr:$(TERM_RESET)" >&2; \
sed -e "s/^\(.*\)$$/$(TERM_ERROR)[*ERROR**][$$HASH]$(TERM_RESET) \1/" \
$(ABSOLUTE_ROOT_DIR)/_build_logs/cmd-$$HASH.err; >&2; \
exit $$ERRCODE; \
elif [ -z $(SILENT) ]; then \
UNIX_END_DATE=$$(date +"%s"); \
printf '[%7ss][%$(MAX_PID_SIZE)s] $(TERM_SUCCESS)SUCCESS %s$(TERM_RESET)\n' \
"$$(($$UNIX_END_DATE - $$UNIX_START_DATE))" "$$HASH" "$(1)"; \
fi
endef
endif
# print any variable for Makefile debugging
print-%:
$(QUIET)echo '$*=$($*)'
TESTLOCK = $(INFER_DIR)/tests/testlock.py

@ -0,0 +1 @@
Please see [CONTRIBUTING.md](./CONTRIBUTING.md) for how to set up your development environment and run tests.

@ -0,0 +1,24 @@
<img src="website/static/img/logo.png" alt="logo" width="15%" />
# Infer [![Build Status](https://travis-ci.org/facebook/infer.svg?branch=master)](https://travis-ci.org/facebook/infer)
[Infer](http://fbinfer.com/) is a static analysis tool for Java,
C++, Objective-C, and C. Infer is written in [OCaml](https://ocaml.org/).
## Installation
Read our [Getting
Started](http://fbinfer.com/docs/getting-started) page for
details on how to install packaged versions of Infer. To build Infer
from source, see [INSTALL.md](./INSTALL.md).
## Contributing
See [CONTRIBUTING.md](./CONTRIBUTING.md).
## License
Infer is MIT-licensed.
Note: Enabling Java support may require you to download and install
components licensed under the GPL.

@ -0,0 +1,59 @@
#!/bin/bash
# Copyright (c) Facebook, Inc. and its affiliates.
#
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.
set -e
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
# make sure we run from the root of the repo
pushd "$SCRIPT_DIR" > /dev/null
# We need to record the date that the documentation was last modified to put in our man
# pages. Unfortunately that information is only available reliably from `git`, which we don't have
# access to from other distributions of the infer source code. Such source distributions should
# distribute the "configure" script too. The idea is to bake this date inside "configure" so that
# it's available at build time. We do that by generating an m4 macro that hardcodes the date we
# compute in this script for "configure" to find.
MAN_LAST_MODIFIED_M4=m4/__GENERATED__ac_check_infer_man_last_modified.m4
printf 'generating %s' "$MAN_LAST_MODIFIED_M4... "
if test -d '.git' ; then
# date at which the man pages were last modified, to record in the manpages themselves
MAN_FILES=(
infer/src/base/CommandLineOption.ml
infer/src/base/Config.ml
)
MAN_DATE=$(git log -n 1 --pretty=format:%cd --date=short -- "${MAN_FILES[@]}")
INFER_MAN_LAST_MODIFIED=${INFER_MAN_LAST_MODIFIED:-$MAN_DATE}
else
echo 'no git repository detected; setting last modified date to today'
# best effort: get today's date
INFER_MAN_LAST_MODIFIED=${INFER_MAN_LAST_MODIFIED:-$(date +%Y-%m-%d)}
fi
printf "AC_DEFUN([AC_CHECK_INFER_MAN_LAST_MODIFIED],\n" > "$MAN_LAST_MODIFIED_M4"
printf "[INFER_MAN_LAST_MODIFIED=%s\n" "$INFER_MAN_LAST_MODIFIED" >> "$MAN_LAST_MODIFIED_M4"
printf " AC_SUBST([INFER_MAN_LAST_MODIFIED])\n" >> "$MAN_LAST_MODIFIED_M4"
printf "])\n" >> "$MAN_LAST_MODIFIED_M4"
printf 'done\n'
# older versions of `autoreconf` only support including macros via acinclude.m4
ACINCLUDE="acinclude.m4"
printf "generating $ACINCLUDE..."
cat m4/*.m4 > "$ACINCLUDE"
printf " done\n"
printf "generating ./configure script..."
autoreconf -fi
printf " done\n"
echo ""
echo "you may now run the following commands to build Infer:"
echo ""
echo " ./configure"
echo " make"
echo ""
echo 'run `./configure --help` for more options'

@ -0,0 +1,232 @@
#!/usr/bin/env bash
# Convenience script to build Infer when using opam
# Copyright (c) Facebook, Inc. and its affiliates.
#
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.
set -e
set -o pipefail
set -u
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
INFER_ROOT="$SCRIPT_DIR"
DEPENDENCIES_DIR="$INFER_ROOT/facebook/dependencies"
PLATFORM="$(uname)"
SANDCASTLE=${SANDCASTLE:-}
NCPU="$(getconf _NPROCESSORS_ONLN 2>/dev/null || echo 1)"
INFER_OPAM_DEFAULT_SWITCH="4.12.0+flambda"
INFER_OPAM_DEFAULT_SWITCH_OPTIONS="--package=ocaml-variants.4.12.0+options,ocaml-option-flambda"
INFER_OPAM_SWITCH=${INFER_OPAM_SWITCH:-$INFER_OPAM_DEFAULT_SWITCH}
INFER_OPAM_SWITCH_OPTIONS=${INFER_OPAM_SWITCH_OPTIONS:-$INFER_OPAM_DEFAULT_SWITCH_OPTIONS}
PLUGIN_DIR="$INFER_ROOT/facebook-clang-plugins"
PLUGIN_SETUP_SCRIPT=${PLUGIN_SETUP_SCRIPT:-setup.sh}
PLUGIN_SETUP="${PLUGIN_DIR}/clang/${PLUGIN_SETUP_SCRIPT}"
function usage() {
echo "Usage: $0 [-y] [targets]"
echo
echo " targets:"
echo " all build everything (default)"
echo " clang build C and Objective-C analyzer"
echo " erlang build Erlang analyzer"
echo " java build Java analyzer"
echo
echo " options:"
echo " -h,--help show this message"
echo " --no-opam-lock do not use the opam/infer.opam.locked file and let opam resolve dependencies"
echo " --only-setup-opam initialize opam, install the opam dependencies of infer, and exit"
echo " --user-opam-switch use the current opam switch to install infer (default: $INFER_OPAM_DEFAULT_SWITCH)"
echo " -y,--yes automatically agree to everything"
echo
echo " examples:"
echo " $0 # build Java, Erlang and C/Objective-C analyzers"
echo " $0 java erlang clang # equivalent way of doing the above"
echo " $0 java # build only the Java analyzer"
}
# arguments
BUILD_CLANG=${BUILD_CLANG:-no}
BUILD_ERLANG=${BUILD_ERLANG:-no}
BUILD_JAVA=${BUILD_JAVA:-no}
INFER_CONFIGURE_OPTS=${INFER_CONFIGURE_OPTS:-""}
INTERACTIVE=${INTERACTIVE:-yes}
JOBS=${JOBS:-$NCPU}
ONLY_SETUP_OPAM=${ONLY_SETUP_OPAM:-no}
USE_OPAM_LOCK=${USE_OPAM_LOCK:-yes}
USER_OPAM_SWITCH=no
ORIG_ARGS="$*"
function build_all() {
BUILD_CLANG=yes
BUILD_ERLANG=yes
BUILD_JAVA=yes
}
while [[ $# -gt 0 ]]; do
opt_key="$1"
case $opt_key in
all)
build_all
shift
continue
;;
clang)
BUILD_CLANG=yes
shift
continue
;;
erlang)
BUILD_ERLANG=yes
shift
continue
;;
java)
BUILD_JAVA=yes
shift
continue
;;
-h|--help)
usage
exit 0
;;
--no-opam-lock)
USE_OPAM_LOCK=no
shift
continue
;;
--user-opam-switch)
USER_OPAM_SWITCH=yes
shift
continue
;;
--only-setup-opam)
ONLY_SETUP_OPAM=yes
shift
continue
;;
-y|--yes)
INTERACTIVE=no
shift
continue
;;
*)
usage
exit 1
esac
shift
done
if [ "$BUILD_CLANG" == "no" ] && [ "$BUILD_ERLANG" == "no" ] && [ "$BUILD_JAVA" == "no" ]; then
build_all
fi
# enable --yes option for some commands in non-interactive mode
YES=
if [ "$INTERACTIVE" == "no" ]; then
YES=--yes
fi
# --yes by default for opam commands except if we are using the user's opam switch
if [ "$INTERACTIVE" == "no" ] || [ "$USER_OPAM_SWITCH" == "no" ]; then
export OPAMYES=true
fi
setup_opam () {
opam var root 1>/dev/null 2>/dev/null || opam init --reinit --bare --no-setup &&
opam_retry opam_switch_create_if_needed "$INFER_OPAM_SWITCH" "$INFER_OPAM_SWITCH_OPTIONS" &&
opam switch set "$INFER_OPAM_SWITCH"
}
install_opam_deps () {
local locked=
if [ "$USE_OPAM_LOCK" == yes ]; then
locked=.locked
fi
opam install --deps-only "$INFER_ROOT"/opam/infer.opam$locked &&
if [ -n "$SANDCASTLE" ]; then
opam pin list | grep yojson || opam pin add yojson "${DEPENDENCIES_DIR}/yojson-1.7.0fix"
fi
}
echo "initializing opam... " >&2
. "$INFER_ROOT"/scripts/opam_utils.sh
if [ "$USER_OPAM_SWITCH" == "no" ]; then
setup_opam
fi
eval $(SHELL=bash opam env)
echo >&2
echo "installing infer dependencies; this can take up to 30 minutes... " >&2
opam_retry install_opam_deps
if [ "$ONLY_SETUP_OPAM" == "yes" ]; then
exit 0
fi
echo "preparing build... " >&2
./autogen.sh > /dev/null
if [ "$BUILD_CLANG" == "no" ]; then
INFER_CONFIGURE_OPTS+=" --disable-c-analyzers"
fi
if [ "$BUILD_ERLANG" == "no" ]; then
INFER_CONFIGURE_OPTS+=" --disable-erlang-analyzers"
fi
if [ "$BUILD_JAVA" == "no" ]; then
INFER_CONFIGURE_OPTS+=" --disable-java-analyzers"
fi
./configure $INFER_CONFIGURE_OPTS
if [ "$BUILD_CLANG" == "yes" ]; then
if ! "$PLUGIN_SETUP" --only-check-install; then
echo ""
echo " Warning: you are not using a release of Infer. The C and"
echo " Objective-C analyses require a custom clang to be compiled"
echo " now. This step takes ~30-60 minutes, possibly more."
echo ""
echo " To speed this along, you are encouraged to use a release of"
echo " Infer instead:"
echo ""
echo " http://fbinfer.com/docs/getting-started"
echo ""
echo " If you are only interested in analyzing Java programs, simply"
echo " run this script with only the \"java\" argument:"
echo ""
echo " $0 java"
echo ""
confirm="n"
printf "Are you sure you want to compile clang? (y/N) "
if [ "$INTERACTIVE" == "no" ]; then
confirm="y"
echo "$confirm"
else
read confirm
fi
if [ "x$confirm" != "xy" ]; then
exit 0
fi
# only run this script if we are definitely building clang
facebook-clang-plugins/clang/src/prepare_clang_src.sh
fi
fi
make -j "$JOBS" opt || (
echo >&2
echo ' compilation failure; you can try running' >&2
echo >&2
echo ' make clean' >&2
echo " '$0' $ORIG_ARGS" >&2
echo >&2
exit 1)
echo
echo "*** Success! Infer is now built in '$SCRIPT_DIR/infer/bin/'."
echo '*** Install infer on your system with `make install`.'
echo
echo '*** If you plan to hack on infer, check out CONTRIBUTING.md to setup your dev environment.'

@ -0,0 +1,427 @@
dnl Copyright (c) Facebook, Inc. and its affiliates.
dnl
dnl This source code is licensed under the MIT license found in the
dnl LICENSE file in the root directory of this source tree.
dnl autoconf script for Infer
dnl run ./autogen.sh to generate a configure script
AC_PREREQ([2.63])
# WARNING: the version number has to be kept in sync with:
# - the values below
# - opam
AC_INIT([Infer],
[1.1.0],
[https://github.com/facebook/infer/issues/])
AC_CONFIG_SRCDIR([infer/src/istd/IStd.ml])
# WARNING: keep in sync with above
INFER_MAJOR=1
INFER_MINOR=1
INFER_PATCH=0
AC_SUBST([INFER_MAJOR])
AC_SUBST([INFER_MINOR])
AC_SUBST([INFER_PATCH])
# are we in a release source tree
AC_CHECK_FILE([.release], [is_release_tree=yes], [is_release_tree=no])
IS_RELEASE_TREE=$is_release_tree
AC_SUBST([IS_RELEASE_TREE])
# are we in an internal source tree
AC_CHECK_FILE([.facebook], [is_facebook_tree=yes], [is_facebook_tree=no])
IS_FACEBOOK_TREE=$is_facebook_tree
AC_SUBST([IS_FACEBOOK_TREE])
AC_ARG_VAR([PATH], [the shell's $PATH list of directories to search for executables])
# to compile the facebook-clang-plugins
AC_ARG_VAR([CLANG_PREFIX], [directory where clang is installed (defaults=$PWD/facebook-clang-plugins/clang/install)])
AS_IF([test "x$CLANG_PREFIX" = "x"], [
CLANG_PREFIX="$(pwd)/facebook-clang-plugins/clang/install"
])
AC_ARG_VAR([CLANG_INCLUDES], [clang headers directories (defaults=$CLANG_PREFIX/include)])
AS_IF([test "x$CLANG_INCLUDES" = "x"], [
CLANG_INCLUDES="$CLANG_PREFIX/include"
])
BUILD_PLATFORM=unknown
WINDOWS_BUILD=no
AC_MSG_CHECKING([for build platform])
# see https://stackoverflow.com/questions/714100/os-detecting-makefile
# but we do this in the configure for homogeneity
case "${OS}" in
Windows_NT*)
BUILD_PLATFORM=Windows
;;
*)
uname_str=`uname -s`
case "${uname_str}" in
Linux*)
BUILD_PLATFORM=Linux
;;
Darwin*)
BUILD_PLATFORM=Darwin
;;
cygwin*|mingw*)
BUILD_PLATFORM=Windows
;;
*)
AC_MSG_ERROR(["OS $uname_str is not supported"])
;;
esac
esac
AC_MSG_RESULT([$BUILD_PLATFORM])
AC_SUBST([BUILD_PLATFORM])
AC_MSG_CHECKING([for Windows build])
AS_IF([test x"$BUILD_PLATFORM" = x"Windows"], [WINDOWS_BUILD=yes])
AC_MSG_RESULT([$WINDOWS_BUILD])
AC_SUBST([WINDOWS_BUILD])
AC_ARG_ENABLE(c-analyzers,
AS_HELP_STRING([--disable-c-analyzers],
[do not build the C/C++/ObjC analyzers (default is to build them)]),
,
enable_c_analyzers=yes)
BUILD_C_ANALYZERS=$enable_c_analyzers
AC_SUBST([BUILD_C_ANALYZERS])
AC_ARG_ENABLE(erlang-analyzers,
AS_HELP_STRING([--disable-erlang-analyzers],
[do not build the Erlang analyzers (default is to build them)]),
,
enable_erlang_analyzers=yes)
BUILD_ERLANG_ANALYZERS=$enable_erlang_analyzers
AC_SUBST([BUILD_ERLANG_ANALYZERS])
AC_ARG_ENABLE(java-analyzers,
AS_HELP_STRING([--disable-java-analyzers],
[do not build the Java analyzers (default is to build them)]),
,
enable_java_analyzers=yes)
BUILD_JAVA_ANALYZERS=$enable_java_analyzers
AC_SUBST([BUILD_JAVA_ANALYZERS])
AC_ARG_WITH(fcp-clang,
AS_HELP_STRING([--with-fcp-clang],
[use $CLANG_PREFIX/bin/clang to override the default compiler (default is not to override)]),
,
with_fcp_clang=no)
AS_IF([test "x$enable_c_analyzers" = "xyes"], [
AC_MSG_CHECKING([whether to use the compilers in $CLANG_PREFIX/bin])
case "$with_fcp_clang" in
no)
AC_MSG_RESULT([no])
;;
yes)
CC=$CLANG_PREFIX/bin/clang
CXX=$CLANG_PREFIX/bin/clang++
OBJC=$CLANG_PREFIX/bin/clang
AC_MSG_RESULT([yes])
;;
*)
AC_MSG_ERROR([invalid value for --without-fcp-clang; use "yes" or "no"])
;;
esac
AC_CHECK_TOOL([SHASUM], [shasum], [no])
AC_ASSERT_PROG([shasum], [$SHASUM])
# cmake is required to build llvm+clang
AC_CHECK_TOOL([CMAKE], [cmake], [no])
AC_ASSERT_PROG([cmake], [$CMAKE])
AC_ARG_ENABLE(ocamlopt-custom-cc,
AS_HELP_STRING([--enable-ocamlopt-custom-cc], [use CC in ocamlopt invocations]),
,
enable_ocamlopt_custom_cc=no)
ENABLE_OCAMLOPT_CUSTOM_CC=$enable_ocamlopt_custom_cc
AC_SUBST([ENABLE_OCAMLOPT_CUSTOM_CC])
])
# end if($enable_c_analyzers)
AC_CHECK_TOOL([XCODE_SELECT], [xcode-select], [no])
AS_IF([test "x$XCODE_SELECT" != "xno"], [XCODE_SELECT_OUT=`xcode-select -p`])
AC_ARG_VAR([XCODE_BASE], [Install location of xcode])
AS_IF(
[test "x$XCODE_BASE" != "x"],
[AC_CHECK_FILE($XCODE_BASE,[HAS_OBJC=yes],[HAS_OBJC=no])],
[test "x$XCODE_SELECT" != "xno"],
[XCODE_BASE=$XCODE_SELECT_OUT HAS_OBJC=yes],
[HAS_OBJC=no])
AC_CHECK_TOOL([XCRUN], [xcrun], [no])
AC_ARG_VAR([SDKROOT], [path to the OSX platform SDK used by clang])
AS_IF(
[test "x$SDKROOT" = "x" && test "x$XCRUN" != "xno"],
[SDKROOT=`xcrun --sdk macosx --show-sdk-path`]
)
AC_SUBST([XCODE_BASE])
AC_SUBST([HAS_OBJC])
AC_SUBST([SDKROOT])
# prefer clang over gcc because the plugins makes use of
# clang-specific #pragma's
AC_PROG_CC(clang gcc)
AC_PROG_AWK
AC_PROG_INSTALL
AC_PROG_LN_S
AC_PROG_MAKE_SET
AC_PROG_MKDIR_P
if test "x$enable_c_analyzers" = "xyes"; then
AC_PROG_CPP
AC_PROG_CXX(clang++ g++)
# AC_PROG_CXX doesn't set CXX to "no" in case of failure (I have no words...); from the manual:
# "If none of those checks succeed, then as a last resort set CXX to g++. "
AS_IF([$CXX --version > /dev/null], [], [AC_MSG_ERROR([no C++ compiler found])])
dnl clang wants either clang version >= 3.1 or gcc version >= 4.7.2 to
dnl compile itself
AC_MSG_CHECKING([if the C/C++ compiler is recent enough])
AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
#ifdef __clang__
#if __clang_major__ < 3 || (__clang_major__ == 3 && __clang_minor__ < 1)
#error compiler is too old
#endif // version check
#elif defined __GNUC__ // __clang__
#if __GNUC__ < 4 || (__GNUC__ == 4 && (__GNUC_MINOR__ < 7 || (__GNUC_MINOR__ == 7 && __GNUC_PATCHLEVEL__ < 2)))
#error compiler is too old
#endif // version check
#endif // __GNUC__
]])],
[AC_MSG_RESULT([yes])],
[dnl
AC_MSG_RESULT([no])
AC_MSG_ERROR([
Your C/C++ compiler seems to be too old to build clang, which is
required by the facebook-clang-plugins. Please install either
gcc version >= 4.7.2 or clang version >= 3.1.
See the output of `./configure --help` to force the use of a different
C compiler.
Alternatively, you can checkout a binary release of infer:
https://github.com/facebook/infer/releases/])
]
)
AC_CHECK_HEADERS([fcntl.h inttypes.h limits.h locale.h malloc.h stddef.h stdint.h stdlib.h string.h sys/mount.h sys/param.h sys/socket.h sys/statfs.h sys/time.h unistd.h wchar.h wctype.h])
fi
# end if($enable_c_analyzers)
# OCaml dependencies
AC_PROG_OCAML
AC_ASSERT_PROG([ocamlc], [$OCAMLC])
# check the version of OCaml
AC_ASSERT_OCAML_MIN_VERSION([4.06.1])
AC_ASSERT_PROG([ocamlopt], [$OCAMLOPT])
AC_CHECK_TOOL([OCAMLBUILD], [ocamlbuild], [no])
AC_ASSERT_PROG([ocamlbuild], [$OCAMLBUILD])
AC_PROG_FINDLIB
AC_PROG_OCAMLLEX
AC_ASSERT_PROG([ocamllex], [$OCAMLLEX])
AC_CHECK_TOOL([MENHIR], [menhir], [no])
AC_ASSERT_PROG([menhir], [$MENHIR])
AC_ASSERT_OCAML_PKG([atdgen])
AC_ASSERT_OCAML_PKG([biniou])
AC_ASSERT_OCAML_PKG([camlzip], [zip])
AC_ASSERT_OCAML_PKG([easy-format])
AC_ASSERT_OCAML_PKG([oUnit])
AC_CHECK_TOOL([UTOP], [utop], [no])
AC_ASSERT_OCAML_PKG([yojson])
AC_MSG_CHECKING([which ocamlformat to use])
AS_IF([test x"$is_facebook_tree" = x"yes"],
[OCAMLFORMAT="$(pwd)"/facebook/dependencies/bin/ocamlformat],
[OCAMLFORMAT=ocamlformat])
AC_MSG_RESULT([$OCAMLFORMAT])
AC_SUBST([OCAMLFORMAT])
AC_ARG_VAR([CPATH], [Additional directories to search for C headers.])
AC_ARG_VAR([LIBRARY_PATH], [Additional directories to search for C shared objects.])
AC_ARG_VAR([CAML_LD_LIBRARY_PATH],
[Additional directories to search for dynamically-loaded libraries.])
AC_ARG_VAR([OPAMROOT], [Root of the local opam installation.])
AC_ARG_VAR([OPAMSWITCH], [Opam switch used for building infer.])
AC_CHECK_TOOL([OPAM], [opam], [no])
AS_IF([test "$OPAM" != "no"], [
AC_MSG_CHECKING([opam version])
opam_version=$(opam --version)
case $opam_version in
2.*) AC_MSG_RESULT([$opam_version]); break;;
*) AC_MSG_ERROR([opam version $opam_version is not supported, please install opam version 2 instead]); break;;
esac
AC_MSG_CHECKING([current opam root])
OPAMROOT=$("$OPAM" config var root)
AC_MSG_RESULT([$OPAMROOT])
AC_MSG_CHECKING([current opam switch])
OPAMSWITCH=$("$OPAM" switch show)
AC_MSG_RESULT([$OPAMSWITCH])
], [
OPAMROOT=no
OPAMSWITCH=no
])
AC_SUBST([OPAMROOT])
AC_SUBST([OPAMSWITCH])
if test "x$enable_erlang_analyzers" = "xyes"; then
AC_CHECK_TOOL([ESCRIPT], [escript], [no])
AC_CHECK_TOOL([REBAR3], [rebar3], [no])
fi
# end if($enable_erlang_analyzers)
if test "x$enable_java_analyzers" = "xyes"; then
AC_CHECK_TOOL([JAVA], [java], [no])
AC_CHECK_TOOL([JAVAC], [javac], [no])
AC_ASSERT_PROG([javac], [$JAVAC])
AC_ASSERT_PROG([java], [$JAVA])
AC_ASSERT_OCAML_PKG([javalib])
AC_ASSERT_OCAML_PKG([sawja])
AC_MSG_CHECKING([for Java major version])
JAVA_MAJOR_VERSION=`"$JAVAC" -version 2>&1 | head -n 1 | cut -d ' ' -f 2`
AS_IF([test "x`echo $JAVA_MAJOR_VERSION | cut -d '.' -f 1`" = "x1"], [
# version 1.8.xx -> 8
JAVA_MAJOR_VERSION=`echo $JAVA_MAJOR_VERSION | cut -d '.' -f 2`
], [
# otherwise pick the first number as the major version
JAVA_MAJOR_VERSION=`echo $JAVA_MAJOR_VERSION | cut -d '.' -f 1`
])
AC_MSG_RESULT([$JAVA_MAJOR_VERSION])
AC_SUBST([JAVA_MAJOR_VERSION])
AC_MSG_CHECKING([for JAVA_HOME])
cat - <<_ACEOF >conftest.java
public class conftest {
public static void main(String[[]] args) {
System.out.println(System.getProperty("java.home"));
System.exit(0);
}
}
_ACEOF
rm -f conftest.class
if "$JAVAC" conftest.java; then
rm -f conftest.java
_USER_JAVA_HOME=$($JAVA -cp . conftest)
if rm -f conftest.class; then
[javac_version_10_or_more=`echo "$JAVA_MAJOR_VERSION" | grep -q -e '^1[0-9]' && echo yes`]
if test "x$javac_version_10_or_more" = "xyes"; then
USER_JAVA_HOME=$_USER_JAVA_HOME
else
USER_JAVA_HOME=$_USER_JAVA_HOME/..
fi
else
AC_MSG_ERROR([Could not run test program with $JAVA])
fi
else
rm -f conftest.java
AC_MSG_ERROR([Could not compile test program with $JAVAC])
fi
AC_MSG_RESULT([$USER_JAVA_HOME])
AC_SUBST([USER_JAVA_HOME])
AC_CHECK_LIB([z], [inflateEnd], [ZLIB_FOUND=yes], [ZLIB_FOUND=no])
AS_IF([test x"$ZLIB_FOUND" = xno], [AC_MSG_ERROR([zlib not found.])])
fi
# end if($enable_java_analyzers)
AC_CHECK_TOOL([ATDGEN], [atdgen], [no])
AC_ASSERT_PROG([atdgen], [$ATDGEN])
AC_ARG_ENABLE(ocaml-bin-annot,
AS_HELP_STRING([--disable-ocaml-bin-annot], [do not build ocaml .cmt files]),
,
enable_ocaml_bin_annot=yes)
ENABLE_OCAML_BINANNOT=$enable_ocaml_bin_annot
AC_SUBST([ENABLE_OCAML_BINANNOT])
# We use Buck to run the Infer tests
AS_IF([test x"$is_facebook_tree" = x"yes"],
AC_MSG_CHECKING([which .buckjavaversion to use])
cp "facebook/dependencies/dotbuckjavaversion" ".buckjavaversion"
AC_MSG_RESULT([facebook/dependencies/dotbuckjavaversion])
AC_MSG_CHECKING([which .buck-java11 to use])
cp "facebook/dependencies/dotbuck-java11" ".buck-java11"
AC_MSG_RESULT([facebook/dependencies/dotbuck-java11]))
AC_CHECK_TOOL([GETCONF], [getconf], [no])
AC_MSG_CHECKING([the number of cpus the build host has])
if test "$GETCONF" != "no"; then
if test $("$GETCONF" _NPROCESSORS_ONLN); then
NCPU=$("$GETCONF" _NPROCESSORS_ONLN)
AC_MSG_RESULT([$NCPU])
fi
else
NCPU=1
AC_MSG_RESULT([failed, defaulting to 1])
fi
AC_SUBST([NCPU])
# optional progs and libraries that, eg build systems to be run in integration tests
AC_CHECK_TOOL([ANT], [ant], [no])
AC_CHECK_TOOL([BUCK], [buck], [no])
AC_CHECK_TOOL([EMACS], [emacs], [no])
AC_ARG_VAR([MVN], [command to execute Maven when running tests])
AS_IF([test "x$MVN" = "x"], [
AC_CHECK_TOOL([MVN], [mvn], [no])
], [
AC_MSG_RESULT([checking for mvn... $MVN])
])
AC_CHECK_TOOL([NDKBUILD], [ndk-build], [no])
if test x"$NDKBUILD" = x"no"; then
# ndk-build not in $PATH, look into potential android NDK install paths and record the absolute path
# to ndk-build
AC_PATH_PROG([NDKBUILD], [ndk-build], [no],
[$PATH$PATH_SEPARATOR$ANDROID_NDK$PATH_SEPARATOR/opt/android_ndk/r15c])
fi
AC_CHECK_TOOL([NINJA], [ninja], [no])
AC_CHECK_TOOL([XCPRETTY], [xcpretty], [no])
AC_CHECK_TOOL([SED], [sed], [no])
AS_IF([test "$SED" != "xno"], [
AC_MSG_CHECKING([if sed is GNU sed])
AS_IF(["$SED" --version 2> /dev/null | grep -q -e "GNU sed"], [
GNU_SED="$SED"
AC_MSG_RESULT([yes])
], [
AC_MSG_RESULT([no])
AC_CHECK_TOOL([GNU_SED], [gsed], [no])
])
])
AC_SUBST([GNU_SED])
AC_CHECK_TOOL([BREW], [brew], [no])
AC_CHECK_TOOL([INSTALL_NAME_TOOL], [install_name_tool], [no])
AC_SUBST([INSTALL_NAME_TOOL])
AC_CHECK_TOOL([LDD], [ldd], [no])
AC_SUBST([LDD])
AC_CHECK_TOOL([OTOOL], [otool], [no])
AC_SUBST([OTOOL])
AC_CHECK_TOOL([PATCHELF], [patchelf], [no])
AC_SUBST([PATCHELF])
AC_CHECK_INFER_MAN_LAST_MODIFIED()
AC_CONFIG_FILES([
Makefile.autoconf
])
AC_OUTPUT

@ -0,0 +1,17 @@
java_library(
name = 'java_libraries',
deps=[
'//dependencies/java/guava:guava',
'//dependencies/java/junit:hamcrest',
'//dependencies/java/jackson:jackson',
'//dependencies/java/jsr-305:jsr-305',
'//dependencies/java/junit:junit',
'//dependencies/java/opencsv:opencsv'
],
visibility = [
'PUBLIC'
]
)
project_config(
src_target = ':java_libraries',
)

@ -0,0 +1,7 @@
prebuilt_jar(
name = 'android-support-v4',
binary_jar = 'android-support-v4.jar',
visibility = [
'PUBLIC',
],
)

@ -0,0 +1,7 @@
prebuilt_jar(
name = 'guava',
binary_jar = 'guava-23.0.jar',
visibility = [
'PUBLIC'
]
)

Binary file not shown.

@ -0,0 +1,10 @@
prebuilt_jar(
name = 'jackson',
binary_jar = 'jackson-2.2.3.jar',
deps = [
'//dependencies/java/guava:guava',
],
visibility = [
'PUBLIC',
]
)

Binary file not shown.

@ -0,0 +1,8 @@
prebuilt_jar(
name = 'jsr-305',
binary_jar = 'jsr305.jar',
source_jar = 'jsr305-src.jar',
visibility = [
'PUBLIC',
],
)

Binary file not shown.

Binary file not shown.

@ -0,0 +1,7 @@
prebuilt_jar(
name = 'jsr-330',
binary_jar = 'javax.inject.jar',
visibility = [
'PUBLIC',
],
)

Binary file not shown.

@ -0,0 +1,7 @@
prebuilt_jar(
name = 'sun-tools',
binary_jar = 'tools.jar',
visibility = [
'PUBLIC'
]
)

Binary file not shown.

@ -0,0 +1,2 @@
Ocamldot was written by Trevor Jim. It is in the public domain; use
it however you like, at your own risk.

@ -0,0 +1,28 @@
# Copyright (c) Facebook, Inc. and its affiliates.
#
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.
# Try to automatically guess whether we are running under Windows.
# Set WIN32=true manually if this doesn't work.
#
ifeq (${OSTYPE},cygwin32) # Cygwin Beta 19
WIN32=true
else
ifeq (${OSTYPE},cygwin) # Cygwin Beta 20
WIN32=true
endif
endif
ifdef WIN32
EXE=.exe
else # UNIX
EXE=
endif
ocamldot$(EXE): ocamldot.mll
ocamllex ocamldot.mll
ocamlc -o $@ ocamldot.ml
clean:
$(RM) ocamldot$(EXE) ocamldot.ml *.cmi *.cmo *.o *.obj

@ -0,0 +1,34 @@
Ocamldot generates program dependency graphs for ocaml programs.
The dependency graph output by ocamldot can be rendered by a separate
program, dot. Dot is freely available from
http://www.research.att.com/sw/tools/graphviz/
Ocamldot is designed to process the output of ocamldep. A typical use
would be
ocamldep *.ml | ocamldot > dep.dot
or
ocamldep *.ml > .depend
ocamldot .depend > dep.dot
This will output a dot graph into the file dep.dot. You can then use
the program dotty to view, edit, and print the graph.
Ocamldot has the following options:
-fullgraph draw the full graph (default is to draw only the kernel)
-landscape output in landscape format (default is portrait)
-lr draw graph from left to right (default is top to bottom)
-r <r> use <r> as a root in the graph; nodes reachable from <r>
will be shown
(The transitive kernel of a dag is the smallest subset of the dag
whose transitive closure is the same as the transitive closure of the
dag. For example, the kernel of A->B, A->C, B->C is just the two
edges A->B, B->C.)
-Trevor Jim

@ -0,0 +1,52 @@
.TH OCAMLDOT 1
.SH NAME
ocamldot \- generate dependency graphs of ocaml programs
.SH SYNOPSIS
.B ocamldot
.I
.RI "[options] <dependency-file>"
.SH "DESCRIPTION"
This manual page documents briefly the
.BR ocamldot
command.
.PP
.B ocamldot
generates program dependency graphs for ocaml programs. The
dependency graph output by ocamldot can be rendered by a separate
program, \fIdot\fR.
.P
Ocamldot is designed to process the output of ocamldep. A typical use would be
.P
ocamldep *.ml | ocamldot > dep.dot
.P
or
.P
ocamldep *.ml > .depend
.br
ocamldot .depend > dep.dot
.SH OPTIONS
.TP
.B \-fullgraph
Draw the full graph (default is to draw only the kernel)
.TP
.B \-landscape
Output in landscape format (default is portrait)
.TP
.B \-lr
Draw graph from left to right (default is top to bottom)
.TP
.B \-r <r>
Use \fI<r>\fR as a root in the graph; nodes reachable from \fI<r>\fR
will be shown.
.P
The transitive kernel of a dag is the smallest subset of the dag whose transitive closure is the same as the transitive closure of the dag.
For example, the kernel of A->B, A->C, B->C is just the two edges A->B, B->C.
.SH SEE ALSO
.BR ocamldep (1),
.BR dot(1)
.P
\fIhttp://www.research.att.com/~trevor/ocamldot\fR.
.SH AUTHOR
Trevor Jim <trevor@research.att.com>

@ -0,0 +1,436 @@
(* ocamldot.mll, July 1999, Trevor Jim *)
{
module StringSet =
Set.Make(struct type t = string let compare = compare end)
module StringMap =
Map.Make(struct type t = string let compare = compare end)
let dependencies = ref []
let currentSource = ref ""
let addDepend t =
let s = !currentSource in
if s<>t
then dependencies := (s,t)::(!dependencies)
}
rule processSource = parse
['.' '-' '/' 'A'-'Z' 'a'-'z' '_' '\192'-'\214' '\216'-'\246'
'\248'-'\255' '\'' '0'-'9' ]+ '.' ['A'-'Z' 'a'-'z']+
[' ' '\009']* ':'
{ let s = Lexing.lexeme lexbuf in
let i = String.rindex s '.' in
let s = String.sub s 0 i in
let s = Filename.basename s in
let s = String.capitalize s in
currentSource := s;
processTargets lexbuf }
| eof
{ () }
| _
{ processSource lexbuf }
and processTargets = parse
[' ' '\009']+
{ processTargets lexbuf }
| '\\' [' ' '\009']* ['\010' '\013']+ [' ' '\009']+
{ processTargets lexbuf }
| ['.' '/' 'A'-'Z' 'a'-'z' '_' '\192'-'\214' '\216'-'\246'
'\248'-'\255' '\'' '0'-'9' ]+ '.' ['A'-'Z' 'a'-'z']+
{ let t = Lexing.lexeme lexbuf in
let i = String.rindex t '.' in
let t = String.sub t 0 i in
let t = Filename.basename t in
let t = String.capitalize t in
addDepend t;
processTargets lexbuf }
| eof
{ () }
| _
{ processSource lexbuf }
{
(********************************)
(* Utility functions for graphs *)
(********************************)
(**********************************************************************)
(* A graph is represented by a (string * StringSet) list, *)
(* that is, a list of (source,targets) pairs. *)
(**********************************************************************)
let emptyGraph = []
(**********************************************************************)
(* divideGraph graph source = (sourceTargets, graphWithoutSource) *)
(* *)
(* Return the targets of a source in a graph and the graph with the *)
(* source substracted from the sources. GraphWithoutSources may *)
(* still contain source as a target. *)
(**********************************************************************)
let divideGraph graph source =
let rec aux l =
match l with
[] -> (StringSet.empty,[])
| (s,ts)::tl ->
if s=source then (ts,tl)
else
let (sourceTargets,tlWithoutSource) = aux tl in
(sourceTargets,(s,ts)::tlWithoutSource) in
aux graph
(*********************************************)
(* Add the edge (source,target) to the graph *)
(*********************************************)
let addEdge graph source target =
let (sourceTargets,graphWithoutSource) = divideGraph graph source in
(source,StringSet.add target sourceTargets)::graphWithoutSource
(************************************************************)
(* Add the edges { (source,t) | t in targets } to the graph *)
(************************************************************)
let addEdges graph source targets =
let (sourceTargets,graphWithoutSource) = divideGraph graph source in
(source,StringSet.union targets sourceTargets)::graphWithoutSource
(**************************************************)
(* Remove the edge (source,target) from the graph *)
(**************************************************)
let removeEdge graph source target =
let rec loop l =
match l with
[] -> []
| (s,ts)::tl ->
if s=source
then (s,StringSet.remove target ts)::tl
else (s,ts)::(loop tl)
in loop graph
(*****************************************************************)
(* Remove the edges { (source,t) | t in targets } from the graph *)
(*****************************************************************)
let removeEdges graph source targets =
let rec loop l =
match l with
[] -> []
| (s,ts)::tl ->
if s=source
then (s,StringSet.diff ts targets)::tl
else (s,ts)::(loop tl)
in loop graph
(**********************************************************************)
(* Convert between an edge-list representation of graphs and our *)
(* representation. *)
(**********************************************************************)
let edgesOfGraph graph =
List.concat
(List.map
(fun (s,ts) ->
List.map (fun t -> (s,t)) (StringSet.elements ts))
graph)
let graphOfEdges edges =
List.fold_left
(fun g (s,t) -> addEdge g s t)
emptyGraph
edges
(****************************)
(* Is an edge in the graph? *)
(****************************)
let isEdge graph source target =
try
let sourceTargets = List.assoc source graph in
StringSet.mem target sourceTargets
with Not_found -> false
(*****************)
(* Print a graph *)
(*****************)
let printGraph graph =
let printEdges(source,targets) =
StringSet.iter
(fun t -> Printf.printf " \"%s\" -> \"%s\" ;\n" source t)
targets in
List.iter printEdges graph
(********************************)
(* Targets of a node in a graph *)
(********************************)
let targetsOf graph node = (* A set of nodes *)
try List.assoc node graph
with Not_found -> StringSet.empty
(*****************************************)
(* Sources that target a node in a graph *)
(*****************************************)
let sourcesOf graph node = (* A list of nodes *)
let rec aux l =
match l with
[] -> []
| (s,ts)::tl ->
if StringSet.mem node ts then s::(aux tl)
else aux tl in
aux graph
(******************************************************************)
(* Add an edge to a transitively closed graph, and return the new *)
(* transitive closure. *)
(******************************************************************)
let addEdgeTc graph source target =
let targetTargets = targetsOf graph target in
let (sourceTargets,graphWithoutSource) = divideGraph graph source in
let sourceSources = sourcesOf graphWithoutSource source in
let newSourceTargets =
StringSet.add target
(StringSet.union sourceTargets targetTargets) in
(source,newSourceTargets)::
(List.fold_right
(fun s g -> addEdges g s newSourceTargets)
sourceSources
graphWithoutSource)
(**********************************************************)
(* Compute the transitive closure of a graph from scratch *)
(**********************************************************)
let tc graph =
let loop graph (source,targets) =
let reachableFromSource =
List.fold_left
(fun r (s,ts) ->
if StringSet.mem s r then StringSet.union r ts
else r)
targets
graph in
(source,reachableFromSource)::
(List.map
(fun (s,ts) ->
if StringSet.mem source ts
then (s,StringSet.union ts reachableFromSource)
else (s,ts))
graph) in
List.fold_left loop [] graph
(************************************************************************)
(* The transitive kernel (tk) of a dag is a subset of the dag whose *)
(* transitive closure is the same as the transitive closure of the dag. *)
(* *)
(* IF THE GRAPH IS NOT A DAG, THIS CODE WON'T WORK PROPERLY!!! *)
(************************************************************************)
(************************************************************************)
(* Add an edge to a kernel dag and return the new kernel and transitive *)
(* closure of the new kernel. Requires the transitive closure of the *)
(* old kernel. *)
(************************************************************************)
let addEdgeTk kernel tcKernel source target =
if isEdge tcKernel source target
then (kernel,tcKernel)
else if source=target
then (addEdge kernel source target,tcKernel)
else
begin
let (sourceTargets,kernelWithoutSource) = divideGraph kernel source in
let targetTargets = StringSet.add target (targetsOf tcKernel target) in
let sourceSources = sourcesOf tcKernel source in
let kernelWithoutSource =
List.fold_left
(fun kws s -> removeEdges kws s targetTargets)
kernelWithoutSource
sourceSources in
((source,
StringSet.add target
(StringSet.diff sourceTargets targetTargets))
::kernelWithoutSource,
addEdgeTc tcKernel source target)
end
(**********************************)
(* The transitive kernel of a dag *)
(**********************************)
let tk dag =
let edges = edgesOfGraph dag in
let (kernel,tcKernel) =
List.fold_left
(fun (k,tck) (s,t) -> addEdgeTk k tck s t)
(emptyGraph,emptyGraph)
edges in
kernel
(**************************)
(* Print the dependencies *)
(**************************)
let doKernel = ref true
let printDepend graph =
if (!doKernel) then printGraph (tk graph)
else printGraph graph
let calledOnFile = ref false
let getDependFromFile file =
calledOnFile := true;
try
let ic = open_in file in
let lexbuf = Lexing.from_channel ic in
processSource lexbuf;
close_in ic
with Sys_error msg -> ()
| Exit -> ()
let getDependFromStdin () =
try
let lexbuf = Lexing.from_channel stdin in
processSource lexbuf
with Sys_error msg -> ()
| Exit -> ()
(**********************************)
(* Color and Cluster by directory *)
(**********************************)
let fold_dir f init path =
let collect cur_dir path (acum, dirs) =
let full_path = Filename.concat cur_dir path in
try
if Sys.is_directory full_path then
(acum, full_path :: dirs)
else
(f acum full_path, dirs)
with Sys_error _ ->
(acum, dirs) in
let rec fold_dir_ (acum, dirs) =
match dirs with
| [] ->
acum
| dir :: dirs ->
fold_dir_ (Array.fold_left (fun ad p -> collect dir p ad) (acum, dirs) (Sys.readdir dir)) in
if Sys.is_directory path then
fold_dir_ (init, [path])
else
f init path
let dir_to_mod_names graph dir =
let nodes =
List.fold_left (fun nodes (source, targets) ->
StringSet.add source (StringSet.union targets nodes)
) StringSet.empty graph in
fold_dir (fun dir_to_mod_names path ->
let file = Filename.basename path in
let mod_name = String.capitalize (try Filename.chop_extension file with _ -> file) in
if ((Filename.check_suffix file ".ml")
&& StringSet.mem mod_name nodes)
then
let dir = Filename.dirname path in
let files = mod_name :: (try StringMap.find dir dir_to_mod_names with Not_found -> []) in
StringMap.add dir files dir_to_mod_names
else
dir_to_mod_names
) StringMap.empty dir
let printColors dir_to_mod_names =
let num_dirs = StringMap.cardinal dir_to_mod_names in
let hsv i s v = Printf.sprintf "\"%f %f %f\"" ((float)i *. (1. /. (float)num_dirs)) s v in
StringMap.fold (fun dir mod_names i ->
List.iter (fun mod_name ->
Printf.printf "\"%s\" [style = filled, fillcolor = %s] ;\n" mod_name (hsv i 0.5 0.9) ;
) mod_names ;
i + 1
) dir_to_mod_names 0
|> ignore
let printClusters clusterDirs dir_to_mod_names =
StringMap.iter (fun dir mod_names ->
let base = Filename.basename dir in
if StringSet.mem base clusterDirs then (
Printf.printf "subgraph cluster_%s { label=\"%s\" ;\n" base base;
List.iter (fun mod_name ->
Printf.printf "\"%s\" ;\n" mod_name
) mod_names ;
Printf.printf "}\n"
)
) dir_to_mod_names
let colorAndCluster clusterDirs graph dir =
let dir_to_mod_names = dir_to_mod_names graph dir in
printColors dir_to_mod_names ;
printClusters clusterDirs dir_to_mod_names
(***************)
(* Entry point *)
(***************)
let usage = "Usage: ocamldot [options] <files>"
let clusters = ref []
let leftToRight = ref false
let landscape = ref false
let roots = ref []
;;
Arg.parse (Arg.align
[
("-c",
Arg.String(fun s -> clusters := s::!clusters),
"<c> cluster the modules in the <c> directory in the graph");
("-fullgraph",
Arg.Clear doKernel,
" draw the full graph (default is to draw only the kernel)");
("-landscape",
Arg.Set landscape,
" output in landscape format (default is portrait)");
("-lr",
Arg.Set leftToRight,
" draw graph from left to right (default is top to bottom)");
("-r",
Arg.String(fun s -> roots := s::!roots),
"<r> use <r> as a root in the graph; nodes reachable from <r> will be shown")
])
getDependFromFile usage;
if not(!calledOnFile) then getDependFromStdin();
print_string "digraph G {\n";
if !landscape
then print_string " size=\"10,7.5\" ;\n rotate=90 ;\n"
else print_string " size=\"7.5,10\" ;\n";
if (!leftToRight) then print_string " rankdir = LR ;\n"
else print_string " rankdir = TB ;\n";
let graph = graphOfEdges(!dependencies) in
begin
match !roots with
[] -> printDepend graph
| roots ->
(* Set up the graph so that the roots are printed at the same level *)
print_string " { rank=same ;\n";
List.iter
(fun r ->
print_string " ";
print_string r;
print_string " ;\n")
roots;
print_string " };\n";
(* Find the graph reachable from the roots *)
let tcGraph = tc graph in
let reachable node =
(List.exists (fun r -> r=node) roots)
||
(List.exists (fun r -> isEdge tcGraph r node) roots) in
let reachableFromRoots =
List.concat
(List.map
(fun (source,targets) ->
if reachable source
then [(source,targets)]
else [])
graph) in
printDepend reachableFromRoots;
let clusterDirs = List.fold_left (fun z s -> StringSet.add s z) StringSet.empty !clusters in
colorAndCluster clusterDirs reachableFromRoots (Sys.getcwd ())
end;
print_string "}\n";
exit 0
;;
}

@ -0,0 +1,27 @@
FROM debian:bullseye-slim
LABEL maintainer "Infer team"
# mkdir the man/man1 directory due to Debian bug #863199
RUN apt-get update && \
mkdir -p /usr/share/man/man1 && \
apt-get install --yes --no-install-recommends \
curl \
libc6-dev \
openjdk-11-jdk-headless \
sqlite3 \
xz-utils \
zlib1g-dev && \
rm -rf /var/lib/apt/lists/*
# Download the Infer release
RUN INFER_VERSION=v1.1.0; \
cd /opt && \
curl -sL \
https://github.com/facebook/infer/releases/download/${INFER_VERSION}/infer-linux64-${INFER_VERSION}.tar.xz | \
tar xJ && \
rm -f /infer && \
ln -s ${PWD}/infer-linux64-$INFER_VERSION /infer
# Install infer
ENV PATH /infer/bin:${PATH}

@ -0,0 +1,37 @@
# docker images for Infer
This directory, `docker/` inside the Infer repo,
contains a docker file to install Infer within a
[docker](https://www.docker.com/) container. This can be used to
quickly try Infer or to deploy Infer.
## Pre-requisites
To use this docker image, you will need a working docker
installation. See the instructions for
[Linux](http://docs.docker.com/linux/step_one/) or
[MacOSX](http://docs.docker.com/mac/step_one/) as appropriate.
## How to use
This docker file will use the latest
[released](https://github.com/facebook/infer/releases) version of
Infer.
1. Get docker running, e.g. using Docker Quickstart Terminal.
2. go to the version of your choice, e.g. `cd docker/1.1.0/`
3. Build or install Infer in the Docker container and try on an example:
```sh
cd docker/1.1.0/
docker build -t infer .
# mount the local examples directory inside the image
# you can mount your project directory here instead
docker run -it infer -v $PWD/../../examples:/infer-examples /bin/bash
# you should now be inside the docker container with a shell prompt, e.g.
# "root@5c3b9af90d59:/# "
cd /infer-examples/
infer -- clang -c hello.c
```

@ -0,0 +1,69 @@
FROM debian:bullseye-slim AS compilator
LABEL maintainer "Infer team"
# mkdir the man/man1 directory due to Debian bug #863199
RUN apt-get update && \
mkdir -p /usr/share/man/man1 && \
apt-get install --yes --no-install-recommends \
autoconf \
automake \
bzip2 \
cmake \
curl \
g++ \
gcc \
git \
libc6-dev \
libgmp-dev \
libmpfr-dev \
libsqlite3-dev \
make \
opam \
openjdk-11-jdk-headless \
patch \
patchelf \
pkg-config \
python3 \
python3-distutils \
unzip \
xz-utils \
zlib1g-dev && \
rm -rf /var/lib/apt/lists/*
# Disable sandboxing
# Without this opam fails to compile OCaml for some reason. We don't need sandboxing inside a Docker container anyway.
RUN opam init --reinit --bare --disable-sandboxing --yes --auto-setup
# Download the latest Infer master
RUN cd / && \
git clone --depth 1 https://github.com/facebook/infer/
# Build opam deps first, then infer. This way if any step fails we
# don't lose the significant amount of work done in the previous
# steps.
RUN cd /infer && ./build-infer.sh java --only-setup-opam
RUN cd /infer && ./build-infer.sh java
# Generate a release
RUN cd /infer && \
make install-with-libs \
BUILD_MODE=opt \
PATCHELF=patchelf \
DESTDIR="/infer-release" \
libdir_relative_to_bindir="../lib"
FROM debian:buster-slim AS executor
RUN apt-get update && apt-get install --yes --no-install-recommends sqlite3
# Get the infer release
COPY --from=compilator /infer-release/usr/local /infer
# Install infer
ENV PATH /infer/bin:${PATH}
# if called with /infer-host mounted then copy infer there
RUN if test -d /infer-host; then \
cp -av /infer/. /infer-host; \
fi

@ -0,0 +1,74 @@
FROM debian:bullseye-slim AS compilator
LABEL maintainer "Infer team"
# mkdir the man/man1 directory due to Debian bug #863199
RUN apt-get update && \
mkdir -p /usr/share/man/man1 && \
apt-get install --yes --no-install-recommends \
autoconf \
automake \
bubblewrap \
bzip2 \
cmake \
curl \
g++ \
gcc \
git \
libc6-dev \
libgmp-dev \
libmpfr-dev \
libsqlite3-dev \
make \
opam \
openjdk-11-jdk-headless \
patch \
patchelf \
pkg-config \
python3 \
python3-distutils \
unzip \
xz-utils \
zlib1g-dev && \
rm -rf /var/lib/apt/lists/*
# Disable sandboxing
# Without this opam fails to compile OCaml for some reason. We don't need sandboxing inside a Docker container anyway.
RUN opam init --reinit --bare --disable-sandboxing --yes --auto-setup
# Download the latest Infer master
RUN cd / && \
git clone --depth 1 https://github.com/facebook/infer/
# Build opam deps first, then clang, then infer. This way if any step
# fails we don't lose the significant amount of work done in the
# previous steps.
RUN cd /infer && ./build-infer.sh --only-setup-opam
RUN cd /infer && \
eval $(opam env) && \
./autogen.sh && \
./configure && \
./facebook-clang-plugins/clang/setup.sh
# Generate a release
RUN cd /infer && \
make install-with-libs \
BUILD_MODE=opt \
PATCHELF=patchelf \
DESTDIR="/infer-release" \
libdir_relative_to_bindir="../lib"
FROM debian:buster-slim AS executor
RUN apt-get update && apt-get install --yes --no-install-recommends sqlite3
# Get the infer release
COPY --from=compilator /infer-release/usr/local /infer
# Install infer
ENV PATH /infer/bin:${PATH}
# if called with /infer-host mounted then copy infer there
RUN if test -d /infer-host; then \
cp -av /infer/. /infer-host; \
fi

@ -0,0 +1,13 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
class Hello {
int test() {
String s = null;
return s.length();
}
}

@ -0,0 +1,19 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#import <Foundation/Foundation.h>
@interface Hello : NSObject
@property NSString* s;
@end
@implementation Hello
NSString* m() {
Hello* hello = nil;
return hello->_s;
}
@end

@ -0,0 +1,41 @@
This directory contains small examples to play with Infer. They each exhibit
one simple programming error that is caught by Infer.
Contents
--------
- `Hello.java`: try this example by running
```infer -- javac Hello.java ```
- `Hello.m`: try this example by running
```infer -- clang -c Hello.m```
- `hello.c`: try this example by running
```infer -- gcc -c hello.c```
In this case, note that Infer captures the gcc command and runs
clang instead to parse C files. Thus you may get compiler errors and
warnings that differ from gcc's.
- `android_hello/`: a sample Android app. Try this example by running
```infer -- ./gradlew build```
Make sure that you have the Android SDK 22 installed and up to date, and in
particular the "Android SDK Build-tools" and "Android Support Repository".
- `c_hello/`: a sample make-based C project. Try this example by running
```infer -- make```
- `ios_hello/`: a sample iOS app. Try this example by running
```infer -- xcodebuild -target HelloWorldApp -configuration Debug -sdk iphonesimulator```
- `java_hello/`: a sample Java project. Try this example by running
```infer -- javac Pointers.java Resources.java Hello.java```
Note
----
The infer toplevel command must be in your PATH for the commands above to
succeed. Otherwise, modify the commands to use the correct path to infer, eg
```../infer/bin/infer -- javac Hello.java```

@ -0,0 +1,27 @@
apply plugin: 'com.android.application'
android {
compileSdkVersion 22
buildToolsVersion "22.0.1"
lintOptions.abortOnError false
defaultConfig {
applicationId "infer.inferandroidexample"
minSdkVersion 8
targetSdkVersion 22
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:22.0.0'
}

@ -0,0 +1,17 @@
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in /Users/irp/android-sdk-macosx/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}

@ -0,0 +1,18 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
package infer.inferandroidexample;
import android.app.Application;
import android.test.ApplicationTestCase;
/** <a href="http://d.android.com/tools/testing/testing_android.html">Testing Fundamentals</a> */
public class ApplicationTest extends ApplicationTestCase<Application> {
public ApplicationTest() {
super(Application.class);
}
}

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="infer.inferandroidexample" >
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>

@ -0,0 +1,17 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
// _SHOULD_BE_SKIPPED_
package infer.inferandroidexample;
public class Generated {
static Object returnsNull() {
return null;
}
}

@ -0,0 +1,82 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
package infer.inferandroidexample;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.view.Menu;
import android.view.MenuItem;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Calendar;
public class MainActivity extends ActionBarActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
String s = getDay();
int length = s.length();
writeToFile();
}
private String getDay() {
if (Calendar.getInstance().get(Calendar.DAY_OF_WEEK) == Calendar.WEDNESDAY) {
return "Wednesday";
} else {
return otherOutput();
}
}
private String otherOutput() {
return null;
}
private void writeToFile() {
byte[] arr = {1, 2, 3};
FileOutputStream fis;
try {
fis = new FileOutputStream("file.txt");
fis.write(arr);
fis.close();
} catch (IOException e) {
// Deal with exception
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
private void inferShouldNotReport() {
// Generated.java is supposed to be skipped by infer, thus even though
// Generated.returnsNull() returns null, infer is not supposed to know
// about it hence should not report an NPE here
Object o = Generated.returnsNull();
o.toString();
}
}

@ -0,0 +1,29 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
package infer.other;
import android.annotation.SuppressLint;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
public class MainActivity extends ActionBarActivity {
Object source() {
return null;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
source().toString();
}
@SuppressLint("NULL_DEREFERENCE")
void shouldNotBeReported() {
source().toString();
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

@ -0,0 +1,11 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">
<TextView android:text="@string/hello_world" android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</RelativeLayout>

@ -0,0 +1,6 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" tools:context=".MainActivity">
<item android:id="@+id/action_settings" android:title="@string/action_settings"
android:orderInCategory="100" app:showAsAction="never" />
</menu>

@ -0,0 +1,6 @@
<resources>
<!-- Example customization of dimensions originally defined in res/values/dimens.xml
(such as screen margins) for screens with more than 820dp of available width. This
would include 7" and 10" devices in landscape (~960dp and ~1280dp respectively). -->
<dimen name="activity_horizontal_margin">64dp</dimen>
</resources>

@ -0,0 +1,5 @@
<resources>
<!-- Default screen margins, per the Android Design guidelines. -->
<dimen name="activity_horizontal_margin">16dp</dimen>
<dimen name="activity_vertical_margin">16dp</dimen>
</resources>

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">InferAndroidExample</string>
<string name="hello_world">Hello world!</string>
<string name="action_settings">Settings</string>
</resources>

@ -0,0 +1,8 @@
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
</style>
</resources>

@ -0,0 +1,19 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.2.3'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
jcenter()
}
}

@ -0,0 +1,18 @@
# Project-wide Gradle settings.
# IDE (e.g. Android Studio) users:
# Gradle settings configured through the IDE *will override*
# any settings specified in this file.
# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
# Default value: -Xmx10248m -XX:MaxPermSize=256m
# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true

@ -0,0 +1,6 @@
#Wed Apr 10 15:27:10 PDT 2013
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-3.4-bin.zip

@ -0,0 +1,164 @@
#!/usr/bin/env bash
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn ( ) {
echo "$*"
}
die ( ) {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
esac
# For Cygwin, ensure paths are in UNIX format before anything is touched.
if $cygwin ; then
[ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
fi
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >&-
APP_HOME="`pwd -P`"
cd "$SAVED" >&-
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
function splitJvmOpts() {
JVM_OPTS=("$@")
}
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"

@ -0,0 +1,15 @@
# Copyright (c) Facebook, Inc. and its affiliates.
#
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.
SOURCES = $(shell ls *.c)
OBJECTS = $(SOURCES:.c=.o)
all: $(OBJECTS)
.c.o:
${CC} -c $<
clean:
rm -rf $(OBJECTS)

@ -0,0 +1,65 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#include <errno.h>
#include <fcntl.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdlib.h>
#include <string.h>
#include <sys/select.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
struct Person {
int age;
int height;
int weight;
};
int simple_null_pointer() {
struct Person* max = 0;
return max->age;
}
struct Person* Person_create(int age, int height, int weight) {
struct Person* who = 0;
return who;
}
int get_age(struct Person* who) { return who->age; }
int null_pointer_interproc() {
struct Person* joe = Person_create(32, 64, 140);
return get_age(joe);
}
void fileNotClosed() {
int fd = open("hi.txt", O_WRONLY | O_CREAT | O_TRUNC, 0600);
if (fd != -1) {
char buffer[256];
// We can easily batch that by separating with space
write(fd, buffer, strlen(buffer));
}
}
void simple_leak() {
int* p;
p = (int*)malloc(sizeof(int));
}
void common_realloc_leak() {
int *p, *q;
p = (int*)malloc(sizeof(int));
q = (int*)realloc(p, sizeof(int) * 42);
// if realloc fails, then p becomes unreachable
if (q != NULL)
free(q);
}

@ -0,0 +1,15 @@
# Copyright (c) Facebook, Inc. and its affiliates.
#
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.
SOURCES = simple_null.cpp
OBJECTS = $(SOURCES:.cpp=.o)
all: $(OBJECTS)
.cpp.o:
${CC} -c $<
clean:
rm -rf $(OBJECTS)

@ -0,0 +1,10 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
void deref_null() {
int* p = nullptr;
*p = 42;
}

@ -0,0 +1,15 @@
# Copyright (c) Facebook, Inc. and its affiliates.
#
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.
SOURCES = simple_null_interproc.c wrappers.c
OBJECTS = $(SOURCES:.c=.o)
all: $(OBJECTS)
.cpp.o:
${CC} -c $<
clean:
rm -rf $(OBJECTS)

@ -0,0 +1,15 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#include <stdlib.h>
int* allocate_int();
void set(int* p, int value);
void deref_null() {
int* p = allocate_int();
set(p, 42);
}

@ -0,0 +1,19 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#include <stdlib.h>
int* allocate_int();
void set(int* p, int value);
void deref_null_ok() {
int* p = allocate_int();
if (p != NULL) {
set(p, 42);
}
free(p);
}

@ -0,0 +1,11 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#include <stdlib.h>
int* allocate_int() { return malloc(sizeof(int)); }
void set(int* p, int value) { *p = value; }

@ -0,0 +1,15 @@
# Copyright (c) Facebook, Inc. and its affiliates.
#
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.
SOURCES = Resources.java
OBJECT = Resources.class
all: $(OBJECT)
$(OBJECT): $(SOURCES)
javac $^
clean:
rm -rf $(OBJECT)

@ -0,0 +1,26 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
class Resources {
public static void cat() throws IOException {
FileInputStream infile = null;
FileOutputStream outfile = null;
try {
infile = new FileInputStream(new File("infile.txt"));
outfile = new FileOutputStream(new File("outfile.txt"));
outfile.write(infile.read());
} finally {
if (infile != null) infile.close();
if (outfile != null) outfile.close();
}
}
}

@ -0,0 +1,20 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class ResourcesFixed {
public static void cat() throws IOException {
try (FileInputStream infile = new FileInputStream(new File("infile.txt"));
FileOutputStream outfile = new FileOutputStream(new File("outfile.txt")); ) {
outfile.write(infile.read());
}
}
}

@ -0,0 +1,13 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
@ThreadSafe
public interface Account {
void deposit(int amount);
int withdraw(int amount);
}

@ -0,0 +1,30 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
class AccountImplementation implements Account {
int mBalance = 0;
private void addToBalance(int amount) {
mBalance += amount;
}
public synchronized void deposit(int amount) {
if (amount > 0) {
addToBalance(amount);
}
}
public synchronized int withdraw(int amount) {
if (amount >= 0 && mBalance - amount >= 0) {
addToBalance(-amount);
return mBalance;
} else {
return 0;
}
}
}

@ -0,0 +1,19 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
@ThreadSafe
public class Client {
Account account;
void getPaid(int amount) {
account.deposit(amount);
}
int buyCoffee() {
return account.withdraw(5);
}
}

@ -0,0 +1,15 @@
# Copyright (c) Facebook, Inc. and its affiliates.
#
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.
SOURCES = Account.java AccountImplementation.java Client.java
OBJECT = Client.class
all: $(OBJECT)
$(OBJECT): $(SOURCES)
javac $^
clean:
rm -rf $(OBJECT)

@ -0,0 +1,7 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
public @interface ThreadSafe {}

@ -0,0 +1,11 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
public interface Account {
void deposit(int amount);
int withdraw(int amount);
}

@ -0,0 +1,30 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
class AccountImplementation implements Account {
int mBalance = 0;
private void addToBalance(int amount) {
mBalance += amount;
}
public void deposit(int amount) {
if (amount > 0) {
addToBalance(amount);
}
}
public int withdraw(int amount) {
if (amount >= 0 && mBalance - amount >= 0) {
addToBalance(-amount);
return mBalance;
} else {
return 0;
}
}
}

@ -0,0 +1,18 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
public class Client {
Account account;
void getPaid(int amount) {
account.deposit(amount);
}
int buyCoffee() {
return account.withdraw(5);
}
}

@ -0,0 +1,15 @@
# Copyright (c) Facebook, Inc. and its affiliates.
#
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.
SOURCES = Account.java AccountImplementation.java Client.java
OBJECT = Client.class
all: $(OBJECT)
$(OBJECT): $(SOURCES)
javac $^
clean:
rm -rf $(OBJECT)

@ -0,0 +1,7 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
public @interface ThreadSafe {}

@ -0,0 +1,15 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
public class Client<T> {
String foo() {
Library<T> lib = new Library<T>();
T t = lib.get();
return t == null ? "default" : t.toString();
}
}

@ -0,0 +1,22 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
public class Library<T> {
@Nullable T t;
private native @Nullable T mayReturnNull();
public Library() {
t = mayReturnNull();
}
@Nullable
public T get() {
return t;
}
}

@ -0,0 +1,15 @@
# Copyright (c) Facebook, Inc. and its affiliates.
#
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.
SOURCES = Client.java Library.java
OBJECT = Client.class
all: $(OBJECT)
$(OBJECT): $(SOURCES)
javac $^
clean:
rm -rf $(OBJECT)

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save