diff --git a/infer/tests/codetoanalyze/java/quandary/TaintExample.java b/infer/tests/codetoanalyze/java/quandary/TaintExample.java new file mode 100644 index 000000000..30c8cd0be --- /dev/null +++ b/infer/tests/codetoanalyze/java/quandary/TaintExample.java @@ -0,0 +1,268 @@ +/* + * Copyright (c) 2013 - 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 codetoanalyze.java.quandary; + +import java.io.InputStream; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.Socket; +import java.net.URL; + +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.SSLException; +import javax.net.ssl.SSLSession; +import javax.net.ssl.SSLSocket; +import javax.net.ssl.SSLSocketFactory; + +import android.content.ContentValues; +import android.content.SharedPreferences; + +import com.facebook.infer.builtins.InferTaint; +import com.facebook.infer.annotation.IntegritySource; +import com.facebook.infer.annotation.IntegritySink; +import com.facebook.infer.annotation.PrivacySource; +import com.facebook.infer.annotation.PrivacySink; + +public class TaintExample { + + public InputStream socketNotVerifiedSimple_FN(SSLSocketFactory f) + throws IOException { + Socket socket = f.createSocket(); + return socket.getInputStream(); + } + + public InputStream socketVerifiedForgotToCheckRetval_FN( + SSLSocketFactory f, + HostnameVerifier v, + SSLSession session) + throws IOException { + + Socket socket = f.createSocket(); + v.verify("hostname", session); + return socket.getInputStream(); + } + + public InputStream socketVerifiedOk1(SSLSocketFactory f, + HostnameVerifier v, + SSLSession session) + throws IOException { + + Socket socket = f.createSocket(); + if (v.verify("hostname", session)) { + return socket.getInputStream(); + } else { + return null; + } + } + + HostnameVerifier mHostnameVerifier; + + public void throwExceptionIfNoVerify(SSLSocket sslSocket, String host) + throws IOException { + + if (!mHostnameVerifier.verify(host, sslSocket.getSession())) { + throw new SSLException("Couldn't verify!"); + } + } + + public InputStream socketVerifiedOk2(SSLSocketFactory f) throws IOException { + SSLSocket s = (SSLSocket) f.createSocket(); + throwExceptionIfNoVerify(s, "hostname"); + return s.getInputStream(); + } + + public InputStream socketIgnoreExceptionNoVerify_FN(SSLSocketFactory f) + throws IOException { + + SSLSocket s = (SSLSocket) f.createSocket(); + try { + throwExceptionIfNoVerify(s, "hostname"); + } catch (SSLException e) { + // ignore the fact that verifying the socket failed + } + return s.getInputStream(); + } + + public InputStream taintingShouldNotPreventInference1_FN(SSLSocketFactory f) throws IOException { + socketNotVerifiedSimple_FN(f).toString(); + // failing to infer a post for socketNotVerifiedSimple will hide this error + Socket s = f.createSocket(); + return s.getInputStream(); + } + + public InputStream readInputStream(Socket socket) throws IOException { + return socket.getInputStream(); + } + + // if we're not careful, postcondition inference will fail for this function + Socket callReadInputStreamCauseTaintError_FN(SSLSocketFactory f) + throws IOException { + Socket socket = f.createSocket(); + InputStream s = readInputStream(socket); + s.toString(); // to avoid RETURN_VALUE_IGNORED warning + return f.createSocket(); + } + + InputStream taintingShouldNotPreventInference2(SSLSocketFactory f) throws IOException { + // if inference fails for this callee, we won't report an error here + Socket s = callReadInputStreamCauseTaintError_FN(f); + return s.getInputStream(); + } + + public void simpleTaintErrorWithModelMethods() { + Object o = InferTaint.inferSecretSource(); + InferTaint.inferSensitiveSink(o); + } + + public Object returnTaintedSourceModelMethods() { + return InferTaint.inferSecretSource(); + } + + public void callSinkMethodModelMethods(Object o) { + InferTaint.inferSensitiveSink(o); + } + + public void interprocTaintErrorWithModelMethods1() { + InferTaint.inferSensitiveSink(returnTaintedSourceModelMethods()); + } + + public void interprocTaintErrorWithModelMethods2() { + callSinkMethodModelMethods(InferTaint.inferSecretSource()); + } + + public void interprocTaintErrorWithModelMethods3() { + callSinkMethodModelMethods(returnTaintedSourceModelMethods()); + } + + public void simpleTaintErrorWithModelMethodsUndefined_FN() { + Object o = InferTaint.inferSecretSourceUndefined(); + InferTaint.inferSensitiveSinkUndefined(o); + } + + public Object returnTaintedSourceModelMethodsUndefined() { + return InferTaint.inferSecretSourceUndefined(); + } + + public void callSinkMethodModelMethodsUndefined(Object o) { + InferTaint.inferSensitiveSinkUndefined(o); + } + + public void interprocTaintErrorWithModelMethodsUndefined1_FN() { + InferTaint.inferSensitiveSinkUndefined(returnTaintedSourceModelMethodsUndefined()); + } + + public void interprocTaintErrorWithModelMethodsUndefined2_FN() { + callSinkMethodModelMethodsUndefined(InferTaint.inferSecretSourceUndefined()); + } + + public void interprocTaintErrorWithModelMethodsUndefined3_FN() { + callSinkMethodModelMethodsUndefined(returnTaintedSourceModelMethodsUndefined()); + } + + public void contentValuesPutWithTaintedString_FN( + ContentValues values, SharedPreferences prefs, String key, String value) { + values.put(key, prefs.getString(key, value)); + } + + public void contentValuesPutOk(ContentValues values, String key, String value) { + values.put(key, value); + } + + @PrivacySource + public String privacySource() { + return "source"; + } + + public void testPrivacySourceAnnot_FN() { + InferTaint.inferSensitiveSinkUndefined(privacySource()); // should report + } + + public void instancePrivacySink(@PrivacySink String s1, String s2) { + } + + public static void staticPrivacySink(@PrivacySink String s1, String s2) { + } + + public void testPrivacySinkAnnot1_FN() { + String source = privacySource(); + instancePrivacySink(source, ""); // should report + } + + public void testPrivacySinkAnnot2() { + String source = privacySource(); + instancePrivacySink("", source); // should not report + } + + public void testPrivacySinkAnnot3_FN() { + String source = privacySource(); + staticPrivacySink(source, ""); // should report + } + + public void testPrivacySinkAnnot4() { + String source = privacySource(); + staticPrivacySink("", source); // should not report + } + + @PrivacySource String mPrivacySource; + + @PrivacySource String sPrivacySource; + + public void testPrivacySourceInstanceFieldAnnot_FN() { + String source = mPrivacySource; + InferTaint.inferSensitiveSinkUndefined(source); // should report + } + + public void testPrivacySourceStaticFieldAnnot_FN() { + String source = sPrivacySource; + InferTaint.inferSensitiveSinkUndefined(source); // should report + } + + String aFieldWithoutAnnotations; + + public void testPrivacySourceFieldAnnotPropagation_FN() { + aFieldWithoutAnnotations = mPrivacySource; + InferTaint.inferSensitiveSinkUndefined(aFieldWithoutAnnotations); // should report + } + + @IntegritySource + public String integritySource() { + return "source"; + } + + @IntegritySource String mIntegritySource; + + @IntegritySource String sIntegritySource; + + public void testIntegritySourceAnnot_FN() { + InferTaint.inferSensitiveSinkUndefined(integritySource()); // should report + } + + public void testIntegritySourceInstanceFieldAnnot_FN() { + String source = mIntegritySource; + InferTaint.inferSensitiveSinkUndefined(source); // should report + } + + public void testIntegritySourceStaticFieldAnnot_FN() { + String source = sIntegritySource; + InferTaint.inferSensitiveSinkUndefined(source); // should report + } + + public void integritySink(@IntegritySink String s1, String s2) { + } + + void testIntegritySinkAnnotReport_FN(String s) { + integritySink(integritySource(), s); // should report + } + + void testIntegritySinkAnnotNoReport(String s) { + integritySink(s, integritySource()); // should not report + } + +} diff --git a/infer/tests/codetoanalyze/java/quandary/issues.exp b/infer/tests/codetoanalyze/java/quandary/issues.exp index b4996deb4..6be6a0e3a 100644 --- a/infer/tests/codetoanalyze/java/quandary/issues.exp +++ b/infer/tests/codetoanalyze/java/quandary/issues.exp @@ -202,6 +202,10 @@ codetoanalyze/java/quandary/Strings.java, void Strings.viaStringBuilderIgnoreRet codetoanalyze/java/quandary/Strings.java, void Strings.viaStringBuilderSugarBad(), 2, QUANDARY_TAINT_ERROR, [Return from Object InferTaint.inferSecretSource(),Call to void InferTaint.inferSensitiveSink(Object)] codetoanalyze/java/quandary/Strings.java, void Strings.viaStringFormatVarArgsDirectBad(), 3, QUANDARY_TAINT_ERROR, [Return from Object InferTaint.inferSecretSource(),Call to void InferTaint.inferSensitiveSink(Object)] codetoanalyze/java/quandary/Strings.java, void Strings.viaStringFormatVarArgsIndirectBad(), 1, QUANDARY_TAINT_ERROR, [Return from Object InferTaint.inferSecretSource(),Call to void Strings.viaStringFormatVarArgsIndirect(Object),Call to void InferTaint.inferSensitiveSink(Object)] +codetoanalyze/java/quandary/TaintExample.java, void TaintExample.interprocTaintErrorWithModelMethods1(), 1, QUANDARY_TAINT_ERROR, [Return from Object InferTaint.inferSecretSource() with tainted data &return,Return from Object TaintExample.returnTaintedSourceModelMethods(),Call to void InferTaint.inferSensitiveSink(Object)] +codetoanalyze/java/quandary/TaintExample.java, void TaintExample.interprocTaintErrorWithModelMethods2(), 1, QUANDARY_TAINT_ERROR, [Return from Object InferTaint.inferSecretSource(),Call to void TaintExample.callSinkMethodModelMethods(Object),Call to void InferTaint.inferSensitiveSink(Object)] +codetoanalyze/java/quandary/TaintExample.java, void TaintExample.interprocTaintErrorWithModelMethods3(), 1, QUANDARY_TAINT_ERROR, [Return from Object InferTaint.inferSecretSource() with tainted data &return,Return from Object TaintExample.returnTaintedSourceModelMethods(),Call to void TaintExample.callSinkMethodModelMethods(Object),Call to void InferTaint.inferSensitiveSink(Object)] +codetoanalyze/java/quandary/TaintExample.java, void TaintExample.simpleTaintErrorWithModelMethods(), 2, QUANDARY_TAINT_ERROR, [Return from Object InferTaint.inferSecretSource(),Call to void InferTaint.inferSensitiveSink(Object)] codetoanalyze/java/quandary/TaintedFormals.java, void TaintedFormals.callTaintedContextBad1(String), 2, QUANDARY_TAINT_ERROR, [Return from Object TaintedFormals.taintedContextBad(String) with tainted data &return,Return from Object TaintedFormals.taintedContextBad(String),Call to void InferTaint.inferSensitiveSink(Object)] codetoanalyze/java/quandary/TaintedFormals.java, void TaintedFormals.callTaintedContextBad2(), 1, QUANDARY_TAINT_ERROR, [Return from Object InferTaint.inferSecretSource(),Call to void TaintedFormals.taintedContextBad(String,Intent,Integer),Call to ComponentName ContextWrapper.startService(Intent)] codetoanalyze/java/quandary/TaintedFormals.java, void TaintedFormals.taintedContextBad(String,Intent,Integer), 3, QUANDARY_TAINT_ERROR, [Return from void TaintedFormals.taintedContextBad(String,Intent,Integer),Call to void InferTaint.inferSensitiveSink(Object)]