Repository navigation
Conversation
…Malloc Running the 1,012 Ketcher autotest KET files that hold monomers through loadKetDocument(...).expandMonomers() and loadStructure under macOS Guard Malloc found these faults in upstream 1.46. All six are still on upstream master. 1. mm_expand.cpp indexed its per-monomer dimensions and graph vertices by monomer id, but Ketcher writes ids such as "635". It now maps each id to its position in monomersIds(), resolves endpoints by ref, skips bonds to molecule atoms and hydrogen bonds, seeds every ring-free component, and checks leaving-group atom indexes. indigoExpandMonomers ended in INDIGO_END(0), which no wrapper treats as a failure, so a document with non-sequential ids or a bond to a molecule was silently left without a layout; it now returns -1. 2. mm_expand.cpp cast an ambiguous monomer to KetMonomer and wrote a transformation past the end of it. 3. MoleculeJsonLoader took the N in "molN" as the molecule's position, so a document whose only molecule is "mol1" read past mol_mappings. It now looks the ref up and checks the atom index, and the KetDocument saver renames connection endpoints to the mol<i> names it gives the nodes. 4. KetMolecule::parseKetAtoms looped over "$refs" with i++ instead of r++, so any rg-label with $refs hung loadKetDocument. 5. KetDocumentJsonSaver wrote a monomer's flip under the key "shift", and the loader then read shift.x from a string; a flip-only transformation was dropped. 6. KetObjWithProps::parseOptsFromKet called GetString() on Ketcher's integer atomId, and rapidjson's assertion aborted the process. Values are now type-checked, and a string property also takes an integer. The JSON template parser also checks leaving-group atom indexes, which a query molecule read unchecked. basic/unc_ket_monomer_expansion covers every case. Bumps to 1.46.0+unc36. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
gordlin
marked this pull request as ready for review
October 2, 2026 19:38
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes the native crashes, hang and lost errors that
mainworks around inmain/unc/materials/chemical/ket_structure_loading.py(uncountableinc/main#186765 anduncountableinc/main#186767, MAT-90161 and MAT-90032), and bumps the fork to
1.46.0+unc36.Bumping
mainto the new wheel, and removing the IMPROVE-marked monomer-id renumbering there, is aseparate PR.
How they were found
The 1,012 Ketcher autotest KET files that hold monomers, run through
loadKetDocument(...).expandMonomers()+molfile(),loadStructureandloadQueryMoleculeunder macOS Guard Malloc (
DYLD_INSERT_LIBRARIES=/usr/lib/libgmalloc.dylib), which turns anout-of-range read into a fault.
The faults
All six are still on upstream
master. Each site carries an[Uncountable]comment that says whatupstream does.
mm_expand.cppused monomer ids as indexes.getDimensionsfillsdimensionsinmonomersIds()order, butbfsPropagateandplaceRingMonomersreaddimensions[stoi(id)],and
getGraphadded the vertexstoi(id). Ketcher writes ids such as"635". The expansionnow maps id to index, resolves endpoints by ref, skips bonds to molecule atoms and hydrogen
bonds, seeds every ring-free component (an unseeded one failed in
applyTransformations), andchecks leaving-group atom indexes.
indigoExpandMonomersended inINDIGO_END(0). No wrapper treats0as a failure, so everyexpansion error was lost, and the monomers were silently left without a layout. It now returns
-1. This is why fault 1 often showed no crash:getGraphthrew first, and nobody saw it.KetMonomer, and the expansion wrote a transformation pastthe end of it. It also read the
selectedflag at the wrong index.{"moleculeId": "molN"}took N as the molecule's position. A document whose only moleculeis
mol1read pastmol_mappings.MoleculeJsonLoadernow looks the ref up, checks the atomindex, and accepts an integer
atomId. The KetDocument saver renamed the molecule node tomol0but keptmol1in the connection, so it now renames the endpoint too.loadKetDocumenthung on any rg-label with$refs. The loop over$refsinKetMolecule::parseKetAtomsincrementediinstead ofr."shift". With a rotate, the loader thenread
shift.xfrom a string. A flip-only transformation was dropped.KetObjWithProps::parseOptsFromKetcalledGetString()on Ketcher's integeratomId, andrapidjson's assertion aborted the process. Values are now type-checked, and a string property
also takes an integer.
The JSON template parser also checks leaving-group atom indexes, which
loadQueryMoleculereadunchecked.
Behaviour change
Because expansion errors were lost, documents with non-sequential ids, a bond to a molecule, or a
hydrogen bond were "expanded" without a layout: every monomer kept its drawn position and no
rotation. They now get the layout that sequential-id documents always got. Hydrogen bonds are left
out of that layout. Without that, the base pairs of
Antisense-expected.ketclose rings that putatoms on top of each other.
Verification
Under Guard Malloc, on a native macOS build of this branch and of
6d6ae47c8:6d6ae47c8Of the 168 expand crashes and hangs, 98 now succeed and 70 raise an
IndigoExceptionfrom themolfile saver: 59 "Ambiguous monomer cannot be saved to molfile" and 11 for an unknown or
unresolved monomer, which those test files contain on purpose. All 24 load crashes now succeed. The remaining expand errors were already errors on
6d6ae47c8.Five files go from success to an error:
Side-Chain-Connections/1.2,1.3,1.4and10,and
Sequence-Mode-Replacement/phosphate to sugar connected two sequences of presets (U). On6d6ae47c8their layout failed silently (array: invalid index 428), and renumbering the ids doesnot change that, because upstream's
getGraphread the digits of the ref. So they alwaysexpanded with no layout. Now upstream's layout runs, and its ring placement puts side-chain loops on
top of each other:
expandMonomers()andmolfile()succeed, but loading that molfile againraises "stereocenters: angle between bonds is too small" unless
ignore-stereochemistry-errorsisset. A heuristic that skips rings sharing a placed monomer fixed four files and broke a fifth, so it
is not in this PR.
basic/unc_ket_monomer_expansioncovers every fault. Against6d6ae47c8its layout checks printFalseand it then aborts. Fault 2 does not crash without Guard Malloc, so that case documents thefix rather than proves it. The hydrogen-bond case was checked against a build with only that skip
removed, and fails there.
Full integration suite on the native macOS build: 302 passed, 14 failed on this branch; 301 passed
and the same 14 failed on
6d6ae47c8(run without the new test, which aborts there), each withbyte-identical output. The 14 are macOS float and font differences. CI on this PR is green.
🤖 Generated with Claude Code