Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

A SIGSEGV (SEGV_MAPERR) crash occurs when calling the trim() method #1190

Closed
fzzwork opened this issue Oct 28, 2023 · 3 comments
Closed

A SIGSEGV (SEGV_MAPERR) crash occurs when calling the trim() method #1190

fzzwork opened this issue Oct 28, 2023 · 3 comments

Comments

@fzzwork
Copy link

fzzwork commented Oct 28, 2023

The language of MMKV

Java

The version of MMKV

v1.2.12

The platform of MMKV

Android

The installation of MMKV

Maven

What's the issue?

A SIGSEGV (SEGV_MAPERR) null pointer exception occurs when the trim() method is called.

CRASHSTACK

#17600 pool-5-thread-3
SIGSEGV(SEGV_MAPERR)
#00 pc 000000000002872c writeActualSize (/data/orange-ci/workspace/Core/MMKV_IO.cpp:418 [Inline: oldStyleWriteActualSize]) []
#1 pc 000000000002ac0c clearAll (/data/orange-ci/workspace/Core/MMKV_IO.cpp:1065) []
#2 pc 000000000002b26c trim (/data/orange-ci/workspace/Core/MMKV_IO.cpp:1013) []
#3 pc 00000000006eee7c /data/app/com.xxx.xxx-ReMjA1XjQbGH_0g4uB9PUg==/oat/arm64/base.odex [::00000000000000000000000000000000]
java:
com.xxx.sdk.xxx.void trim()(TabStorageImpl.java:131)


Crash type: 'native'
Start time: '2023-10-28T11:44:54.793+0800'
Crash time: '2023-10-28T11:44:57.822+0800'
App version: '8.9.85.4766'
Rooted: 'No'
API level: '27'
Build fingerprint: 'Xiaomi/clover/clover:8.1.0/OPM1.171019.019/V10.3.2.0.ODJCNXM:user/release-keys'
ABI: 'arm64'
pid: 16937, tid: 17600, name: pool-5-thread-3 >>> com.xxx.xxx <<<
signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x0
x0 0000007a3e838420 x1 0000000000000000 x2 0000000000000000 x3 0000007a44bd02b8
x4 0000000000000001 x5 0000007a4e4c9324 x6 0000007afbd2d000 x7 0000000001a509c6
x8 0000000000000000 x9 0000000000000002 x10 0000000000000001 x11 0000000000000000
x12 0000007afb61458c x13 0000007afb6145f8 x14 0000007afb61457c x15 0000007afb61457c
x16 0000007afb6132c8 x17 0000007afb5b0c48 x18 0000000000000008 x19 0000007a3e98c160
x20 0000007a3e838420 x21 0000007a44bd2588 x22 0000007a3e9702a0 x23 0000007a3e838438
x24 0000000000000004 x25 0000007a3e838438 x26 0000007a6943a8a0 x27 0000000000000001
x28 0000000000000000 x29 0000007a44bd0300
sp 0000007a44bd02a0 lr 0000007a4476cc10 pc 0000007a4476a72c
backtrace:
#00 pc 000000000002872c /data/app/com.xxx.xxx-ReMjA1XjQbGH_0g4uB9PUg==/lib/arm64/libmmkv.so
#1 pc 000000000002ac0c /data/app/com.xxx.xxx-ReMjA1XjQbGH_0g4uB9PUg==/lib/arm64/libmmkv.so
#2 pc 000000000002b26c /data/app/com.xxx.xxx-ReMjA1XjQbGH_0g4uB9PUg==/lib/arm64/libmmkv.so
#3 pc 00000000006eee7c /data/app/com.xxx.xxx-ReMjA1XjQbGH_0g4uB9PUg==/oat/arm64/base.odex

MMKV log

image

Root Cause Analysis

The issue arises from the failure to open the file corresponding to the MMKV instance, resulting in a memory mapping address of 0. When the trim function is invoked, there's no validation check for the pointer's validity. It directly copies the actualSize to the pointer location, leading to a null pointer exception. The call chain is as follows: trim() -> clearAll() -> writeActualSize() -> oldStyleWriteActualSize() -> memcpy.

Why did the file fail to open? The error message from the File::open() function is: 2 (No such file or directory). I've conducted the following analysis:

Checking earlier logs, other MMKV files in the same directory can be opened normally, even the meta file corresponding to the problematic MMKV file can be opened. So, it's definitely not because the rootDir doesn't exist or is invalid.

Could it be that the file couldn't be opened due to a lock by another process? I checked the logs of other processes at the same time, and there were no MMKV operation logs, so this is definitely not the reason.

I also found that the same file read exception occurs after multiple launches by the same user.

I even checked whether the filename is valid. It only contains uppercase and lowercase letters, underscores, and numbers, so there's no issue there.

In conclusion, it should be due to an abnormality in the mobile file system.

原因分析

问题源于无法打开对应MMKV实例的文件,导致内存映射地址为0。当调用trim函数时,没有对指针的有效性进行检查,直接将actualSize复制到指针位置,从而导致空指针异常。调用链如下:trim() -> clearAll() -> writeActualSize() -> oldStyleWriteActualSize() -> memcpy。

文件为什么会打开失败? File::open()函数的错误信息是:2(没有此文件或目录)。我做了以下分析:

检查稍早时间的日志,相同目录下的其他MMKV文件都可以正常打开,甚至问题MMKV文件对应的meta文件也可以正常打开,所以肯定不会是rootDir不存在或者无效。

会不会是其他进程加锁导致了无法打开呢?我检查了同时期其他进程日志,并没有MMKV的操作日志,因此肯定不会是这个原因。

我还发现同个用户在多次启动后,都会出现同个文件的读取异常。

我甚至还检查了文件名是否有效,它只有大小写字母、下划线和数字,所以是没有问题的。

综上,应该是手机文件系统异常导致的。

The suggestion for modification

The trim method should include a validity check for pointers.

修改建议

trim方法应该加上对指针有效性的判断。

@fzzwork
Copy link
Author

fzzwork commented Nov 17, 2023

如下方式可以规避这个crash:
if( mmkv.totalSize()>0 ){ //文件真实大小>0才有必要trim,文件异常时size==0
mmkv.trim();
}

@fzzwork fzzwork closed this as completed Nov 17, 2023
@fzzwork fzzwork reopened this Nov 17, 2023
@lingol
Copy link
Collaborator

lingol commented Nov 20, 2023

The check was added in the dev branch last week d6fb4a9.
A new version will be released soon, hopefully in this week.

@lingol
Copy link
Collaborator

lingol commented Nov 20, 2023

Released with v1.3.2.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants