15个句号导致微信 ANR,你中招了吗?附原理解析与解决方案

↑ 点击上方蓝字关注我们,和小伙伴一起聊技术!

近日,有网友表示,在微信中输入“两个数字+15/20 个中文字符的句号”(另一说法是任意数字,任意 15 个标点),部分 Android 手机发送或者收到该消息时,微信就会无响应。

案例 1:

15。。。。。。。。。。。。。。。

案例 2:

15。。。。。。。。。。。。。。。。。。。。

中招的手机

来自知乎的网友@口贝力 实测机型:

  • 小米 6:没问题(但将句号改为 20 个时,手机卡死);

  • 苹果:没问题;

  • mete 9:卡死;

  • 三星:卡死;

  • 360 手机:卡死。

  • 效果图如下:

    15个句号导致微信 ANR,你中招了吗?附原理解析与解决方案

    原理解析

    CSDN 博客专家@三精-大精wing 对于导致微信 ANR 的根本原因进行了解析(以下为授权发布):

    本文目的在于学习研究Android技术,若有侵犯,联系作者将及时删除。

    首先,微信发生ANR以后,会生成traces.txt文件。通过adb 导出

    adb pull /data/anr/traces.txt ~/ 

    其中有这么一段:

    native: #05 pc 0043a419  /data/dalvik-cache/arm/system@framework@boot.oat (Java_java_util_regex_Matcher_setInputImpl__JLjava_lang_String_2II+132)

      at java.util.regex.Matcher.setInputImpl(Native method)

      at java.util.regex.Matcher.resetForInput(Matcher.java:252)

      - locked <0x0ecefa84> (a java.util.regex.Matcher)

      at java.util.regex.Matcher.reset(Matcher.java:208)

      at java.util.regex.Matcher.reset(Matcher.java:177)

      at java.util.regex.Matcher.<init>(Matcher.java:90)

      at java.util.regex.Pattern.matcher(Pattern.java:297)

      at com.tencent.mm.ui.widget.celltextview.g.a.o(SourceFile:95)

      at com.tencent.mm.ui.widget.celltextview.g.a.dc(SourceFile:55)

      at com.tencent.mm.ui.widget.celltextview.f.b.a(SourceFile:76)

      at com.tencent.mm.ui.widget.celltextview.d.a.Cw(SourceFile:466)

      at com.tencent.mm.ui.widget.celltextview.d.a.Cp(SourceFile:92)

      at com.tencent.mm.ui.widget.celltextview.CellTextView.onMeasure(SourceFile:102)

      at android.view.View.measure(View.java:18794)

      at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5951)

      at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1465)

      at android.widget.LinearLayout.measureVertical(LinearLayout.java:748)

      at android.widget.LinearLayout.onMeasure(LinearLayout.java:630)

      at android.view.View.measure(View.java:18794)

    发现是cellTextView锁在了celltextView正则的时候。

    于是乎debug celltextview包的a类的o方法,

    发现一段超级复杂的正则(部分位置打码),所以初步断定为可能是正则时间太长导致。于是写了一个单元测试,来测试该正则是否有问题。

    15个句号导致微信 ANR,你中招了吗?附原理解析与解决方案

    实验发现,这个正则根本不会导致耗时过长,平均耗时0-1ms。

    15个句号导致微信 ANR,你中招了吗?附原理解析与解决方案

    那也就是说明,其实不是这里的原因。

    于是将断点打靠上层,到 com.tencent.mm.ui.widget.celltextview.f.b.a() 方法上

    15个句号导致微信 ANR,你中招了吗?附原理解析与解决方案

    点击放过按钮发现程序无限次落到这个断点上,由此可知,是造成了死循环,无限调用a()方法导致的。

    继续深究,为什么会导致死循环。

    线索1:

    发现a()方法上面有一个判断,会导致跳到cond_6最终会继续跳到goto_4调用a()方法。

    这里有个

    add-int/lit8 v4, v4, -0x1

    其实他相当于

    i-1

    线索2

    观察a()方法后面,有wwk,width等属性调用。

    15个句号导致微信 ANR,你中招了吗?附原理解析与解决方案

    结合线索

    接下来,打开jadx,将class文件反编译为java文件,利用线索快速定位代码。发现这些逻辑代码片段如下:

    15个句号导致微信 ANR,你中招了吗?附原理解析与解决方案

    有了java代码,一下子就和蔼可亲了,来屡一下这段的逻辑。

    可以看到有两个while循环,这里不关心外部while,因为可以看出真正卡死的是在内部while循环。

    内部while循环首先判断了dVar2 是否为空,以及dVar2的text是否为空。

    debug发现,dVar2是一个TextPaint类,用于绘制文本信息(包括字号,大小,颜色,超链接样式之类的)。

    也就是说,只要dVar2不为空,这个循环就不会退出,根据代码可以看出,只有在i4>0的时候才可能把dVar2置为空:

    15个句号导致微信 ANR,你中招了吗?附原理解析与解决方案

    那么i4是什么呢,在红框上面可以看到,i4是a的wwk属性。这个值暂时不知道是什么。

    不过通过debug发现,这个wwk是始终等于0的,也就是不满足while内部的dVar2的置空条件,也就造成了while死循环。

    于是乎,造成anr的最根本原因就是在这个while里了。

    解决方案

    方案一

  • 已发布的此类消息,及时撤回;

  • 过几分钟重新打开微信,删除聊天记录(想要尝试者务必提前备份好聊天记录),重新打开即可。

  • 方案二

  • 作为安卓党,不要损友、损自己,不要轻易去尝试,忍住!!!

  • 方案三

  • 据微信 Android 的小伙伴表示,这个 Bug 已经在 Patch 了。

  • PS:来自腾讯官方的回应

    这两天,有部分用户在使用微信6.5.13 Android 版的过程中,发现输入两个数字加15个句号,就会出现手机卡顿的情况。目前,该问题正在紧急修复中,请各位不要因为好奇随便尝试......

    此问题出现的背景是,微信6.5.13 Android 版对文字排版功能进行了优化,以使会话的长文本在显示对齐时比系统默认排版更为美观。在此过程中,出现了意外BUG,导致了这次显示特定内容时微信卡顿的问题。

    由此给大家带来的不便,我们深感歉意,也感谢大家的支持与谅解。

    温馨再提醒一次,请各位不要乱试bug。

    http://www.zhihu.com/question/65828771/answer/235306912

    15个句号导致微信 ANR,你中招了吗?附原理解析与解决方案

    长按识别二维码享更多精彩