
Harness di audit che verifica se la classe di bug di ricorsione Any-unwrapping CVE-2026-0994 influisce sul core C di upb nei binding protobuf di Ruby e PHP, con payload ASan/UBSan.
Seguito dei CVE confermati di ricorsione da unwrapping di Any nei binding Python e JavaScript di protobuf (più recentemente CVE-2026-0994, un bug puramente Python in _ConvertAnyMessage di json_format.py, che ricorreva tramite methodcaller() invece di ConvertMessage() e saltava silenziosamente il contatore di profondità).
Domanda: la stessa classe di bug esiste nel core C upb incluso nelle estensioni native Ruby e PHP?
Risposta breve: no. Sia il percorso di decodifica JSON sia il percorso di decodifica binaria wire applicano correttamente i loro limiti di ricorsione in ogni caso testato qui, incluso un payload di stress a 200.000 livelli eseguito con uno stack da 1MB. Questa è una ipotesi falsificata con evidenza, non una vulnerabilità — è registrata qui come risultato negativo pulito, allo stesso modo in cui registreresti un'ipotesi falsificata in qualsiasi altro filone di ricerca.
Le estensioni native Ruby e PHP di protobuf includono ciascuna un'amalgamazione in singolo file del core C di upb (ruby-upb.c, php-upb.c) invece di collegare una libreria condivisa. Questo audit compila esattamente quel file come target C standalone — nessun runtime Ruby o PHP coinvolto — inizializza un upb_DefPool con i descrittori google.protobuf.Any / Struct / Value / ListValue, e pilota direttamente i reali entry point del decoder (upb_JsonDecode, upb_Decode) con payload avversariali, sotto ASan/UBSan.
| Percorso | Guardia | Limite predefinito | Risultato |
|---|---|---|---|
Decodifica JSON, jsondec_any (Ruby) | d->depth, controllato in jsondec_push | 64 | Falsificata — errore pulito a payload di 5000 livelli, offset in byte corrisponde esattamente a ~64 livelli |
Decodifica binaria wire, upb_Decode (Ruby) | Decode_LimitDepth | 100 | Falsificata — kUpb_DecodeStatus_MaxDepthExceeded pulito a payload di confine di 60 livelli e a payload di stress di 200.000 livelli, sia con stack da 8MB sia con stack da 1MB (approssimando un thread Ruby non-main) |
| Binding PHP | stesse funzioni di guardia | stesso | Falsificata per prova di identità, non con un'esecuzione separata — vedi sotto |
Nessuna violazione ASan o UBSan è stata osservata in alcuna esecuzione. Nessun crash, nessun blocco, nessun esaurimento dello stack.
php-upb.c e ruby-upb.c differiscono complessivamente per ~1.964 righe, ma jsondec_any, jsondec_push e le costanti del limite di profondità wire sono identiche byte per byte tra i due file (verify_php_identical.sh lo dimostra, non fidarti sulla parola — eseguilo). Poiché il codice di guardia stesso è dimostrabilmente lo stesso, il risultato Ruby si trasferisce senza bisogno di un harness ridondante specifico per PHP.
JsonParser / CodedInputStream con la propria gestione di RecursionLimit). Genuinamente non testato; questo repo non lo copre ancora.utf8_range.c inclusa../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
Richiede: gcc, protoc (apt-get install protobuf-compiler), python3, git. Compilato e verificato con gcc (Ubuntu 13.3.0-6ubuntu2~24.04.1) 13.3.0 e libprotoc 3.21.12 — versioni diverse possono comportarsi diversamente; se i tuoi risultati non corrispondono alla tabella sopra, quello è un dato, non un bug nella tua configurazione. Scopri il perché prima di presumere che sia un disallineamento di tooling.
third_party/ (recuperato da fetch_source.sh) contiene il sorgente protobuf di Google con licenza Apache-2.0, fissato al commit sopra. Non viene mai committato in questo repo — fetch_source.sh è l'ancora di riproducibilità invece di includere l'albero sorgente di qualcun altro in questo.