Description
When MathCATForC is built with the no-unsafe feature, GetNavigationBraille can panic inside sxd-document-no-unsafe. GetSpokenText works correctly with the same MathML.
Originally observed with MathCAT and MathCATForC beta.8. The underlying issue was also reproduced with MathCAT 0.7.6-rc.4.
Reproduction
After normal MathCAT initialization:
SetMathML(R"(<math><mi id='focused'>x</mi><mo>+</mo><mi>y</mi></math>)");
GetNavigationBraille();
Build MathCATForC with:
cargo build --release --features no-unsafe
No explicit navigation operation was required in the original beta.8 reproduction.
A deterministic reproduction on MathCAT 0.7.6-rc.4 is:
set_mathml("<math><mi id='focused'>x</mi><mo>+</mo><mi>y</mi></math>")?;
set_navigation_node("focused", 0)?;
get_navigation_braille()?;
Actual Result
index out of bounds: the len is 1 but the index is 7
Relevant stack frames:
sxd_document_no_unsafe::raw::Connections::replace_element_child_parent
sxd_document_no_unsafe::raw::Connections::append_element_child
sxd_document_no_unsafe::dom::Element::append_child
libmathcat::interface::get_navigation_braille
Expected Result
GetNavigationBraille should return braille for the current navigation focus without panicking.
Root Cause
get_navigation_braille creates a temporary Package and <math> element, but copy_mathml(found) allocates the copied subtree in the original document and appends it to the temporary document.
The unsafe backend uses pointers and happens to tolerate this cross-document operation. The no-unsafe backend uses document-local indices, so it uses an original-document index against the temporary document storage and panics.
The invalid cross-document insertion occurs in MathCAT's interface.rs; sxd-document-no-unsafe exposes the ownership violation.
Proposed Fix
Allow recursive MathML copying to receive a destination Document and allocate the entire copied subtree there before appending it.
Add a regression test that focuses below the outer <math> element and calls get_navigation_braille with no-unsafe enabled.
Local Validation
The proposed fix passed:
- Focused regression with
--features no-unsafe
- The same regression with default features
- All
interface::tests with no-unsafe
- MathCATForC release DLL build with
no-unsafe
- Direct C ABI verification returning the expected navigation braille
Description
When MathCATForC is built with the
no-unsafefeature,GetNavigationBraillecan panic insidesxd-document-no-unsafe.GetSpokenTextworks correctly with the same MathML.Originally observed with MathCAT and MathCATForC beta.8. The underlying issue was also reproduced with MathCAT 0.7.6-rc.4.
Reproduction
After normal MathCAT initialization:
Build MathCATForC with:
cargo build --release --features no-unsafeNo explicit navigation operation was required in the original beta.8 reproduction.
A deterministic reproduction on MathCAT 0.7.6-rc.4 is:
Actual Result
Relevant stack frames:
Expected Result
GetNavigationBrailleshould return braille for the current navigation focus without panicking.Root Cause
get_navigation_braillecreates a temporaryPackageand<math>element, butcopy_mathml(found)allocates the copied subtree in the original document and appends it to the temporary document.The unsafe backend uses pointers and happens to tolerate this cross-document operation. The no-unsafe backend uses document-local indices, so it uses an original-document index against the temporary document storage and panics.
The invalid cross-document insertion occurs in MathCAT's
interface.rs;sxd-document-no-unsafeexposes the ownership violation.Proposed Fix
Allow recursive MathML copying to receive a destination
Documentand allocate the entire copied subtree there before appending it.Add a regression test that focuses below the outer
<math>element and callsget_navigation_braillewithno-unsafeenabled.Local Validation
The proposed fix passed:
--features no-unsafeinterface::testswithno-unsafeno-unsafe