[2538]QQ 发送菜刀加符号导致脏话的真实原因分析

本文详细分析了QQ中菜刀表情结合特定字符导致显示脏话的问题,揭示了其背后的真实原因。QQ使用特定字符组合表示表情和脏话,当两者组合时,由于处理逻辑错误,导致菜刀表情被错误地还原为脏话。作者探讨了输入、发送和接收消息时的处理步骤,并通过代码分析和官方补丁验证了这一问题。此外,还讨论了此bug的触发条件和修复情况。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

来晚了,不过我是带着干货来的。
本回答将为大家解释真实的原因,我认为是比大家的各种猜测要更真实一些的。

0x00 先上结论

0.1 真实原因:

  1. QQ 使用 \u0014 加 1 个字符(该字符为表情序号)表示表情
  2. QQ 使用 \u0011 加 3 个字符表示脏话
  3. 当 \u0014 与 \u0011 再与别的 3 个字符组合到一起,就出现了问题,虽然输入的是表情,却被处理为脏话
  4. 而 \u0014\u0011 表示的表情为第 0x11 个,即第 17 个表情

而第 17 个表情,它就是天选之表情,脏话 bug 幕后元凶,知乎话题缔造者,程序猿背锅原因!
菜刀!!!

表情序号部分相关源码
com.tencent.mobileqq.text.EmotcationConstants
static{
    ...
    String[] v0 = new String[203];
    v0[0] = "/呲牙";
    v0[1] = "/调皮";
    v0[v9] = "/流汗";
    v0[v11] = "/偷笑";
    v0[4] = "/再见";
    v0[5] = "/敲打";
    v0[6] = "/擦汗";
    v0[7] = "/猪头";
    v0[8] = "/玫瑰";
    v0[9] = "/流泪";
    v0[10] = "/大哭";
    v0[11] = "/嘘...";
    v0[12] = "/酷";
    v0[13] = "/抓狂";
    v0[14] = "/委屈";
    v0[15] = "/便便";
    v0[16] = "/炸弹";
    v0[17] = "/菜刀";
    ...
}

0.2 验证方式

截图中可以看到转义过的“菊花残”比正常的“菊花残”前面好像多了一点空白。
多出的空白就是无法显示的 \u0014
转义过的脏话,前面多了 \u0014

将 QQ 消息复制出来,粘帖到 idea 的双引号中,就会自动转义为 \u 形式

public void test() {
    //菜刀表情
    String a = "\u0014\u0011";

    //菜刀表情+冒号+微笑表情
    String b = "\u0014\u0011:\u0014\u0017";

    //发出去之后变成的 菊花残
    String c = "\u0014菊花残";

    //可以看到 \u0011:\u0014\u0017 被还原为了 菊花残
}

0.3 脏话的处理逻辑是什么

为什么点击发送的时候,要将处理过的脏话还原呢?
经过推测,应该是这样的逻辑。
1. 在输入时,监听 afterTextChanged 将输入的脏话转义
2. 在发送时,将已转义过的脏话还原,发送给服务器
(可能为了保证不同版本发送消息的准确,比如转义只存在于 Android ,为了低版本或别的版本正常显示,只能发送期输入的内容)
3. 在收到消息时,再将收到脏话转义

每一个步骤都受变量或方法控制,为 true 才执行相关步骤。
虽然步骤 1 和 3 没有执行,但是步骤 2 却执行了。
按理说没有执行 1 的转义,执行 2 的还原也没有影响,但是却遇到了菜刀的 \u0011,触发了 bug。

前面说的好像很有道理,为什么要说是“推测”呢,因为控制 1 和 3 变量,在代码中的确是 true,但实际却没有执行。
一定是我阅读代码的方式不对,留待以后 QQ 更新版本验证或等大神指点。

0x01 分析过程

1.1 好奇心

知乎上给推送了相关问题,很感兴趣,然后有网友反编译了代码,但是只能说明在代码里存在脏话,并不能解释为什么
尤其是为什么 菜刀+字符 就会显示,会什么别的表情不会?
有网友推测是写反了,如果是这样,为什么会过得了测试和代码 review?
为什么要把脏话替换为 菜刀加其他?
这显然是不能满足我的好奇心。

后文即整个分析过程,仅用于学习交流,侵删。
简单分析,有不对的地方欢迎指正。
原文地址[2538]QQ 发送菜刀加符号导致脏话的真实原因分析

1.2 LoveLanguageManager 中与脏话相关的方法

根据之前网友的反编译的结果,我们找到 classes2.dex 中的包 com.tencent.mobileqq.lovelanguage
经过一番查看,我们在 LoveLanguageManager 中找到两个可疑方法,分别用于将 EditText 中的脏话进行替换与还原

(后文中的代码

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值