HN 日本語サマリー

← 一覧へ戻る
プログラミング

AOSPソースリリースが遅すぎるため、開発者はバグ報告のためにライブラリを逆アセンブルしている

AOSP Source Releases Are So Late Developers Disassemble Libraries to Report Bugs (github.com)

256 pointsby tharen118 コメント

要約

Android 17のBionic Cライブラリにあるwcscspn()とwcspbrk()関数に、U+0100以上の文字を誤って一致と見なしてしまうバグが発見されました。この問題は、AOSPのソースコードリリースが遅れることで、開発者がバグ報告のためにライブラリを逆アセンブルするという異例の手段を取らざるを得なくなっている状況を浮き彫りにしています。このバグは、絵文字やCJK文字などの非ASCII文字を含む文字列処理を壊し、Visual Pinballなどのアプリケーションに影響を与えています。

全文翻訳

AOSPソースリリースが遅すぎるため、開発者はバグ報告のためにライブラリを逆アセンブルしている [BUG] bionic: wcscspn()/wcspbrk() は、すべてのwchar_t >= 0x100 を一致として扱います (Android 17, CP3A.260905.009) #2260 新規イシューコピーリンク新規イシューコピーリンクオープンオープン [BUG] bionic: wcscspn()/wcspbrk() は、すべてのwchar_t >= 0x100 を一致として扱います (Android 17, CP3A.260905.009)#2260コピーリンクラベルバグ説明francisdbが2026年10月12日にオープン 説明 2026年9月リリースされたAndroid 17ビルドでは、wcscspn() および wcspbrk() は、拒否セットの文字がすべて U+0100 未満である場合、文字列中の U+0100 以上の最初の文字で停止します。その文字は、セットに含まれていないにもかかわらず一致として報告されます。wcsspn(), wcschr(), wcsrchr(), wmemchr() および wcsstr() は正しいです。 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) OK 公開されている android17-release ソース (android-17.0.0_r1, 2026年6月) は external/llvm-libc から wcscspn/wcspbrk をビルドしますが、これは wchar_t の単純なネストループであり、正しいです。9月のビルドのコードは異なります(「メカニズム」を参照)ので、2026年6月と9月のリリース間にリグレッションが導入されました。 再現手順 NDK (aarch64-linux-android30-clang) でビルドし、/data/local/tmp にプッシュし、adb shell で実行します: #include <stdio.h> #include <wchar.h> int main(void) { wchar_t s[] = {'a', 0x1F680, 0x100, 'b', 'x', '\n', 0}; printf("wcscspn(s, L\"x\\n\") = %zu (expected 4)\n", wcscspn(s, L"x\n")); printf("wcspbrk(s, L\"x\\n\") = index %ld (expected 4)\n", (long)(wcspbrk(s, L"x\n") - s)); printf("wcsspn(s, L\"a\\U0001F680\") = %zu (expected 2)\n", wcsspn(s, L"a\U0001F680")); return 0; } CP3A.260905.009 での出力: wcscspn(s, L"x\n") = 1 (expected 4) wcspbrk(s, L"x\n") = index 1 (expected 4) wcsspn(s, L"a\U0001F680") = 2 (expected 2) U+0001 から U+10FFFF までのすべてのコードポイント(サロゲートとセットの2つのメンバーを除く)を wcscspn(L"<cp>\n", L"x\n") でスキャンすると、1,111,808 のコードポイントで 1 の代わりに 0 が返されます。U+0100 から U+10FFFF までのすべてのコードポイントです。U+0001 から U+00FF は正しいです。 どのセット形状がトリガーするか(すべて Pixel 8a で測定) 拒否セット 結果 1文字 OK 2文字以上、すべて < U+0100 (例: L"x\n", L"\xe9\n") 壊れている 2文字以上、少なくとも1つ >= U+0100 OK ハヤシ(haystack)を U+0080..U+00FF に制限 OK メカニズム(出荷された libc.so から) CP3A.260905.009 の /apex/com.android.runtime/lib64/bionic/libc.so の wcscspn の逆アセンブルは、セットによって選択される3つのパスを示しています: 1文字: 単純な比較ループ。正しい。 2文字以上: スタック上の256バイトのブールテーブルがセットから埋められます。セットの文字は 1..0xFF の範囲です。セットの文字が >= 0x100 の場合、関数は各ハヤシ文字に対して wcschr() を呼び出すフォールバックを行います。正しい。 それ以外の場合、ハヤシはテーブルに対してスキャンされます: a2564: ldrb w8, [x9, x8] ; table[c] a2568: tbnz w8, #0, a2578 ; セット内 -> 停止 (正しい) a256c: ldr w8, [x22, #0x4]! ; 次の文字 a2570: cmp w8, #0x100 a2574: b.lo a2564 ; c < 0x100 -> スキャンを続ける a2578: ... ; c >= 0x100 -> 停止、一致として報告 U+0100 以上の文字は、メンバーがすべて U+0100 未満のセットには含まれないため、wcscspn ではスキャンを続行する必要があります。コードは代わりに停止します。 wcsspn は同じ構造を持ち、そこで停止することは正しい答えです(文字はキープセットに含まれていません)。そのため、補関数のみが間違っています。wcspbrk はこのスキャン上に実装されており、バグを継承します。 既存の bionic テスト TEST(wchar, wcspbrk) は tests/wchar_test.cpp で ASCII 入力のみを使用しているため、これをキャッチしません。EXPECT_EQ(3u, wcscspn(L"aĀb\n", L"x\n")) のようなテストはキャッチするでしょう。 実世界への影響 Android 上の Visual Pinball (libwinevbs、Wine の vbscript エンジンの Unix ビルド) は、9月のアップデート後に絵文字を含むコメントを VBScript ソースに含むテーブルのロードを停止しました。lexical analyzer は wcspbrk(ptr, L"\n\r") を使用してコメントをスキップしていましたが、行末ではなく最初の絵文字の位置を取得し、「無効な文字」を報告しました。 FileSystem.MoveFolder も同様に、wcspbrk(src, L"*?><") を介して、U+0100 以上の文字を含むパスをワイルドカードパターンとして扱いました。 呼び出しを単純なループに置き換えることで、下流で回避策が適用されました: vpinball/libwinevbs#41 (vpinball/vpinball@e7837322f4 で出荷済み)。 影響を受ける関数の完全な逆アセンブルとプローブソースは、要求に応じて利用可能です。 私はサポートされているNDKを使用しています 私が使用しているNDKは現在サポートされていることを確認しました 影響を受けるバージョン r29 リアクションは現在利用できません アクティビティ francisdbが2026年10月12日にバグを追加しました enh-googleが2026年10月12日にコメントしました enh-google 2026年10月12日 コラボレーター その他のアクション はい、すべて正しそうです。そして、まだ ToT で問題になっているようです。(「ソースを見ればいいだけじゃない?」と言おうと思ったのですが、android-latest-release はまだこれらの4月の変更のどれも含まれていないほど古いようです :-( wcspbrk() は、それが単に __attribute__((__flatten__)) wchar_t* wcspbrk(const wchar_t* s, const wchar_t* delims) { size_t i = wcscspn(s, delims); if (s[i] != L'\0') return const_cast<wchar_t*>(s) + i; return nullptr; } だからです。しかし、両方の不足しているテストを追加します。そして理想的には、非ASCIIを実際に使用するテストがどこにも欠けていないかを見つけようとします。 また、影響を受けるデバイスの数を最小限に抑えるために、修正をバックポートできるかどうかも確認します。(これは、直接関係のないテストを別の後続の変更で追加することを保証する理由になるでしょう。) 😕リアクション 😕10 Joaquín Vacas Verísimo, Kunal Agrawal, Vinayak, Doug Lynch, Matheus Araújo, David Allison, LifeIsStrange, JannF, Alexander Pushkov, Oliver Krieg がリアクションしました 👀リアクション 👀3 Joaquín Vacas Verísimo, Doug Lynch, David Allison がリアクションしました enh-googleが2026年10月12日にコメントしました enh-google 2026年10月12日 コラボレーター その他のアクション ああ、さらに恥ずかしいことに、wcscspn() の既存のテストがあります。それは単に間違っています: [ RUN ] wchar.wcscspn bionic/tests/wchar_test.cpp:(1475) Failure in test wchar.wcspbrk Expected equality of these values: 2u Which is: 2 wcscspn(L"he\ufffelo", L"lo") Which is: 3 wchar.wcspbrk exited with exitcode 1. 🤦 😕リアクション 😕1 Joaquín Vacas Verísimo がリアクションしました 👀リアクション 👀1 Joaquín Vacas Verísimo がリアクションしました francisdbが2026年10月13日にコメントしました francisdb 2026年10月13日 著者 その他のアクション 迅速な対応ありがとうございます。ソースが(まだ)利用できないのは確かに残念です。 joaquinvacasが2026年10月13日にコメントしました joaquinvacas 2026年10月13日 その他のアクション ドラマチックに聞こえるかもしれませんが、そうではありません。ただ心配しているのです。何かがおかしいと感じます... GoogleがAOSPソースコードを閉鎖することを決定して以来、多くの問題が修正なしで発生しており、Google側からの透明性はありません...これがどのように管理されるかについて、何か動きはありますか?つまり、このバグではなく、AOSPプロジェクトの管理に関する問題です。 👍リアクション 👍18 MasterMann, Marcin Panniak, Terence Eden, Ben Parsons, p12h4, Björn Kettunen, Marcos Del Sol Vives, Braden Farmer, Max Rumpf, Agustín および 8 名がリアクションしました pirama-arumuga-nainarが2026年10月13日にコメントしました pirama-arumuga-nainar 2026年10月13日 コラボレーター その他のアクション これがどのように管理されるかについて、何か動きはありますか?つまり、このバグではなく、AOSPプロジェクトの管理に関する問題です。 source.android.com(特に、https://source.android.com/docs/whatsnew/site-updates?year=2026#aosp-changes)にこのトピックに関する公式なコミュニケーションがあります。 (「ソースを見ればいいだけじゃない?」と言おうと思ったのですが、android-latest-release はまだこれらの4月の変更のどれも含まれていないほど古いようです :-( 参考までに、android-latest-release はマニフェストブランチであり、android17-release は git br