mirror of
https://github.com/penpot/penpot.git
synced 2026-04-25 11:18:36 +00:00
Replace unsafe std::mem::transmute calls in Rust WASM path code with validated TryFrom conversions to prevent undefined behavior from invalid enum discriminant values. This was the most likely root cause of the "No matching clause: -19772" production crash -- corrupted bytes flowing through transmute could produce arbitrary invalid enum variants. Fix byteOffset handling throughout the CLJS PathData serialization pipeline. DataView instances created via buf/slice carry a non-zero byteOffset, but from-bytes, transit write handler, -write-to, buf/clone, and buf/equals? all operated on the full underlying ArrayBuffer, ignoring offset and length. This could silently produce PathData with incorrect size or content. Rust changes (render-wasm): - RawSegmentData: From<[u8; N]> -> TryFrom<[u8; N]> with discriminant validation (must be 0x01-0x04) before transmuting - RawBoolType: From<u8> -> TryFrom<u8> with explicit match on 0-3 - Add #[wasm_error] to set_shape_path_content, current_to_path, convert_stroke_to_path, and set_shape_bool_type so panics are caught and routed through the WASM error protocol instead of crashing - set_shape_path_content: replace .expect() with proper Result/? error propagation per segment - Remove unused From<BytesType> bound from SerializableResult trait CLJS changes (common): - from-bytes: use DataView.byteLength instead of ArrayBuffer.byteLength for DataView inputs; preserve byteOffset/byteLength when converting from Uint8Array, Uint32Array, and Int8Array - Transit write handler: construct Uint8Array with byteOffset and byteLength from the DataView, not the full backing ArrayBuffer - -write-to: same byteOffset/byteLength fix - buf/clone: copy only the DataView byte range using Uint8Array with proper offset, not Uint32Array over the full ArrayBuffer - buf/equals?: compare DataView byte ranges using Uint8Array with proper offset, not the full backing ArrayBuffers Frontend changes: - shape-to-path, stroke-to-path, calculate-bool*: wrap WASM call and buffer read in try/catch to ensure mem/free is always called, even when an exception occurs between the WASM call and the free call Signed-off-by: Andrey Antukh <niwi@niwi.nz>