首页 时政热点 科技头条 智能AI 安全攻防 数码硬件 开发者生态 汽车 游戏 社会热点 开源推荐 医疗健康 归档 标签 关于

AOSP 源代码发布太晚了,开发人员拆解库来报告错误

2026-10-14 1 阅读 约7分钟阅读 tharen
分享:
字号:
[BUG] 仿生:wcscspn()/wcspbrk() 将每个 wchar_t >= 0x100 视为匹配(Android 17、CP3A.260905.009) #2260 复制链接 复制链接 打开 打开 [BUG] 仿生:wcscspn()/wcspbrk() 将每个 wchar_t >= 0x100 视为匹配(Android 17、 CP3A.260905.009) #2260 复制链接 标签 bug 说明 francisdb 于 2026 年 10 月 12 日打开 问题主体操作 说明 在 2026 年 9 月开始构建的 Android 17 上,只要拒绝集有两个或多个全部 < U+0100 的字符,wcscspn() 和 wcspbrk() 就会停止在字符串的第一个字符 >= U+0100 处。即使该字符不在集合中,也会将其报告为匹配项。 wcsspn() 、 wcschr() 、 wcsrchr() 、 wmemchr() 和 wcssstr() 是正确的。任何扫描宽字符串中 ASCII 分隔符(例如换行符或通配符)的代码,只要文本包含表情符号、CJK、西里尔文、希腊语或拉丁语扩展字符,就会中断。受影响/不受影响的设备构建结果 Pixel 7 google/panther/panther:17/CP3A.260905.009/16091614:user/release-keys 损坏 Pixel 8a google/akita/akita:17/CP3A.260905.009/16091614:user/release-keys (补丁2026-09-05)损坏Nothing Phone 2 Nothing/PongEEA/Pong:16/BQ2A.250721.001-BP2A.250605.031.A3(补丁2026-08-01)确定公共android17-release源(android-17.0.0_r1,2026年6月)构建wcscspn /来自 external/llvm-libc 的 wcspbrk,这是 wchar_t 上的普通嵌套循环,并且是正确的。 9 月版本的代码不同(请参阅“机制”),因此在 6 月和 9 月版本之间引入了回归。使用 NDK ( aarch64-linux-android30-clang ) 构建复制器,推送到 /data/local/tmp ,使用 adb shell 运行: #include #include int main ( void ) { wchar_t s [] = { 'a' , 0x1F680 , 0x100 , 'b' , 'x' , '\n', 0 }; printf ( "wcscspn(s, L\"x\\n\") = %zu (预期 4)\n" , wcscspn ( s , L"x\n" )); printf ( "wcspbrk(s, L\"x\\n\") = 索引 %ld (预期为 4)\n" , ( long )( wcspbrk ( s , L"x\n" ) - s )); printf ( "wcsspn(s, L\"a\\U0001F680\") = %zu (预期 2)\n" , wcsspn ( s , L"a\U0001F680" ));返回 0 ; CP3A.260905.009 上的输出: wcscspn(s, L"x\n") = 1 (预期 4) wcspbrk(s, L"x\n") = 索引 1 (预期 4) wcsspn(s, L"a\U0001F680") = 2 (预期 2) 扫描从 U+0001 到U+10FFFF(跳过代理项和两个集合成员)与 wcscspn(L"\n", L"x\n") 对于 1,111,808 个代码点返回 0 而不是 1:从 U+0100 到 U+10FFFF 的每个代码点。 U+0001 到 U+00FF 是正确的。哪组形状触发它(全部在 Pixel 8a 上测量): 拒绝集结果 一个字符可以 两个或更多字符,全部 < U+0100(例如 L"x\n" 、 L"\xe9\n" ) 损坏两个或更多字符,至少一个 >= U+0100 ok haystack 限制为 U+0080..U+00FF ok 机制(来自附带的 libc.so) 反汇编CP3A.260905.009 上 /apex/com.android.runtime/lib64/bionic/libc.so 中的 wcscspn 显示了该组选择的三个路径: 一个字符:一个简单的比较循环。正确的。两个或更多字符:堆栈上的 256 字节布尔表从集合中填充,而集合字符在 1..0xFF 中。如果看到设置字符 >= 0x100,则该函数会回退到为每个 haystack 字符调用 wcschr()。正确的。否则,将根据表扫描干草堆: a2564: ldrb w8, [x9, x8] ;表[c] a2568: tbnz w8, #0, a2578 ;在设置 - >停止(正确)a256c:ldr w8,[x22,#0x4]! ;下一个字符 a2570: cmp w8, #0x100 a2574: b.lo a2564 ; c < 0x100 -> 继续扫描 a2578: ... ; c >= 0x100 -> STOP,报告为匹配 字符 >= 0x100 不能位于成员全部 < 0x100 的集合中,因此对于 wcscspn,扫描必须继续经过它。代码反而停止了。 wcsspn 具有相同的结构,并且停止就是正确的答案(该字符不在 keep 集中),这就是为什么只有补码函数是错误的。 wcspbrk 是在此扫描之上实现的,并继承了该错误。 tests/wchar_test.cpp 中现有的仿生测试 TEST(wchar, wcspbrk) 仅使用 ASCII 输入,因此它无法捕获这一点。诸如 EXPECT_EQ(3u, wcscspn(L"aĀb\n", L"x\n")) 之类的测试可以。真实世界影响 Android 上的 Visual Pinball(libwinevbs,Wine 的 vbscript 引擎的 Unix 版本)在 9 月更新后停止加载任何 VBScript 源代码包含带表情符号注释的表格:词法分析器使用 wcspbrk(ptr, L"\n\r") 跳过注释,获取第一个表情符号的位置而不是行尾,并报告“无效字符”。 FileSystem.MoveFolder 同样通过 wcspbrk(src, L"*?><") 将包含字符 >= U+0100 的每个路径视为通配符模式。通过用普通循环替换调用来解决下游问题: vpinball/libwinevbs#41 (在 vpinball/vpinball@ e7837322f4 中提供)。可根据要求提供受影响功能和探头源的完整拆卸。我正在使用受支持的 NDK 我已检查过,并且我正在使用的 NDK 当前受支持 受影响的版本 r29 反应当前不可用 Activity francisdb 于 2026 年 10
这篇文章对您有帮助吗?

订阅66必读

每日精选科技资讯,直达你的邮箱