【问题标题】:Javascript infinite recursive function crashes Chromium 50 ARM64 lib on Android 10Javascript 无限递归函数在 Android 10 上崩溃 Chromium 50 ARM64 lib
【发布时间】:2023-12-16 02:31:01
【问题描述】:

我的 Android 应用使用基于 Chromium 50(V8 JavaScript 引擎 5.0)的类似控件的 web 视图。由于各种原因,不能使用系统 WebView 或更新的 Chromium 版本。

我在 Android 10 和 arm64 版本的二进制文件上收到了很多 Fatal signal 11 (SIGSEGV), code 2 (SEGV_ACCERR) 崩溃。与旧 Android 版本相同的二进制文件以及与 Android 10 的 32 位版本的二进制文件没有问题。

这是一个包含无限递归函数的示例代码,它会崩溃: webView.evaluateJavascript("(function a(i) { a(i++); })()", null);

来自 Android Studio 调试器的堆栈跟踪:

art_sigsegv_fault 0x000000753da02e9c
art::FaultManager::HandleFault(int, siginfo*, void*) 0x000000753da033a4
___lldb_unnamed_symbol24$$app_process64 0x0000005ca3207da8
<unknown> 0x00000075c3f888c0
<unknown> 0x00000074784191e8
<unknown> 0x00000074784191e8
<unknown> 0x00000074784191e8
<unknown> 0x00000074784191e8
<unknown> 0x00000074784191e8
............... the same line 15560 times
<unknown> 0x000000747830be94
<unknown> 0x000000747841937c
<unknown> 0x0000007478339a28
<unknown> 0x000000747831fe30

欢迎提出如何避免这些崩溃的任何想法。

【问题讨论】:

    标签: crash chromium v8 android-10.0 javascript-debugger


    【解决方案1】:

    V8 开发人员在这里。您提到的链接讨论了 system 库。我不知道为什么 V8 会尝试读取系统库。你确定这是怎么回事?您可以运行 Debug 构建并获得堆栈跟踪吗?如果没有进一步的数据,我会怀疑还有其他原因正在发生并导致这些崩溃。

    FWIW:

    --untrusted-code-mitigations 导致(优化)编译器发出(部分)缓解最近发现的“幽灵”CPU 安全漏洞的代码序列。这与 Android 10 的兼容性完全无关。

    --jitless 在足够新的 V8 版本中关闭所有即时代码生成(当然,性能成本很高)。这也与 Android 系统二进制文件的仅执行内存无关。

    更新问题后更新,并在 cmets 中讨论:

    根据堆栈跟踪,似乎进程在堆栈空间用完时崩溃。 V8 应该检测到这种情况并在此之前抛出RangeError;实现这一点的机制是通过估计一个进程可以使用多少堆栈空间来实现的。显然,对于(至少)在 Android 10 上运行的应用程序的特定组合,剩余堆栈空间比 V8 v5.0 预期的要少。一种解决方法是使用标志--stack-size=800 运行,或者编辑src/globals.h 中的V8_DEFAULT_STACK_SIZE_KB 常量。

    给其他读者的提示:将--stack-size 设置为一个巨大的值不会神奇地给你更深的递归限制;相反,当超出操作系统定义的堆栈限制时,它会让您的进程崩溃,而不是抛出RangeError。将--stack-size 设置得太低意味着JavaScript 代码在抛出RangeError 之前将无法进行很多深度函数调用(或者,极端情况下,根本不运行)。通常建议不要使用此标志,除非您遇到像这里这样的特定问题,在其中进行小的调整会有所帮助。

    【讨论】:

    • 你好 jmrk!非常感谢您的评论和有关标志的信息。我猜测这些崩溃是由 XOM 引起的,因为它们只出现在 Android 10 和 arm64 版本的二进制文件中。但似乎你是对的,它与 XOM 无关,因为这里有一个包含无限递归函数的示例代码,它会崩溃: webView.evaluateJavascript("(function a(i) { a(i++); })()", null );与旧 Android 版本相同的二进制文件以及与 Android 10 相同的 32 位版本的二进制文件没有问题。
    • 当无限递归导致崩溃时,总是有没有被正确捕获的堆栈溢出的味道。很可能是旧 V8 版本存在错误,或者可能只是与较新的 Android 不兼容;例如,如果操作系统为用户空间进程提供的堆栈较少,则需要调整 V8 内部对 JS 函数使用多少堆栈的限制。 (这只是一个疯狂的猜测;我仍然建议在调试器中运行并获取回溯以弄清楚发生了什么。)
    • 我对我的 webview 库进行了调试构建,但未剥离的库版本为 3.2 GB。这就是我使用剥离的调试版本的原因。为了获得回溯,我从手机中获取了 tombstone 文件,使用以下命令对其进行符号化:third_party/android_platform/development/scripts/stack --arch=arm64 --output-directory out/Debug tombstone > tombstone.txt。您可以在我的问题中找到它的链接。它似乎没有提供适当的回溯。我会尝试其他方法。
    • 我不知道为什么该输出中有这么多堆栈跟踪,也不知道如何确定哪个是相关的。如果是第一个,那么它看起来像是 ART 中某处的检查失败。故障地址 0x7495cdfff8 看起来像是某些东西可能错误地读取了前一页内存的末尾。输出中根本没有提到“v8”,所以我没有看到任何证据表明 V8 涉及任何问题,因此我认为我不能在这里提供进一步的帮助,抱歉。
    • 堆栈跟踪之所以如此之多,是因为它们适用于所有线程。我们对名为 Chrome_InProcRe 的第一个感兴趣,但如您所见,它只有一个行堆栈跟踪。我正在尝试编译未剥离的调试二进制文件以获得更多信息的堆栈跟踪,但到目前为止没有成功。当应用程序崩溃时,我从 Android Studio 调试器发布了堆栈跟踪。