Skip to content

Commit 99f569e

Browse files
Free input data pointer when rustbuffer_from_bytes throws (#39)
UniffiRustBufferValue.allocateWithBytes calls createPointer to wrap the input bytes, hands the inner pointer to ffi_rustbuffer_from_bytes through uniffiCaller.rustCall, and only then calls freePointer. If the rustCall throws (panic, CALL_ERROR with a lifted error, or any other exception), control jumps over the freePointer call and the wrapper Box allocated by ffi-rs is leaked. The leak is small per occurrence but is guaranteed on every failure path that goes through this allocator. Move the freePointer call into a finally block so the pointer is always released, regardless of how the rustCall returns.
1 parent b874680 commit 99f569e

1 file changed

Lines changed: 20 additions & 18 deletions

File tree

templates/sys.ts

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -317,24 +317,26 @@ export class UniffiRustBufferValue {
317317
paramsValue: [bytes],
318318
});
319319

320-
const rustBuffer = uniffiCaller.rustCall(
321-
(callStatus) => {
322-
return FFI_DYNAMIC_LIB.{{ci.ffi_rustbuffer_from_bytes().name()}}([
323-
// TODO: figure out why this is necessary.
324-
{ data: unwrapPointer([dataPointer])[0], len: bytes.byteLength },
325-
callStatus,
326-
]);
327-
},
328-
/*liftString:*/ {{ &Type::String | typescript_ffi_converter_name }}.lift,
329-
);
330-
331-
freePointer({
332-
paramsType: [arrayConstructor({ type: DataType.U8Array, length: bytes.byteLength })],
333-
paramsValue: [dataPointer],
334-
pointerType: PointerType.RsPointer
335-
});
336-
337-
return new UniffiRustBufferValue(rustBuffer);
320+
try {
321+
const rustBuffer = uniffiCaller.rustCall(
322+
(callStatus) => {
323+
return FFI_DYNAMIC_LIB.{{ci.ffi_rustbuffer_from_bytes().name()}}([
324+
// TODO: figure out why this is necessary.
325+
{ data: unwrapPointer([dataPointer])[0], len: bytes.byteLength },
326+
callStatus,
327+
]);
328+
},
329+
/*liftString:*/ {{ &Type::String | typescript_ffi_converter_name }}.lift,
330+
);
331+
332+
return new UniffiRustBufferValue(rustBuffer);
333+
} finally {
334+
freePointer({
335+
paramsType: [arrayConstructor({ type: DataType.U8Array, length: bytes.byteLength })],
336+
paramsValue: [dataPointer],
337+
pointerType: PointerType.RsPointer
338+
});
339+
}
338340
}
339341

340342
static allocateEmpty() {

0 commit comments

Comments
 (0)