From 52992d8c748e4c48672304d6b1e3a3901c86f568 Mon Sep 17 00:00:00 2001 From: Siddharth Tiwari Date: Fri, 26 Jun 2026 23:10:38 +0530 Subject: [PATCH] Fix uninitialized memory disclosure in WASM CropAndResize --- .../src/cc/kernels/CropAndResize.cc | 9 +++++++-- tfjs-backend-wasm/src/index_test.ts | 20 +++++++++++++++++++ 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/tfjs-backend-wasm/src/cc/kernels/CropAndResize.cc b/tfjs-backend-wasm/src/cc/kernels/CropAndResize.cc index 2b184e2046a..04bad1ed9f7 100644 --- a/tfjs-backend-wasm/src/cc/kernels/CropAndResize.cc +++ b/tfjs-backend-wasm/src/cc/kernels/CropAndResize.cc @@ -16,6 +16,7 @@ #include #endif +#include #include #include #include @@ -119,11 +120,15 @@ void CropAndResize(size_t images_id, size_t boxes_id, size_t box_ind_id, const float x2 = *boxes_buf; boxes_buf++; - if (*box_ind_buf >= batch) { + if (*box_ind_buf < 0 || static_cast(*box_ind_buf) >= batch) { + float* out_buf_ptr = out_buf + b * output_strides[0]; + std::fill(out_buf_ptr, out_buf_ptr + output_strides[0], 0.0f); + box_ind_buf++; continue; } - const size_t box_offset = *box_ind_buf * images_strides[0]; + const size_t box_offset = + static_cast(*box_ind_buf) * images_strides[0]; const float height_scale = (crop_height > 1) ? (y2 - y1) * image_height_m1 / (crop_height - 1) : 0; diff --git a/tfjs-backend-wasm/src/index_test.ts b/tfjs-backend-wasm/src/index_test.ts index d9428cb99f9..7e49f108892 100644 --- a/tfjs-backend-wasm/src/index_test.ts +++ b/tfjs-backend-wasm/src/index_test.ts @@ -65,6 +65,26 @@ describeWithFlags('wasm read/write', ALL_ENVS, () => { test_util.expectArraysClose(await t.data(), view); }); + it('cropAndResize zero-fills out-of-range box indices', async () => { + const image = tf.tensor4d([1, 2, 3, 4], [1, 2, 2, 1]); + const boxes = tf.tensor2d([ + 0, 0, 1, 1, + 0, 0, 1, 1, + ], [2, 4]); + const boxInd = tf.tensor1d([999, -1], 'int32'); + + const output = + tf.image.cropAndResize(image, boxes, boxInd, [4, 4], 'nearest', -7); + + expect(output.shape).toEqual([2, 4, 4, 1]); + test_util.expectArraysClose(await output.data(), new Float32Array(32)); + + image.dispose(); + boxes.dispose(); + boxInd.dispose(); + output.dispose(); + }); + // TODO(mattSoulanille): Re-enable this once it's working on iOS. // tslint:disable-next-line: ban xit('allocates more than two gigabytes', async () => {