MASTG-DEMO-0037: App Leaking Information about Unclosed SQL Cursor via StrictMode
Content in BETA
This content is in beta and still under active development, so it is subject to change any time (e.g. structure, IDs, content, URLs, etc.).
Send Feedback
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.