Skip to content

Commit e179126

Browse files
authored
Merge pull request #9129 from atorralba/atorralba/get-underlying-expr
Java: Add Expr::getUnderlyingExpr predicate
2 parents f2670bc + 9c941dc commit e179126

File tree

9 files changed

+57
-4
lines changed

9 files changed

+57
-4
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
category: feature
3+
---
4+
* The QL predicate `Expr::getUnderlyingExpr` has been added. It can be used to look through casts and not-null expressions and obtain the underlying expression to which they apply.

java/ql/lib/semmle/code/java/Expr.qll

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,18 @@ class Expr extends ExprParent, @expr {
100100

101101
/** Holds if this expression is parenthesized. */
102102
predicate isParenthesized() { isParenthesized(this, _) }
103+
104+
/**
105+
* Gets the underlying expression looking through casts and not-nulls, if any.
106+
* Otherwise just gets this expression.
107+
*/
108+
Expr getUnderlyingExpr() {
109+
if this instanceof CastingExpr or this instanceof NotNullExpr
110+
then
111+
result = this.(CastingExpr).getExpr().getUnderlyingExpr() or
112+
result = this.(NotNullExpr).getExpr().getUnderlyingExpr()
113+
else result = this
114+
}
103115
}
104116

105117
/**

java/ql/lib/semmle/code/java/security/CleartextStorageSharedPrefsQuery.qll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ private predicate sharedPreferencesInput(DataFlow::Node editor, Expr input) {
5151
exists(MethodAccess m |
5252
m.getMethod() instanceof PutSharedPreferenceMethod and
5353
input = m.getArgument(1) and
54-
editor.asExpr() = m.getQualifier()
54+
editor.asExpr() = m.getQualifier().getUnderlyingExpr()
5555
)
5656
}
5757

@@ -61,7 +61,7 @@ private predicate sharedPreferencesInput(DataFlow::Node editor, Expr input) {
6161
*/
6262
private predicate sharedPreferencesStore(DataFlow::Node editor, MethodAccess m) {
6363
m.getMethod() instanceof StoreSharedPreferenceMethod and
64-
editor.asExpr() = m.getQualifier()
64+
editor.asExpr() = m.getQualifier().getUnderlyingExpr()
6565
}
6666

6767
/** Flow from `SharedPreferences.Editor` to either a setter or a store method. */

java/ql/lib/semmle/code/java/security/UnsafeAndroidAccess.qll

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,15 +75,18 @@ private predicate webViewLoadUrl(Argument urlArg, WebViewRef webview) {
7575
loadUrl.getArgument(0) = urlArg and
7676
loadUrl.getMethod() instanceof WebViewLoadUrlMethod
7777
|
78+
webview.getAnAccess() = DataFlow::exprNode(loadUrl.getQualifier().getUnderlyingExpr())
79+
or
7880
webview.getAnAccess() = DataFlow::getInstanceArgument(loadUrl)
7981
or
8082
// `webview` is received as a parameter of an event method in a custom `WebViewClient`,
8183
// so we need to find `WebViews` that use that specific `WebViewClient`.
8284
exists(WebViewClientEventMethod eventMethod, MethodAccess setWebClient |
8385
setWebClient.getMethod() instanceof WebViewSetWebViewClientMethod and
8486
setWebClient.getArgument(0).getType() = eventMethod.getDeclaringType() and
85-
loadUrl.getQualifier() = eventMethod.getWebViewParameter().getAnAccess()
87+
loadUrl.getQualifier().getUnderlyingExpr() = eventMethod.getWebViewParameter().getAnAccess()
8688
|
89+
webview.getAnAccess() = DataFlow::exprNode(setWebClient.getQualifier().getUnderlyingExpr()) or
8790
webview.getAnAccess() = DataFlow::getInstanceArgument(setWebClient)
8891
)
8992
)
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import android.app.Activity
2+
import android.content.Context
3+
import android.content.SharedPreferences
4+
5+
class CleartextStorageSharedPrefsTestKt : Activity() {
6+
fun testSetSharedPrefs1(context: Context, name: String, password: String) {
7+
val sharedPrefs = context.getSharedPreferences("user_prefs", Context.MODE_PRIVATE);
8+
sharedPrefs.edit().putString("name", name).apply(); // Safe
9+
sharedPrefs.edit().putString("password", password).apply(); // $ hasCleartextStorageSharedPrefs
10+
}
11+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
// semmle-extractor-options: --javac-args -cp ${testdir}/../../../stubs/google-android-9.0.0
2+
// codeql-extractor-kotlin-options: ${testdir}/../../../stubs/google-android-9.0.0

java/ql/test/query-tests/security/CWE-749/AndroidManifest.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444

4545
<activity android:name=".UnsafeActivity3" android:exported="true" />
4646
<activity android:name=".UnsafeActivity4" android:exported="true" />
47+
<activity android:name=".UnsafeActivityKt" android:exported="true" />
4748

4849
<receiver android:name=".UnsafeAndroidBroadcastReceiver" android:exported="true" />
4950
</application>
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package com.example.app
2+
3+
import android.app.Activity
4+
import android.os.Bundle
5+
import android.webkit.WebSettings
6+
import android.webkit.WebView
7+
import android.webkit.WebViewClient
8+
9+
class UnsafeActivityKt : Activity() {
10+
override fun onCreate(savedInstanceState : Bundle) {
11+
12+
val wv = findViewById<WebView>(-1)
13+
// Implicit not-nulls happening here
14+
wv.settings.setJavaScriptEnabled(true)
15+
wv.settings.setAllowFileAccessFromFileURLs(true)
16+
17+
val thisUrl : String = intent.extras.getString("url")
18+
wv.loadUrl(thisUrl) // $ hasUnsafeAndroidAccess
19+
}
20+
}
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../stubs/android
1+
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../stubs/google-android-9.0.0
2+
//codeql-extractor-kotlin-options: ${testdir}/../../../stubs/google-android-9.0.0

0 commit comments

Comments
 (0)