MASTG-TEST-0263
android
MASTG-DEMO-0037: App Leaking Information about Unclosed SQL Cursor via StrictMode
Download MASTG-DEMO-0037 APK
Open MASTG-DEMO-0037 Folder
Build MASTG-DEMO-0037 APK
Sample
The snippet below shows sample code that enables a StrictMode
policy to detect leaked (i.e., unclosed) SQLite objects. When such an object is detected, a log message is emitted to the system log.
The snippet then opens an SQL Cursor which remains unclosed, to trigger the policy.
MastgTest.kt 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36 package org . owasp . mastestapp
import android.content.Context
import android.database.sqlite.SQLiteDatabase
import android.os.StrictMode
class MastgTest ( private val context : Context ){
fun mastgTest (): String {
enableStrictMode ()
triggerSqliteCursorLeak ()
System . gc () // Force garbage collection to trigger leak detection
return "SUCCESS!! \n\n SQL Cursor leaked."
}
private fun enableStrictMode () {
StrictMode . setVmPolicy (
StrictMode . VmPolicy . Builder ()
. detectLeakedClosableObjects () // Detect leaked / unclosed SQLite objects
. penaltyLog () // Log violations
. build ()
)
}
private fun triggerSqliteCursorLeak () {
val db : SQLiteDatabase = context . openOrCreateDatabase ( "test.db" , Context . MODE_PRIVATE , null )
db . execSQL ( "CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY, name TEXT)" )
db . execSQL ( "INSERT INTO users (name) VALUES ('Alice'), ('Bob')" )
// Create cursor , and intentionally do not close it
val cursor = db . rawQuery ( "SELECT * FROM users" , null )
}
}
Steps
Install the app on your device.
Open the app and let it execute.
Execute run.sh
which uses Monitoring System Logs to show the system logs created by StrictMode
.
run.sh adb logcat - s StrictMode - d > output . txt
Observation
The system log outputs all detected StrictMode
policy violations.
output.txt 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85 03 - 26 11 : 33 : 23.415 2340 2407 D StrictMode : StrictMode policy violation : android . os . strictmode . LeakedClosableViolation : A resource was acquired at attached stack trace but never released . See java . io . Closeable for information on avoiding resource leaks .
03 - 26 11 : 33 : 23.415 2340 2407 D StrictMode : at android . os . StrictMode $ AndroidCloseGuardReporter . report ( StrictMode . java : 1994 )
03 - 26 11 : 33 : 23.415 2340 2407 D StrictMode : at dalvik . system . CloseGuard . warnIfOpen ( CloseGuard . java : 336 )
03 - 26 11 : 33 : 23.415 2340 2407 D StrictMode : at android . database . AbstractCursor . finalize ( AbstractCursor . java : 531 )
03 - 26 11 : 33 : 23.415 2340 2407 D StrictMode : at android . database . sqlite . SQLiteCursor . finalize ( SQLiteCursor . java : 291 )
03 - 26 11 : 33 : 23.415 2340 2407 D StrictMode : at java . lang . Daemons $ FinalizerDaemon . doFinalize ( Daemons . java : 339 )
03 - 26 11 : 33 : 23.415 2340 2407 D StrictMode : at java . lang . Daemons $ FinalizerDaemon . processReference ( Daemons . java : 324 )
03 - 26 11 : 33 : 23.415 2340 2407 D StrictMode : at java . lang . Daemons $ FinalizerDaemon . runInternal ( Daemons . java : 300 )
03 - 26 11 : 33 : 23.415 2340 2407 D StrictMode : at java . lang . Daemons $ Daemon . run ( Daemons . java : 145 )
03 - 26 11 : 33 : 23.415 2340 2407 D StrictMode : at java . lang . Thread . run ( Thread . java : 1012 )
03 - 26 11 : 33 : 23.415 2340 2407 D StrictMode : Caused by : java . lang . Throwable : Explicit termination method 'AbstractCursor.close' not called
03 - 26 11 : 33 : 23.415 2340 2407 D StrictMode : at dalvik . system . CloseGuard . openWithCallSite ( CloseGuard . java : 288 )
03 - 26 11 : 33 : 23.415 2340 2407 D StrictMode : at dalvik . system . CloseGuard . open ( CloseGuard . java : 257 )
03 - 26 11 : 33 : 23.415 2340 2407 D StrictMode : at android . database . AbstractCursor .< init > ( AbstractCursor . java : 227 )
03 - 26 11 : 33 : 23.415 2340 2407 D StrictMode : at android . database . AbstractWindowedCursor .< init > ( AbstractWindowedCursor . java : 39 )
03 - 26 11 : 33 : 23.415 2340 2407 D StrictMode : at android . database . sqlite . SQLiteCursor .< init > ( SQLiteCursor . java : 98 )
03 - 26 11 : 33 : 23.415 2340 2407 D StrictMode : at android . database . sqlite . SQLiteDirectCursorDriver . query ( SQLiteDirectCursorDriver . java : 52 )
03 - 26 11 : 33 : 23.415 2340 2407 D StrictMode : at android . database . sqlite . SQLiteDatabase . rawQueryWithFactory ( SQLiteDatabase . java : 1714 )
03 - 26 11 : 33 : 23.415 2340 2407 D StrictMode : at android . database . sqlite . SQLiteDatabase . rawQuery ( SQLiteDatabase . java : 1653 )
03 - 26 11 : 33 : 23.415 2340 2407 D StrictMode : at org . owasp . mastestapp . MastgTest . triggerSqliteCursorLeak ( MastgTest . kt : 35 )
03 - 26 11 : 33 : 23.415 2340 2407 D StrictMode : at org . owasp . mastestapp . MastgTest . mastgTest ( MastgTest . kt : 12 )
03 - 26 11 : 33 : 23.415 2340 2407 D StrictMode : at org . owasp . mastestapp . MainActivityKt $ MyScreenContent $ 1 $ 1 $ 1. invoke ( MainActivity . kt : 117 )
03 - 26 11 : 33 : 23.415 2340 2407 D StrictMode : at org . owasp . mastestapp . MainActivityKt $ MyScreenContent $ 1 $ 1 $ 1. invoke ( MainActivity . kt : 115 )
03 - 26 11 : 33 : 23.415 2340 2407 D StrictMode : at androidx . compose . foundation . ClickablePointerInputNode $ pointerInput $ 3. invoke - k - 4 lQ0M ( Clickable . kt : 987 )
03 - 26 11 : 33 : 23.415 2340 2407 D StrictMode : at androidx . compose . foundation . ClickablePointerInputNode $ pointerInput $ 3. invoke ( Clickable . kt : 981 )
03 - 26 11 : 33 : 23.415 2340 2407 D StrictMode : at androidx . compose . foundation . gestures . TapGestureDetectorKt $ detectTapAndPress $ 2 $ 1. invokeSuspend ( TapGestureDetector . kt : 255 )
03 - 26 11 : 33 : 23.415 2340 2407 D StrictMode : at kotlin . coroutines . jvm . internal . BaseContinuationImpl . resumeWith ( ContinuationImpl . kt : 33 )
03 - 26 11 : 33 : 23.415 2340 2407 D StrictMode : at kotlinx . coroutines . DispatchedTaskKt . resume ( DispatchedTask . kt : 177 )
03 - 26 11 : 33 : 23.415 2340 2407 D StrictMode : at kotlinx . coroutines . DispatchedTaskKt . dispatch ( DispatchedTask . kt : 166 )
03 - 26 11 : 33 : 23.415 2340 2407 D StrictMode : at kotlinx . coroutines . CancellableContinuationImpl . dispatchResume ( CancellableContinuationImpl . kt : 474 )
03 - 26 11 : 33 : 23.415 2340 2407 D StrictMode : at kotlinx . coroutines . CancellableContinuationImpl . resumeImpl ( CancellableContinuationImpl . kt : 508 )
03 - 26 11 : 33 : 23.415 2340 2407 D StrictMode : at kotlinx . coroutines . CancellableContinuationImpl . resumeImpl $ default ( CancellableContinuationImpl . kt : 497 )
03 - 26 11 : 33 : 23.415 2340 2407 D StrictMode : at kotlinx . coroutines . CancellableContinuationImpl . resumeWith ( CancellableContinuationImpl . kt : 368 )
03 - 26 11 : 33 : 23.415 2340 2407 D StrictMode : at androidx . compose . ui . input . pointer . SuspendingPointerInputModifierNodeImpl $ PointerEventHandlerCoroutine . offerPointerEvent ( SuspendingPointerInputFilter . kt : 665 )
03 - 26 11 : 33 : 23.415 2340 2407 D StrictMode : at androidx . compose . ui . input . pointer . SuspendingPointerInputModifierNodeImpl . dispatchPointerEvent ( SuspendingPointerInputFilter . kt : 544 )
03 - 26 11 : 33 : 23.415 2340 2407 D StrictMode : at androidx . compose . ui . input . pointer . SuspendingPointerInputModifierNodeImpl . onPointerEvent - H0pRuoY ( SuspendingPointerInputFilter . kt : 566 )
03 - 26 11 : 33 : 23.415 2340 2407 D StrictMode : at androidx . compose . foundation . AbstractClickablePointerInputNode . onPointerEvent - H0pRuoY ( Clickable . kt : 947 )
03 - 26 11 : 33 : 23.415 2340 2407 D StrictMode : at androidx . compose . foundation . AbstractClickableNode . onPointerEvent - H0pRuoY ( Clickable . kt : 795 )
03 - 26 11 : 33 : 23.415 2340 2407 D StrictMode : at androidx . compose . ui . input . pointer . Node . dispatchMainEventPass ( HitPathTracker . kt : 317 )
03 - 26 11 : 33 : 23.415 2340 2407 D StrictMode : at androidx . compose . ui . input . pointer . Node . dispatchMainEventPass ( HitPathTracker . kt : 303 )
03 - 26 11 : 33 : 23.415 2340 2407 D StrictMode : at androidx . compose . ui . input . pointer . NodeParent . dispatchMainEventPass ( HitPathTracker . kt : 185 )
03 - 26 11 : 33 : 23.415 2340 2407 D StrictMode : at androidx . compose . ui . input . pointer . HitPathTracker . dispatchChanges ( HitPathTracker . kt : 104 )
03 - 26 11 : 33 : 23.415 2340 2407 D StrictMode : at androidx . compose . ui . input . pointer . PointerInputEventProcessor . process - BIzXfog ( PointerInputEventProcessor . kt : 113 )
03 - 26 11 : 33 : 23.415 2340 2407 D StrictMode : at androidx . compose . ui . platform . AndroidComposeView . sendMotionEvent - 8 iAsVTc ( AndroidComposeView . android . kt : 1576 )
03 - 26 11 : 33 : 23.415 2340 2407 D StrictMode : at androidx . compose . ui . platform . AndroidComposeView . handleMotionEvent - 8 iAsVTc ( AndroidComposeView . android . kt : 1527 )
03 - 26 11 : 33 : 23.415 2340 2407 D StrictMode : at androidx . compose . ui . platform . AndroidComposeView . dispatchTouchEvent ( AndroidComposeView . android . kt : 1466 )
03 - 26 11 : 33 : 23.415 2340 2407 D StrictMode : at android . view . ViewGroup . dispatchTransformedTouchEvent ( ViewGroup . java : 3120 )
03 - 26 11 : 33 : 23.415 2340 2407 D StrictMode : at android . view . ViewGroup . dispatchTouchEvent ( ViewGroup . java : 2801 )
03 - 26 11 : 33 : 23.415 2340 2407 D StrictMode : at android . view . ViewGroup . dispatchTransformedTouchEvent ( ViewGroup . java : 3120 )
03 - 26 11 : 33 : 23.415 2340 2407 D StrictMode : at android . view . ViewGroup . dispatchTouchEvent ( ViewGroup . java : 2801 )
03 - 26 11 : 33 : 23.415 2340 2407 D StrictMode : at android . view . ViewGroup . dispatchTransformedTouchEvent ( ViewGroup . java : 3120 )
03 - 26 11 : 33 : 23.415 2340 2407 D StrictMode : at android . view . ViewGroup . dispatchTouchEvent ( ViewGroup . java : 2801 )
03 - 26 11 : 33 : 23.415 2340 2407 D StrictMode : at android . view . ViewGroup . dispatchTransformedTouchEvent ( ViewGroup . java : 3120 )
03 - 26 11 : 33 : 23.415 2340 2407 D StrictMode : at android . view . ViewGroup . dispatchTouchEvent ( ViewGroup . java : 2801 )
03 - 26 11 : 33 : 23.415 2340 2407 D StrictMode : at com . android . internal . policy . DecorView . superDispatchTouchEvent ( DecorView . java : 490 )
03 - 26 11 : 33 : 23.415 2340 2407 D StrictMode : at com . android . internal . policy . PhoneWindow . superDispatchTouchEvent ( PhoneWindow . java : 1904 )
03 - 26 11 : 33 : 23.415 2340 2407 D StrictMode : at android . app . Activity . dispatchTouchEvent ( Activity . java : 4377 )
03 - 26 11 : 33 : 23.415 2340 2407 D StrictMode : at com . android . internal . policy . DecorView . dispatchTouchEvent ( DecorView . java : 448 )
03 - 26 11 : 33 : 23.415 2340 2407 D StrictMode : at android . view . View . dispatchPointerEvent ( View . java : 15919 )
03 - 26 11 : 33 : 23.415 2340 2407 D StrictMode : at android . view . ViewRootImpl $ ViewPostImeInputStage . processPointerEvent ( ViewRootImpl . java : 7021 )
03 - 26 11 : 33 : 23.415 2340 2407 D StrictMode : at android . view . ViewRootImpl $ ViewPostImeInputStage . onProcess ( ViewRootImpl . java : 6815 )
03 - 26 11 : 33 : 23.415 2340 2407 D StrictMode : at android . view . ViewRootImpl $ InputStage . deliver ( ViewRootImpl . java : 6229 )
03 - 26 11 : 33 : 23.415 2340 2407 D StrictMode : at android . view . ViewRootImpl $ InputStage . onDeliverToNext ( ViewRootImpl . java : 6286 )
03 - 26 11 : 33 : 23.415 2340 2407 D StrictMode : at android . view . ViewRootImpl $ InputStage . forward ( ViewRootImpl . java : 6252 )
03 - 26 11 : 33 : 23.415 2340 2407 D StrictMode : at android . view . ViewRootImpl $ AsyncInputStage . forward ( ViewRootImpl . java : 6417 )
03 - 26 11 : 33 : 23.415 2340 2407 D StrictMode : at android . view . ViewRootImpl $ InputStage . apply ( ViewRootImpl . java : 6260 )
03 - 26 11 : 33 : 23.415 2340 2407 D StrictMode : at android . view . ViewRootImpl $ AsyncInputStage . apply ( ViewRootImpl . java : 6474 )
03 - 26 11 : 33 : 23.415 2340 2407 D StrictMode : at android . view . ViewRootImpl $ InputStage . deliver ( ViewRootImpl . java : 6233 )
03 - 26 11 : 33 : 23.415 2340 2407 D StrictMode : at android . view . ViewRootImpl $ InputStage . onDeliverToNext ( ViewRootImpl . java : 6286 )
03 - 26 11 : 33 : 23.415 2340 2407 D StrictMode : at android . view . ViewRootImpl $ InputStage . forward ( ViewRootImpl . java : 6252 )
03 - 26 11 : 33 : 23.415 2340 2407 D StrictMode : at android . view . ViewRootImpl $ InputStage . apply ( ViewRootImpl . java : 6260 )
03 - 26 11 : 33 : 23.415 2340 2407 D StrictMode : at android . view . ViewRootImpl $ InputStage . deliver ( ViewRootImpl . java : 6233 )
03 - 26 11 : 33 : 23.415 2340 2407 D StrictMode : at android . view . ViewRootImpl . deliverInputEvent ( ViewRootImpl . java : 9211 )
03 - 26 11 : 33 : 23.415 2340 2407 D StrictMode : at android . view . ViewRootImpl . doProcessInputEvents ( ViewRootImpl . java : 9162 )
03 - 26 11 : 33 : 23.415 2340 2407 D StrictMode : at android . view . ViewRootImpl . enqueueInputEvent ( ViewRootImpl . java : 9131 )
03 - 26 11 : 33 : 23.415 2340 2407 D StrictMode : at android . view . ViewRootImpl $ WindowInputEventReceiver . onInputEvent ( ViewRootImpl . java : 9337 )
03 - 26 11 : 33 : 23.415 2340 2407 D StrictMode : at android . view . InputEventReceiver . dispatchInputEvent ( InputEventReceiver . java : 267 )
03 - 26 11 : 33 : 23.415 2340 2407 D StrictMode : at android . os . MessageQueue . nativePollOnce ( Native Method )
03 - 26 11 : 33 : 23.415 2340 2407 D StrictMode : at android . os . MessageQueue . next ( MessageQueue . java : 335 )
03 - 26 11 : 33 : 23.415 2340 2407 D StrictMode : at android . os . Looper . loopOnce ( Looper . java : 162 )
03 - 26 11 : 33 : 23.415 2340 2407 D StrictMode : at android . os . Looper . loop ( Looper . java : 294 )
03 - 26 11 : 33 : 23.415 2340 2407 D StrictMode : at android . app . ActivityThread . main ( ActivityThread . java : 8177 )
03 - 26 11 : 33 : 23.415 2340 2407 D StrictMode : at java . lang . reflect . Method . invoke ( Native Method )
03 - 26 11 : 33 : 23.415 2340 2407 D StrictMode : at com . android . internal . os . RuntimeInit $ MethodAndArgsCaller . run ( RuntimeInit . java : 552 )
03 - 26 11 : 33 : 23.415 2340 2407 D StrictMode : at com . android . internal . os . ZygoteInit . main ( ZygoteInit . java : 971 )
Evaluation
The test fails because StrictMode
is enabled, as we can see from the system log output which shows that there is a location (MastgTest.kt:35
) where an SQL cursor is not closed properly.
Note: The reported cursor not being closed is a different issue outside the scope of this demo.