|
|
|
#!/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.
|
|
|
|
|
|
|
|
# USAGE
|
|
|
|
#
|
|
|
|
# 1. Follow instructions in https://source.android.com/setup/build/downloading to download
|
|
|
|
# the AOSP source and in https://source.android.com/setup/build/building to get proprietary
|
|
|
|
# binaries. You will need lots of space (at least 100Gb). Let <android-root> be its root as
|
|
|
|
# an *absolute path*.
|
|
|
|
#
|
|
|
|
# 2. Replace <android-root>/prebuilts/jdk/jdk9/<your OS>/bin/javac with the following script.
|
|
|
|
#
|
|
|
|
# #!/bin/bash
|
|
|
|
# infer -q --capture --continue --starvation-only --no-starvation \
|
|
|
|
# --project-root <android-root> --results-dir <android-root>/infer-out -- \
|
|
|
|
# /usr/local/bin/javac "$@"
|
|
|
|
#
|
|
|
|
# Here, my local installation of java is in /usr/local/, change accordingly. I used a
|
|
|
|
# Java *8* installation without problems, YMMV.
|
|
|
|
#
|
|
|
|
# 3. From <android-root> do
|
|
|
|
#
|
|
|
|
# $ . build/envsetup.sh
|
|
|
|
# $ export TEMPORARY_DISABLE_PATH_RESTRICTIONS=true
|
|
|
|
# $ cd libcore/ojluni
|
|
|
|
# $ mm -j1 javac-check
|
|
|
|
#
|
|
|
|
# ... and wait. It took me ~22h.
|
|
|
|
#
|
|
|
|
# 4. From <android-root> run
|
|
|
|
#
|
|
|
|
# $ infer analyze --starvation-only --dev-android-strict-mode
|
|
|
|
#
|
|
|
|
# 5. From <android-root> run this script, capturing stdout.
|
|
|
|
#
|
|
|
|
# $ <infer-root>/scripts/make-strict-mode.sh > \
|
|
|
|
# <infer-root>/infer/src/concurrency/StrictModeModels.ml
|
|
|
|
#
|
|
|
|
# 6. You may need to adapt the optional ~actuals_pred argument for methods in the above ML file.
|
|
|
|
# The aim is to avoid false positives when there is an overloaded method with different
|
|
|
|
# signatures and it so happens that one of the versions makes a violation when another does not.
|
|
|
|
# Recompile Infer.
|
|
|
|
|
|
|
|
|
|
|
|
SOURCE_FILES=$(grep "error:" infer-out/bugs.txt | cut -f1 -d: | sort -u | grep -v test )
|
|
|
|
MATCHERS=""
|
|
|
|
|
|
|
|
cat <<EOF
|
|
|
|
(*
|
|
|
|
* 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.
|
|
|
|
*)
|
|
|
|
|
|
|
|
open! IStd
|
|
|
|
open ConcurrencyModels
|
|
|
|
|
|
|
|
EOF
|
|
|
|
|
|
|
|
for SOURCE_FILE in $SOURCE_FILES ; do
|
|
|
|
PACKAGE=$(grep -E "^package " $SOURCE_FILE | cut -f2 -d' ' | cut -f1 -d\;)
|
|
|
|
|
|
|
|
if [[ $PACKAGE != android.* ]] && [[ $PACKAGE != androidx.* ]] && [[ $PACKAGE != java.* ]] ; then
|
|
|
|
continue
|
|
|
|
fi
|
|
|
|
|
|
|
|
BASENAME=$(basename $SOURCE_FILE )
|
|
|
|
CLASS=${BASENAME%.*}
|
|
|
|
|
|
|
|
if ! grep -q -E "public.*class.* ${CLASS}" $SOURCE_FILE ; then
|
|
|
|
continue
|
|
|
|
fi
|
|
|
|
|
|
|
|
HIDE=$(grep -B 2 -E "public.*class.* ${CLASS}" $SOURCE_FILE | grep '@hide')
|
|
|
|
if [ ! -z "$HIDE" ] ; then
|
|
|
|
continue
|
|
|
|
fi
|
|
|
|
|
|
|
|
FULLCLASSNAME="${PACKAGE}.${CLASS}"
|
|
|
|
METHOD_REXP="^ Method \`.* $CLASS\."
|
|
|
|
METHODS=$(grep -E "$METHOD_REXP" infer-out/bugs.txt | cut -f2 -d. | cut -f1 -d\` | sort -u)
|
|
|
|
|
|
|
|
if [ -z "$METHODS" ] ; then
|
|
|
|
continue
|
|
|
|
fi
|
|
|
|
|
|
|
|
HEADER=""
|
|
|
|
MATCHER="is_${CLASS}_method"
|
|
|
|
|
|
|
|
for METHOD in $METHODS; do
|
|
|
|
METHODNAME=$(echo $METHOD | cut -f1 -d\( )
|
|
|
|
|
|
|
|
if ! grep -q -E "public.*${METHODNAME}" $SOURCE_FILE ; then
|
|
|
|
continue
|
|
|
|
fi
|
|
|
|
|
|
|
|
if [ -z "$HEADER" ] ; then
|
|
|
|
echo "(* $SOURCE_FILE *)"
|
|
|
|
echo "let ${MATCHER} ="
|
|
|
|
echo " is_call_of_class \"${FULLCLASSNAME}\""
|
|
|
|
echo " ["
|
|
|
|
HEADER=true
|
|
|
|
fi
|
|
|
|
|
|
|
|
echo " \"${METHODNAME}\"; (* $METHOD *)"
|
|
|
|
done
|
|
|
|
|
|
|
|
if [ ! -z "$HEADER" ] ; then
|
|
|
|
echo " ]"
|
|
|
|
echo ' |> Staged.unstage'
|
|
|
|
echo
|
|
|
|
MATCHERS="$MATCHERS $MATCHER"
|
|
|
|
fi
|
|
|
|
done
|
|
|
|
|
|
|
|
echo
|
|
|
|
echo "let is_strict_mode_violation ="
|
|
|
|
echo " let matchers = ["
|
|
|
|
for M in $MATCHERS ; do
|
|
|
|
echo " $M ;"
|
|
|
|
done
|
|
|
|
echo " ]"
|
|
|
|
echo " in"
|
|
|
|
echo " fun tenv pn actuals -> List.exists matchers ~f:(fun m -> m tenv pn actuals)"
|