CVE-2022-42885: Open Babel GRO Parser Uninitialized Pointer Dereference
A crafted GROMACS .gro file can make Open Babel dereference an uninitialized residue pointer while parsing atom records, crashing the process and potentially enabling arbitrary code execution.
The problem
Open Babel's GRO format reader in `src/formats/groformat.cpp` declared a local `OBResidue* res` pointer but never initialized it before the atom-parsing loop. When a new residue number was encountered in the atom records, the code path that should have called `mol->NewResidue()` could be skipped under malformed input, leaving `res` pointing at garbage stack memory.
The first call to `res->AddAtom(atom)` at line 278 then dereferenced that garbage pointer, crashing inside `OBResidue::AddAtom` and, depending on stack layout, giving an attacker influence over the instruction pointer. Any application that passes untrusted files to `obabel`, `OBConversion`, or any language binding (Python, Ruby, Java, R, Perl, C#, PHP) is affected.
Proof of concept
A working proof-of-concept for CVE-2022-42885 in openbabel, with the exact payload below.
Minimized malformed GRO file (save as res.uninit.gro, then run):
$ obabel -i gro res.uninit.gro -o sdf
--- res.uninit.gro ---
Malformed GRO trigger
1
1CRASH CA 1 0.000 0.000 0.000
0.00000 0.00000 0.00000
The atom count header says 1 atom, but the residue-change logic is entered with `res` still uninitialized, causing AddressSanitizer to report:
AddressSanitizer: SEGV on unknown address 0x00000078
#0 OBResidue::AddAtom(OBAtom*) residue.cpp:891
#1 GROFormat::ReadMolecule(...) groformat.cpp:278The root cause is CWE-824: the local variable `OBResidue* res` was declared but never set to `nullptr`, so it held whatever value was on the stack at that point. The parser only assigned `res` inside a conditional branch that compared the current residue ID to the previous one; a crafted input that bypasses that branch reaches `res->AddAtom(atom)` with a wild pointer.
The Talos crash trace confirms the fault inside `std::vector::push_back` called from `OBResidue::AddAtom` via `groformat.cpp:278`, with ASAN reporting a read of address `0x00000078` (a small offset from a near-zero or stack-garbage base). Because `res` lives on the stack and the attacker controls the file content that shapes stack layout, the pointer value can be influenced toward code execution.
The fix (commit fa9a2d9a) initializes `res = nullptr` at declaration and adds a null check before any method call on it, ensuring a malformed record is rejected rather than dereferenced.
The fix
Upgrade to Open Babel 3.2.0, which includes the fix in commit fa9a2d9a. The patch initializes `OBResidue* res = nullptr` and guards every subsequent use with a null check. No workaround exists for older versions; avoid passing untrusted .gro files to any Open Babel interface until the upgrade is applied.
Reported by Cisco Talos.
Related research
- high · 7.8CVE-2022-44451CVE-2022-44451: Open Babel MSI Parser Uninitialized Pointer Dereference
- high · 7.8CVE-2022-43467CVE-2022-43467: Open Babel PQS Parser Out-of-Bounds Write
- high · 7.8CVE-2022-43607CVE-2022-43607: Open Babel MOL2 Parser Stack Buffer Overflow
- high · 7.8CVE-2022-46289CVE-2022-46289: Open Babel ORCA nAtoms Heap Buffer Overflow