From 9a2746c14311c5b7fad69b67d372a3aa5de347e5 Mon Sep 17 00:00:00 2001 From: Jules Villard Date: Thu, 13 Jul 2017 05:31:10 -0700 Subject: [PATCH] [make] fix javac capture Summary: This deteriorated over time. Reviewed By: dulmarod Differential Revision: D5406274 fbshipit-source-id: 286f122 --- Makefile | 3 +- examples/java_hello/Makefile | 17 ++++++ infer/lib/wrappers/javac | 25 ++++---- infer/src/integration/Clang.ml | 5 +- .../codetoanalyze/make/Hello.java | 59 +++++++++++++++++++ .../build_systems/codetoanalyze/make/Makefile | 13 +++- .../codetoanalyze/make/Pointers.java | 26 ++++++++ .../codetoanalyze/make/Resources.java | 27 +++++++++ infer/tests/build_systems/make/Makefile | 2 +- infer/tests/build_systems/make/issues.exp | 3 + .../tests/build_systems/utf8_in_pwd/Makefile | 2 +- .../build_systems/utf8_in_pwd/issues.exp | 3 + infer/tests/build_systems/waf/issues.exp | 3 + 13 files changed, 164 insertions(+), 24 deletions(-) create mode 100644 examples/java_hello/Makefile create mode 100644 infer/tests/build_systems/codetoanalyze/make/Hello.java create mode 100644 infer/tests/build_systems/codetoanalyze/make/Pointers.java create mode 100644 infer/tests/build_systems/codetoanalyze/make/Resources.java diff --git a/Makefile b/Makefile index 0b145307f..f1781e466 100644 --- a/Makefile +++ b/Makefile @@ -23,7 +23,6 @@ BUILD_SYSTEMS_TESTS += \ fail_on_issue \ j1 \ linters \ - make \ project_root_rel \ reactive \ run_hidden_linters \ @@ -84,7 +83,7 @@ endif endif ifeq ($(BUILD_C_ANALYZERS)+$(BUILD_JAVA_ANALYZERS),yes+yes) -BUILD_SYSTEMS_TESTS += utf8_in_pwd +BUILD_SYSTEMS_TESTS += make utf8_in_pwd endif .PHONY: all diff --git a/examples/java_hello/Makefile b/examples/java_hello/Makefile new file mode 100644 index 000000000..f90ab404d --- /dev/null +++ b/examples/java_hello/Makefile @@ -0,0 +1,17 @@ +# Copyright (c) 2017 - present Facebook, Inc. +# All rights reserved. +# +# This source code is licensed under the BSD style license found in the +# LICENSE file in the root directory of this source tree. An additional grant +# of patent rights can be found in the PATENTS file in the same directory. + +SOURCES = Resources.java Pointers.java Hello.java +OBJECTS = $(SOURCES:.java=.class) + +all: Hello.class + +%.class: $(SOURCES) + javac $(SOURCES) + +clean: + rm -rf $(OBJECTS) diff --git a/infer/lib/wrappers/javac b/infer/lib/wrappers/javac index 6eb05358f..6dbeee1fb 100755 --- a/infer/lib/wrappers/javac +++ b/infer/lib/wrappers/javac @@ -2,28 +2,23 @@ # This is a wrapper for javac -if [ -z "$INFER_RESULTS_DIR" ]; then - echo '$INFER_RESULTS_DIR with a path to the results dir not provided.' > /dev/stderr - exit 1 -elif [ -z "$INFER_OLD_PATH" ]; then +if [ -z "$INFER_OLD_PATH" ]; then echo '$INFER_OLD_PATH with a copy of $PATH not provided.' > /dev/stderr exit 1 fi -HOST_COMPILER=(`PATH=$INFER_OLD_PATH which javac`) +HOST_COMPILER=(`PATH="$INFER_OLD_PATH" which javac`) COMPILER_ARGS=("$@") HOST_COMPILER_COMMAND=("$HOST_COMPILER" "${COMPILER_ARGS[@]}") -FRONTEND_COMMAND=("infer" "-a" "capture" "-o" "$INFER_RESULTS_DIR" "--" "javac" "${COMPILER_ARGS[@]}") +FRONTEND_COMMAND=("infer" "capture" "--continue" "--" "javac" "${COMPILER_ARGS[@]}") if [[ "$*" == *-version* ]]; then - "${HOST_COMPILER_COMMAND[@]}" -elif [ -n "$INFER_COMPILER_WRAPPER_IN_RECURSION" ]; then - if [ -z "$INFER_LISTENER" ]; then - "${HOST_COMPILER_COMMAND[@]}" - fi + exec "${HOST_COMPILER_COMMAND[@]}" +elif [ "$INFER_COMPILER_WRAPPER_IN_RECURSION" != "1" ]; then + export INFER_COMPILER_WRAPPER_IN_RECURSION="1" + PATH="$INFER_OLD_PATH" exec "${FRONTEND_COMMAND[@]}" else - export INFER_COMPILER_WRAPPER_IN_RECURSION="Y" - "${FRONTEND_COMMAND[@]}" + echo 'ERROR: the javac wrapper called itself!' > /dev/stderr + # internal error + exit 3 fi - -exit $? diff --git a/infer/src/integration/Clang.ml b/infer/src/integration/Clang.ml index a9a14a2bf..d20db40e2 100644 --- a/infer/src/integration/Clang.ml +++ b/infer/src/integration/Clang.ml @@ -49,8 +49,9 @@ let capture compiler ~prog ~args = -> ClangWrapper.exe ~prog ~args | Make -> let path_var = "PATH" in - let new_path = Config.wrappers_dir ^ ":" ^ Sys.getenv_exn path_var in - let extended_env = `Extend [(path_var, new_path)] in + let old_path = Option.value ~default:"" (Sys.getenv path_var) in + let new_path = Config.wrappers_dir ^ ":" ^ old_path in + let extended_env = `Extend [(path_var, new_path); ("INFER_OLD_PATH", old_path)] in L.environment_info "Running command %s with env:@\n%a@\n@." prog pp_extended_env extended_env ; Unix.fork_exec ~prog ~argv:(prog :: args) ~env:extended_env () |> Unix.waitpid |> function diff --git a/infer/tests/build_systems/codetoanalyze/make/Hello.java b/infer/tests/build_systems/codetoanalyze/make/Hello.java new file mode 100644 index 000000000..0ae51fa3d --- /dev/null +++ b/infer/tests/build_systems/codetoanalyze/make/Hello.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2015 - present Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +package hello; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.Random; + +class Hello { + + void doesNotCauseNPE() { + Pointers.A a = Pointers.mayReturnNull(10); + a.method(); + } + + void mayCauseNPE() { + Random rng = new Random(); + Pointers.A a = Pointers.mayReturnNull(rng.nextInt()); + // NPE + a.method(); + } + + void mayLeakResource() throws IOException { + OutputStream stream = Resources.allocateResource(); + if (stream == null) { + return; + } + + try { + stream.write(12); + } finally { + // Resource leak + } + } + + void twoResources() throws IOException { + FileInputStream fis = null; + FileOutputStream fos = null; + try { + fis = new FileInputStream(new File("whatever.txt")); + fos = new FileOutputStream(new File("everwhat.txt")); + fos.write(fis.read()); + } finally { + if (fis != null) { fis.close(); } // Resource leak + if (fos != null) { fos.close(); } + } + } + +} diff --git a/infer/tests/build_systems/codetoanalyze/make/Makefile b/infer/tests/build_systems/codetoanalyze/make/Makefile index 087da7b66..3acd8f8b6 100644 --- a/infer/tests/build_systems/codetoanalyze/make/Makefile +++ b/infer/tests/build_systems/codetoanalyze/make/Makefile @@ -5,13 +5,20 @@ # LICENSE file in the root directory of this source tree. An additional grant # of patent rights can be found in the PATENTS file in the same directory. -SOURCES = $(shell ls *.c) -OBJECTS = $(SOURCES:.c=.o) +C_SOURCES = $(shell ls *.c) +JAVA_SOURCES = Resources.java Pointers.java Hello.java +SOURCES = $(C_SOURCES) $(JAVA_SOURCES) +C_OBJECTS = $(C_SOURCES:.c=.o) +JAVA_OBJECTS = $(JAVA_SOURCES:.java=.class) +OBJECTS = $(C_OBJECTS) $(JAVA_OBJECTS) -all: $(OBJECTS) +all: $(C_OBJECTS) Hello.class .c.o: $(CC) -c $< +%.class: $(JAVA_SOURCES) + javac $(JAVA_SOURCES) + clean: rm -rf $(OBJECTS) diff --git a/infer/tests/build_systems/codetoanalyze/make/Pointers.java b/infer/tests/build_systems/codetoanalyze/make/Pointers.java new file mode 100644 index 000000000..3d8efa90a --- /dev/null +++ b/infer/tests/build_systems/codetoanalyze/make/Pointers.java @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2015 - present Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +package hello; + +public class Pointers { + + public static class A { + public void method() { + } + } + + public static A mayReturnNull(int i) { + if (i > 0) { + return new A(); + } + return null; + } + +} diff --git a/infer/tests/build_systems/codetoanalyze/make/Resources.java b/infer/tests/build_systems/codetoanalyze/make/Resources.java new file mode 100644 index 000000000..c5f0b5234 --- /dev/null +++ b/infer/tests/build_systems/codetoanalyze/make/Resources.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2015 - present Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +package hello; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; + +public class Resources { + + public static FileOutputStream allocateResource() { + try { + File file = new File("foo.txt"); + return new FileOutputStream(file); + } catch (IOException e) { + return null; + } + } + +} diff --git a/infer/tests/build_systems/make/Makefile b/infer/tests/build_systems/make/Makefile index 99a400158..4c0cdfa52 100644 --- a/infer/tests/build_systems/make/Makefile +++ b/infer/tests/build_systems/make/Makefile @@ -17,7 +17,7 @@ SOURCES = $(wildcard ../codetoanalyze/make/*.c) include $(TESTS_DIR)/clang.make infer-out/report.json: $(CLANG_DEPS) $(SOURCES) $(HEADERS) - $(QUIET)$(call silent_on_success,Testing make clang integration,\ + $(QUIET)$(call silent_on_success,Testing make clang and javac integration,\ $(INFER_BIN) --dump-duplicate-symbols --project-root $(TESTS_DIR) -a $(ANALYZER) -- \ make -C ../codetoanalyze/make clean all) $(QUIET)$(call check_no_duplicates,infer-out/duplicates.txt) diff --git a/infer/tests/build_systems/make/issues.exp b/infer/tests/build_systems/make/issues.exp index 26203c528..1fc806660 100644 --- a/infer/tests/build_systems/make/issues.exp +++ b/infer/tests/build_systems/make/issues.exp @@ -1 +1,4 @@ +build_systems/codetoanalyze/make/Hello.java, void Hello.mayCauseNPE(), 4, NULL_DEREFERENCE, [start of procedure mayCauseNPE(),Skipped call: function or method not found,start of procedure mayReturnNull(...),Taking false branch,return from a call to Pointers$A Pointers.mayReturnNull(int)] +build_systems/codetoanalyze/make/Hello.java, void Hello.mayLeakResource(), 7, RESOURCE_LEAK, [start of procedure mayLeakResource(),start of procedure allocateResource(),Skipped call: function or method not found,return from a call to FileOutputStream Resources.allocateResource(),Taking false branch] +build_systems/codetoanalyze/make/Hello.java, void Hello.twoResources(), 11, RESOURCE_LEAK, [start of procedure twoResources(),Taking true branch,exception java.io.IOException] build_systems/codetoanalyze/make/utf8_in_function_names.c, test_성공, 2, NULL_DEREFERENCE, [start of procedure test_성공()] diff --git a/infer/tests/build_systems/utf8_in_pwd/Makefile b/infer/tests/build_systems/utf8_in_pwd/Makefile index 35253c64e..0e5151e37 100644 --- a/infer/tests/build_systems/utf8_in_pwd/Makefile +++ b/infer/tests/build_systems/utf8_in_pwd/Makefile @@ -31,7 +31,7 @@ JAVAC_SOURCES = $(ROOT_DIR)/examples/Hello.java MAKE_DIR = $(UTF8_DIR)/make MAKE_SOURCES_DIR = ../codetoanalyze/make -MAKE_SOURCES = $(wildcard $(MAKE_SOURCES_DIR)/*.c) +MAKE_SOURCES = $(wildcard $(MAKE_SOURCES_DIR)/*.c $(MAKE_SOURCES_DIR)/*.java) ANALYZER = infer CLEAN_EXTRA = $(CMAKE_BUILD_DIR) $(CMAKE_ANALYZE_DIR) infer-out-cmake diff --git a/infer/tests/build_systems/utf8_in_pwd/issues.exp b/infer/tests/build_systems/utf8_in_pwd/issues.exp index 93a044100..1a3326f9b 100644 --- a/infer/tests/build_systems/utf8_in_pwd/issues.exp +++ b/infer/tests/build_systems/utf8_in_pwd/issues.exp @@ -3,4 +3,7 @@ Hello.java, void Hello.mayCauseNPE(), 4, NULL_DEREFERENCE, [start of procedure m Hello.java, void Hello.mayLeakResource(), 7, RESOURCE_LEAK, [start of procedure mayLeakResource(),start of procedure allocateResource(),Skipped call: function or method not found,return from a call to FileOutputStream Resources.allocateResource(),Taking false branch] Hello.java, void Hello.twoResources(), 11, RESOURCE_LEAK, [start of procedure twoResources(),Taking true branch,exception java.io.IOException] Hello.java, int Hello.test(), 2, NULL_DEREFERENCE, [start of procedure test()] +Hello.java, void Hello.mayCauseNPE(), 4, NULL_DEREFERENCE, [start of procedure mayCauseNPE(),Skipped call: function or method not found,start of procedure mayReturnNull(...),Taking false branch,return from a call to Pointers$A Pointers.mayReturnNull(int)] +Hello.java, void Hello.mayLeakResource(), 7, RESOURCE_LEAK, [start of procedure mayLeakResource(),start of procedure allocateResource(),Skipped call: function or method not found,return from a call to FileOutputStream Resources.allocateResource(),Taking false branch] +Hello.java, void Hello.twoResources(), 11, RESOURCE_LEAK, [start of procedure twoResources(),Taking true branch,exception java.io.IOException] utf8_in_function_names.c, test_성공, 2, NULL_DEREFERENCE, [start of procedure test_성공()] diff --git a/infer/tests/build_systems/waf/issues.exp b/infer/tests/build_systems/waf/issues.exp index b785ca3df..67bf25b9a 100644 --- a/infer/tests/build_systems/waf/issues.exp +++ b/infer/tests/build_systems/waf/issues.exp @@ -1 +1,4 @@ +Hello.java, void Hello.mayCauseNPE(), 4, NULL_DEREFERENCE, [start of procedure mayCauseNPE(),Skipped call: function or method not found,start of procedure mayReturnNull(...),Taking false branch,return from a call to Pointers$A Pointers.mayReturnNull(int)] +Hello.java, void Hello.mayLeakResource(), 7, RESOURCE_LEAK, [start of procedure mayLeakResource(),start of procedure allocateResource(),Skipped call: function or method not found,return from a call to FileOutputStream Resources.allocateResource(),Taking false branch] +Hello.java, void Hello.twoResources(), 11, RESOURCE_LEAK, [start of procedure twoResources(),Taking true branch,exception java.io.IOException] utf8_in_function_names.c, test_성공, 2, NULL_DEREFERENCE, [start of procedure test_성공()]