diff --git a/infer/src/checkers/ThreadSafety.ml b/infer/src/checkers/ThreadSafety.ml index 1d3362ac1..55f203ba7 100644 --- a/infer/src/checkers/ThreadSafety.ml +++ b/infer/src/checkers/ThreadSafety.ml @@ -1055,8 +1055,7 @@ let report_unsafe_accesses ~is_file_threadsafe aggregated_access_map = | Access.Read -> let reported_reads = Typ.Procname.Set.add pname reported.reported_reads in { reported with reported_reads; reported_sites; } in - let report_unsafe_access - ~should_report (access, pre, threaded, tenv, pdesc) accesses reported_acc = + let report_unsafe_access (access, pre, threaded, tenv, pdesc) accesses reported_acc = let pname = Procdesc.get_proc_name pdesc in if is_duplicate_report access pname reported_acc then @@ -1145,7 +1144,7 @@ let report_unsafe_accesses ~is_file_threadsafe aggregated_access_map = let reportable_accesses = List.filter ~f:(fun (_, _, _, tenv, pdesc) -> should_report pdesc tenv) grouped_accesses in List.fold - ~f:(fun acc access -> report_unsafe_access ~should_report access reportable_accesses acc) + ~f:(fun acc access -> report_unsafe_access access reportable_accesses acc) reportable_accesses ~init:reported) aggregated_access_map diff --git a/infer/src/quandary/JavaTrace.ml b/infer/src/quandary/JavaTrace.ml index 14c0d2c68..f68496b49 100644 --- a/infer/src/quandary/JavaTrace.ml +++ b/infer/src/quandary/JavaTrace.ml @@ -99,7 +99,8 @@ module SourceKind = struct match Procdesc.get_proc_name pdesc with | Typ.Procname.Java java_pname -> begin - match Typ.Procname.java_get_class_name java_pname, Typ.Procname.java_get_method java_pname with + match Typ.Procname.java_get_class_name java_pname, + Typ.Procname.java_get_method java_pname with | "codetoanalyze.java.quandary.TaintedFormals", "taintedContextBad" -> taint_formals_with_types ["java.lang.Integer"; "java.lang.String"] Other formals | class_name, method_name -> @@ -107,6 +108,16 @@ module SourceKind = struct match Typ.Name.name typename, method_name with | "android.app.Activity", ("onActivityResult" | "onNewIntent") -> Some (taint_formals_with_types ["android.content.Intent"] Intent formals) + | "android.webkit.WebViewClient", + ("onLoadResource" | "shouldInterceptRequest" | "shouldOverrideUrlLoading") -> + Some + (taint_formals_with_types + ["android.webkit.WebResourceRequest"; "java.lang.String"] + Intent + formals) + | "android.webkit.WebChromeClient", + ("onJsAlert" | "onJsBeforeUnload" | "onJsConfirm" | "onJsPrompt") -> + Some (taint_formals_with_types ["java.lang.String"] Intent formals) | _ -> None in begin @@ -215,20 +226,13 @@ module SinkKind = struct Some (taint_nth 0 Intent ~report_reachable:true) | "android.content.Intent", "setClassName" -> Some (taint_all Intent ~report_reachable:true) - | "android.webkit.WebChromeClient", - ("onJsAlert" | "onJsBeforeUnload" | "onJsConfirm" | "onJsPrompt") -> - Some (taint_all JavaScript ~report_reachable:true) | "android.webkit.WebView", - ("addJavascriptInterface" | - "evaluateJavascript" | + ("evaluateJavascript" | "loadData" | "loadDataWithBaseURL" | "loadUrl" | "postWebMessage") -> Some (taint_all JavaScript ~report_reachable:true) - | "android.webkit.WebViewClient", - ("onLoadResource" | "shouldInterceptRequest" | "shouldOverrideUrlLoading") -> - Some (taint_all JavaScript ~report_reachable:true) | class_name, method_name -> (* check the list of externally specified sinks *) let procedure = class_name ^ "." ^ method_name in diff --git a/infer/tests/codetoanalyze/java/quandary/WebViews.java b/infer/tests/codetoanalyze/java/quandary/WebViews.java index 316fa539d..b27df2ea4 100644 --- a/infer/tests/codetoanalyze/java/quandary/WebViews.java +++ b/infer/tests/codetoanalyze/java/quandary/WebViews.java @@ -9,16 +9,22 @@ package codetoanalyze.java.quandary; -import android.content.Context; +import java.net.URISyntaxException; +import android.app.Activity; +import android.content.Context; import android.content.Intent; import android.net.Uri; import android.webkit.JavascriptInterface; +import android.webkit.JsPromptResult; +import android.webkit.JsResult; import android.webkit.ValueCallback; +import android.webkit.WebChromeClient; import android.webkit.WebMessage; +import android.webkit.WebResourceRequest; +import android.webkit.WebResourceResponse; import android.webkit.WebView; import android.webkit.WebViewClient; -import android.webkit.WebChromeClient; import com.facebook.infer.builtins.InferTaint; @@ -27,7 +33,6 @@ public class WebViews { void callWebviewSinks(WebView webview) { String stringSource = (String) InferTaint.inferSecretSource(); - webview.addJavascriptInterface(new Object(), stringSource); webview.evaluateJavascript(stringSource, null); webview.loadData(stringSource, "", ""); webview.loadDataWithBaseURL("", stringSource, "", "", ""); @@ -35,23 +40,6 @@ public class WebViews { webview.postWebMessage(null, (Uri) InferTaint.inferSecretSource()); } - void callWebviewClientSinks(WebView webview, WebViewClient client) { - String stringSource = (String) InferTaint.inferSecretSource(); - - client.onLoadResource(webview, stringSource); - client.shouldInterceptRequest(webview, stringSource); - client.shouldOverrideUrlLoading(webview, stringSource); // should have 3 reports - } - - void callWebviewChromeClientSinks(WebView webview, WebChromeClient client) { - String stringSource = (String) InferTaint.inferSecretSource(); - - client.onJsAlert(webview, stringSource, "", null); - client.onJsBeforeUnload(webview, stringSource, "", null); - client.onJsConfirm(webview, stringSource, "", null); - client.onJsPrompt(webview, stringSource, "", "", null); // should have 4 reports - } - // make sure all of the rules apply to subclasses as well class MyWebView extends WebView { public MyWebView(Context c) { @@ -59,19 +47,76 @@ public class WebViews { } } + Activity mActivity; + class MyWebViewClient extends WebViewClient { + + @Override + public void onLoadResource(WebView w, String url) { + try { + Intent.parseUri(url, 0); // should report + } catch (URISyntaxException e) { + } + } + + @Override + public WebResourceResponse shouldInterceptRequest(WebView w, WebResourceRequest request) { + mActivity.startActivity(new Intent("action", request.getUrl())); // should report + return null; + } + + @Override + public boolean shouldOverrideUrlLoading(WebView w, String url) { + try { + Intent.parseUri(url, 0); // should report + } catch (URISyntaxException e) { + } + return false; + } } class MyWebChromeClient extends WebChromeClient { - } - void callWebviewSubclassSinks( - MyWebView webview, MyWebViewClient client, MyWebChromeClient chromeClient) { + @Override + public boolean onJsAlert(WebView w, String url, String message, JsResult result) { + try { + Intent.parseUri(url, 0); // should report + } catch (URISyntaxException e) { + } + return false; + } + + @Override + public boolean onJsBeforeUnload(WebView w, String url, String m, JsResult result) { + try { + Intent.parseUri(url, 0); // should report + } catch (URISyntaxException e) { + } + return false; + } + + @Override + public boolean onJsConfirm(WebView w, String url, String m, JsResult result) { + try { + Intent.parseUri(url, 0); // should report + } catch (URISyntaxException e) { + } + return false; + } + + @Override + public boolean onJsPrompt(WebView w, String url, String m, String s, JsPromptResult result) { + try { + Intent.parseUri(url, 0); // should report + } catch (URISyntaxException e) { + } + return false; + } + } + void callWebviewSubclassSink(MyWebView webview) { String stringSource = (String) InferTaint.inferSecretSource(); webview.evaluateJavascript(stringSource, null); - client.onLoadResource(webview, stringSource); - chromeClient.onJsAlert(webview, stringSource, "", null); // should have 3 reports } class JsObject { diff --git a/infer/tests/codetoanalyze/java/quandary/issues.exp b/infer/tests/codetoanalyze/java/quandary/issues.exp index 59d815fe0..1db5d2bbc 100644 --- a/infer/tests/codetoanalyze/java/quandary/issues.exp +++ b/infer/tests/codetoanalyze/java/quandary/issues.exp @@ -182,19 +182,16 @@ codetoanalyze/java/quandary/UnknownCode.java, void UnknownCode.propagateEmptyBad codetoanalyze/java/quandary/UnknownCode.java, void UnknownCode.propagateViaUnknownAbstractCodeBad(), 3, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),call to void InferTaint.inferSensitiveSink(Object)] codetoanalyze/java/quandary/UnknownCode.java, void UnknownCode.propagateViaUnknownConstructorBad(), 4, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),call to void InferTaint.inferSensitiveSink(Object)] codetoanalyze/java/quandary/UnknownCode.java, void UnknownCode.propagateViaUnknownNativeCodeBad(), 3, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),call to void InferTaint.inferSensitiveSink(Object)] -codetoanalyze/java/quandary/WebViews.java, void WebViews.callWebviewChromeClientSinks(WebView,WebChromeClient), 3, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),call to boolean WebChromeClient.onJsAlert(WebView,String,String,JsResult)] -codetoanalyze/java/quandary/WebViews.java, void WebViews.callWebviewChromeClientSinks(WebView,WebChromeClient), 4, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),call to boolean WebChromeClient.onJsBeforeUnload(WebView,String,String,JsResult)] -codetoanalyze/java/quandary/WebViews.java, void WebViews.callWebviewChromeClientSinks(WebView,WebChromeClient), 5, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),call to boolean WebChromeClient.onJsConfirm(WebView,String,String,JsResult)] -codetoanalyze/java/quandary/WebViews.java, void WebViews.callWebviewChromeClientSinks(WebView,WebChromeClient), 6, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),call to boolean WebChromeClient.onJsPrompt(WebView,String,String,String,JsPromptResult)] -codetoanalyze/java/quandary/WebViews.java, void WebViews.callWebviewClientSinks(WebView,WebViewClient), 3, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),call to void WebViewClient.onLoadResource(WebView,String)] -codetoanalyze/java/quandary/WebViews.java, void WebViews.callWebviewClientSinks(WebView,WebViewClient), 4, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),call to WebResourceResponse WebViewClient.shouldInterceptRequest(WebView,String)] -codetoanalyze/java/quandary/WebViews.java, void WebViews.callWebviewClientSinks(WebView,WebViewClient), 5, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),call to boolean WebViewClient.shouldOverrideUrlLoading(WebView,String)] -codetoanalyze/java/quandary/WebViews.java, void WebViews.callWebviewSinks(WebView), 3, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),call to void WebView.addJavascriptInterface(Object,String)] -codetoanalyze/java/quandary/WebViews.java, void WebViews.callWebviewSinks(WebView), 4, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),call to void WebView.evaluateJavascript(String,ValueCallback)] -codetoanalyze/java/quandary/WebViews.java, void WebViews.callWebviewSinks(WebView), 5, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),call to void WebView.loadData(String,String,String)] -codetoanalyze/java/quandary/WebViews.java, void WebViews.callWebviewSinks(WebView), 6, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),call to void WebView.loadDataWithBaseURL(String,String,String,String,String)] -codetoanalyze/java/quandary/WebViews.java, void WebViews.callWebviewSinks(WebView), 7, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),call to void WebView.loadUrl(String)] -codetoanalyze/java/quandary/WebViews.java, void WebViews.callWebviewSinks(WebView), 8, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),call to void WebView.postWebMessage(WebMessage,Uri)] -codetoanalyze/java/quandary/WebViews.java, void WebViews.callWebviewSubclassSinks(WebViews$MyWebView,WebViews$MyWebViewClient,WebViews$MyWebChromeClient), 4, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),call to void WebView.evaluateJavascript(String,ValueCallback)] -codetoanalyze/java/quandary/WebViews.java, void WebViews.callWebviewSubclassSinks(WebViews$MyWebView,WebViews$MyWebViewClient,WebViews$MyWebChromeClient), 5, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),call to void WebViewClient.onLoadResource(WebView,String)] -codetoanalyze/java/quandary/WebViews.java, void WebViews.callWebviewSubclassSinks(WebViews$MyWebView,WebViews$MyWebViewClient,WebViews$MyWebChromeClient), 6, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),call to boolean WebChromeClient.onJsAlert(WebView,String,String,JsResult)] +codetoanalyze/java/quandary/WebViews.java, WebResourceResponse WebViews$MyWebViewClient.shouldInterceptRequest(WebView,WebResourceRequest), 1, QUANDARY_TAINT_ERROR, [return from WebResourceResponse WebViews$MyWebViewClient.shouldInterceptRequest(WebView,WebResourceRequest),call to void Activity.startActivity(Intent)] +codetoanalyze/java/quandary/WebViews.java, boolean WebViews$MyWebChromeClient.onJsAlert(WebView,String,String,JsResult), 2, QUANDARY_TAINT_ERROR, [return from boolean WebViews$MyWebChromeClient.onJsAlert(WebView,String,String,JsResult),call to Intent Intent.parseUri(String,int)] +codetoanalyze/java/quandary/WebViews.java, boolean WebViews$MyWebChromeClient.onJsBeforeUnload(WebView,String,String,JsResult), 2, QUANDARY_TAINT_ERROR, [return from boolean WebViews$MyWebChromeClient.onJsBeforeUnload(WebView,String,String,JsResult),call to Intent Intent.parseUri(String,int)] +codetoanalyze/java/quandary/WebViews.java, boolean WebViews$MyWebChromeClient.onJsConfirm(WebView,String,String,JsResult), 2, QUANDARY_TAINT_ERROR, [return from boolean WebViews$MyWebChromeClient.onJsConfirm(WebView,String,String,JsResult),call to Intent Intent.parseUri(String,int)] +codetoanalyze/java/quandary/WebViews.java, boolean WebViews$MyWebChromeClient.onJsPrompt(WebView,String,String,String,JsPromptResult), 2, QUANDARY_TAINT_ERROR, [return from boolean WebViews$MyWebChromeClient.onJsPrompt(WebView,String,String,String,JsPromptResult),call to Intent Intent.parseUri(String,int)] +codetoanalyze/java/quandary/WebViews.java, boolean WebViews$MyWebViewClient.shouldOverrideUrlLoading(WebView,String), 2, QUANDARY_TAINT_ERROR, [return from boolean WebViews$MyWebViewClient.shouldOverrideUrlLoading(WebView,String),call to Intent Intent.parseUri(String,int)] +codetoanalyze/java/quandary/WebViews.java, void WebViews$MyWebViewClient.onLoadResource(WebView,String), 2, QUANDARY_TAINT_ERROR, [return from void WebViews$MyWebViewClient.onLoadResource(WebView,String),call to Intent Intent.parseUri(String,int)] +codetoanalyze/java/quandary/WebViews.java, void WebViews.callWebviewSinks(WebView), 3, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),call to void WebView.evaluateJavascript(String,ValueCallback)] +codetoanalyze/java/quandary/WebViews.java, void WebViews.callWebviewSinks(WebView), 4, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),call to void WebView.loadData(String,String,String)] +codetoanalyze/java/quandary/WebViews.java, void WebViews.callWebviewSinks(WebView), 5, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),call to void WebView.loadDataWithBaseURL(String,String,String,String,String)] +codetoanalyze/java/quandary/WebViews.java, void WebViews.callWebviewSinks(WebView), 6, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),call to void WebView.loadUrl(String)] +codetoanalyze/java/quandary/WebViews.java, void WebViews.callWebviewSinks(WebView), 7, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),call to void WebView.postWebMessage(WebMessage,Uri)] +codetoanalyze/java/quandary/WebViews.java, void WebViews.callWebviewSubclassSink(WebViews$MyWebView), 2, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),call to void WebView.evaluateJavascript(String,ValueCallback)]