概要
- 2026年9月のAndroid 17ビルドで wcscspn() と wcspbrk() にバグ発生
- U+0100 以上の文字で不正動作、ASCII区切り文字探索が失敗
- wcsspn() 等は正常動作、影響範囲限定
- 実例として Visual Pinball などで不具合確認
- バグの詳細なメカニズムと再現方法も判明
Android 17のwcscspn()/wcspbrk()バグ概要
- 2026年9月以降のAndroid 17ビルドで wcscspn() および wcspbrk() に不具合発生
- reject set が ASCII範囲(U+0100未満) の2文字以上のみの場合、探索文字列内の U+0100以上 の文字で誤判定
- 本来一致しないはずの 絵文字・CJK・キリル・ギリシャ文字 などで一致扱い
- wcsspn(), wcschr(), wcsrchr(), wmemchr(), wcsstr() は正常動作
- ASCII区切り文字(例:改行、ワイルドカード)探索処理が U+0100以上 の文字で中断される
- Pixel 7/8a で再現、2026年6月ビルドまでは正常動作
影響範囲・再現手順
- 影響端末
- Pixel 7, 8a(2026年9月ビルド): 不具合あり
- Nothing Phone 2(2026年8月ビルド): 問題なし
- NDK ビルドでサンプルコードを実行し、出力値が期待値と異なることを確認
- 例:
wcscspn(s, L"x\n") = 1 (期待値: 4)wcspbrk(s, L"x\n") = index 1 (期待値: 4)wcsspn(s, L"a\U0001F680") = 2 (期待値: 2)
バグの詳細メカニズム
- libc.so の逆アセンブル結果より、 reject set が全て U+0100未満 の場合、 256バイトのboolテーブル で判定
- 探索中の文字が U+0100以上 になると、テーブル外アクセスを避けて 即一致扱い で停止
- 本来一致しない文字でも 一致判定 されてしまうロジック
- wcsspn() も同様構造だが、こちらは設計通り動作
- wcspbrk() はこのスキャンロジックを利用しており、同様のバグを継承
- テストコードが ASCII入力のみ のため、既存のテストでは未検出
実際の影響例
- Visual Pinball (libwinevbs/Wine vbscript engine)で、コメント行に 絵文字 が含まれるとパース不能
wcspbrk(ptr, L"\n\r")で行末を探す際、絵文字で停止してしまい「Invalid character」エラー
- FileSystem.MoveFolder で、パスに U+0100以上 の文字を含むとワイルドカード扱いに
- 回避策として 独自ループ による実装に置換(vpinball/libwinevbs#41等)
まとめ・推奨対応
- Android 17(2026年9月以降)で wcscspn() や wcspbrk() を使用するコードは要注意
- ASCII以外の文字列処理 で不具合発生リスク
- 影響を受ける場合は 独自実装 や 代替API を暫定利用推奨
- バグ報告・修正の進捗確認も重要
参考情報
- NDK r29 で問題発生確認
- bionic の既存テストでは未検出
- 詳細な逆アセンブルや再現ソースは要望に応じて提供可能