
أداة تدقيق تختبر ما إذا كانت فئة ثغرة التكرار غير المحدود لفك أي (Any-unwrapping recursion) CVE-2026-0994 تؤثر على نواة C الخاصة بـ upb في ارتباطات protobuf للغة Ruby وPHP، باستخدام حِمل ASan/UBSan.
متابعة لثغرات CVE المؤكدة الخاصة بالاستدعاء الذاتي لفك تغليف Any في ارتباطات protobuf الخاصة بـ Python وJavaScript (وأحدثها CVE-2026-0994، وهو خطأ في Python الخالص داخل _ConvertAnyMessage في json_format.py، حيث كان يستدعي نفسه عبر methodcaller() بدلاً من ConvertMessage() ويتخطى عدّاد العمق بصمت).
السؤال: هل توجد نفس فئة الخطأ في نواة upb المكتوبة بلغة C والمضمّنة في امتدادات Ruby وPHP الأصلية؟
الإجابة المختصرة: لا. كلاً من مسار فك ترميز JSON ومسار فك ترميز البيانات الثنائية يفرضان حدود الاستدعاء الذاتي بشكل صحيح في كل الحالات المختبرة هنا، بما في ذلك حمولة إجهادية بمستوى 200,000 تم تشغيلها على مكدس بحجم 1MB. هذه فرضية مُبطَلة مع أدلة، وليست ثغرة — وهي مسجّلة هنا كنتيجة سلبية نظيفة، بالطريقة نفسها التي تسجّل بها فرضية مُبطَلة في أي مسار بحثي آخر.
كل من امتدادات protobuf الأصلية لـ Ruby وPHP تضمّن نسخة مدمجة أحادية الملف من نواة upb المكتوبة بلغة C (، ) بدلاً من الربط بمكتبة مشتركة. يبني هذا التدقيق ذلك الملف بالضبط كهدف C مستقل — دون أي وقت تشغيل لـ Ruby أو PHP — ويهيّئ بوصفات / / / ، ويشغّل نقاط دخول فك الترميز الحقيقية (، ) مباشرة بحمولات عدائية، تحت ASan/UBSan.
ruby-upb.cphp-upb.cupb_DefPoolgoogle.protobuf.AnyStructValueListValueupb_JsonDecodeupb_Decode| المسار | الحارس | الحد الافتراضي | النتيجة |
|---|---|---|---|
فك ترميز JSON، jsondec_any (Ruby) | d->depth، يُفحص في jsondec_push | 64 | مُبطَلة — خطأ نظيف عند حمولة بمستوى 5000، وإزاحة البايت تطابق ~64 مستوى بالضبط |
فك ترميز البيانات الثنائية، upb_Decode (Ruby) | Decode_LimitDepth | 100 | مُبطَلة — kUpb_DecodeStatus_MaxDepthExceeded نظيف عند حمولة حدّية بمستوى 60 وعند حمولة إجهادية بمستوى 200,000، وكلاهما تحت مكدس بحجم 8MB ومكدس بحجم 1MB (بمحاكاة خيط Ruby غير الرئيسي) |
| ارتباط PHP | نفس دوال الحارس | نفسها | مُبطَلة بإثبات التطابق، وليس بتشغيل منفصل — انظر أدناه |
لم يُلاحظ أي انتهاك لـ ASan أو UBSan في أي تشغيل. لا انهيار، لا تعليق، لا استنفاد للمكدس.
يختلف php-upb.c وruby-upb.c بنحو 1,964 سطراً إجمالاً، لكن jsondec_any وjsondec_push وثوابت حد العمق في مسار البيانات الثنائية متطابقة بايتاً ببايت بين الملفين (verify_php_identical.sh يثبت ذلك، لا تأخذها على الثقة — شغّله). وبما أن كود الحارس نفسه قابل للإثبات بأنه متطابق، فإن نتيجة Ruby تنتقل دون الحاجة إلى أداة اختبار مكررة خاصة بـ PHP.
JsonParser / CodedInputStream مع معالجتهما الخاصة لـ RecursionLimit). غير مُختبر فعلياً؛ هذا المستودع لا يغطيه بعد.utf8_range.c../fetch_source.sh # pins & clones protobuf @ ead3f0029facc43da13588132e9091bf9bd7a26f
./build.sh # compiles both harnesses w/ ASan+UBSan against the fetched source
./run_tests.sh # generates payloads, runs the full matrix, prints results
./verify_php_identical.sh # confirms the PHP claim above instead of asserting it
يتطلب: gcc، protoc (apt-get install protobuf-compiler)، python3، git. تم البناء والتحقق مقابل gcc (Ubuntu 13.3.0-6ubuntu2~24.04.1) 13.3.0 وlibprotoc 3.21.12 — قد تتصرف إصدارات مختلفة بشكل مختلف؛ إذا لم تطابق نتائجك الجدول أعلاه، فهذه بيانات، وليست خطأً في إعدادك. اكتشف السبب قبل افتراض أنه عدم تطابق في الأدوات.
يحتوي third_party/ (الذي يجلبه fetch_source.sh) على مصدر protobuf الخاص بـ Google المرخّص بموجب Apache-2.0، والمثبّت على الالتزام أعلاه. لا يُرفع أبداً إلى هذا المستودع — fetch_source.sh هو مرتكز قابلية إعادة الإنتاج بدلاً من تضمين شجرة مصدر شخص آخر في هذه الشجرة.