跳过内容

MASTG-DEMO-0037: 应用通过 StrictMode 泄露未关闭 SQL 游标的信息

下载 MASTG-DEMO-0037 APK 打开 MASTG-DEMO-0037 文件夹 构建 MASTG-DEMO-0037 APK

示例

下面的代码段显示了启用 StrictMode 策略以检测泄漏(即未关闭)的 SQLite 对象的示例代码。 当检测到此类对象时,会将日志消息发送到系统日志。

然后,该代码段打开一个 SQL 游标,该游标保持未关闭状态,以触发该策略。

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\nSQL 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)
    }
}

步骤

  1. 在您的设备上安装该应用程序。
  2. 打开该应用程序并使其执行。
  3. 执行 run.sh,它使用 监控系统日志来显示由 StrictMode 创建的系统日志。
run.sh
1
adb logcat -s StrictMode -d > output.txt

观察

系统日志输出所有检测到的 StrictMode 策略违规行为。

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-4lQ0M(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-8iAsVTc(AndroidComposeView.android.kt:1576)
03-26 11:33:23.415  2340  2407 D StrictMode:    at androidx.compose.ui.platform.AndroidComposeView.handleMotionEvent-8iAsVTc(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)

评估

该测试失败,因为启用了 StrictMode,正如我们从系统日志输出中看到的那样,它显示了存在一个 SQL 游标未正确关闭的位置 (MastgTest.kt:35)。

注意: 报告的游标未关闭是本演示范围之外的另一个问题。