diff --git a/src/x32-unpool/x32-unpool-neon.c b/src/x32-unpool/x32-unpool-neon.c index 7b6367fa420..e83018f804c 100644 --- a/src/x32-unpool/x32-unpool-neon.c +++ b/src/x32-unpool/x32-unpool-neon.c @@ -18,6 +18,7 @@ void xnn_x32_unpool_ukernel__neon( const uint32_t* index, uint32_t** output) { + const size_t num_outputs = kernel_elements; // Pre-initialize outputs with constant. const uint32x4_t vfill = vdupq_n_u32(fill); uint32_t** os = output; @@ -41,7 +42,13 @@ void xnn_x32_unpool_ukernel__neon( size_t offset = 0; do { const uint32_t i = *index++; - *((uint32_t*) ((uintptr_t) output[i] + offset)) = *input++; + const uint32_t v = *input++; + // Ignore indices outside the kernel_elements output pointers instead of + // dereferencing output[i] out of bounds. Valid unpooling indices are + // always < kernel_elements, so well-formed input is unaffected. + if (i < num_outputs) { + *((uint32_t*) ((uintptr_t) output[i] + offset)) = v; + } offset += sizeof(uint32_t); } while (--channels != 0); } diff --git a/src/x32-unpool/x32-unpool-scalar.c b/src/x32-unpool/x32-unpool-scalar.c index 4596622071d..7d1a279e059 100644 --- a/src/x32-unpool/x32-unpool-scalar.c +++ b/src/x32-unpool/x32-unpool-scalar.c @@ -16,6 +16,7 @@ void xnn_x32_unpool_ukernel__scalar( const uint32_t* index, uint32_t** output) { + const size_t num_outputs = kernel_elements; // Pre-initialize outputs with constant. uint32_t** os = output; do { @@ -30,7 +31,13 @@ void xnn_x32_unpool_ukernel__scalar( size_t offset = 0; do { const uint32_t i = *index++; - *((uint32_t*) ((uintptr_t) output[i] + offset)) = *input++; + const uint32_t v = *input++; + // Ignore indices outside the kernel_elements output pointers instead of + // dereferencing output[i] out of bounds. Valid unpooling indices are + // always < kernel_elements, so well-formed input is unaffected. + if (i < num_outputs) { + *((uint32_t*) ((uintptr_t) output[i] + offset)) = v; + } offset += sizeof(uint32_t); } while (--channels != 0); } diff --git a/src/x32-unpool/x32-unpool-sse2.c b/src/x32-unpool/x32-unpool-sse2.c index adcbe22b990..45e48c39525 100644 --- a/src/x32-unpool/x32-unpool-sse2.c +++ b/src/x32-unpool/x32-unpool-sse2.c @@ -18,6 +18,7 @@ void xnn_x32_unpool_ukernel__sse2( const uint32_t* index, uint32_t** output) { + const size_t num_outputs = kernel_elements; // Pre-initialize outputs with constant. const __m128i vfill = _mm_set1_epi32((int) fill); uint32_t** os = output; @@ -43,7 +44,13 @@ void xnn_x32_unpool_ukernel__sse2( size_t offset = 0; do { const uint32_t i = *index++; - *((uint32_t*) ((uintptr_t) output[i] + offset)) = *input++; + const uint32_t v = *input++; + // Ignore indices outside the kernel_elements output pointers instead of + // dereferencing output[i] out of bounds. Valid unpooling indices are + // always < kernel_elements, so well-formed input is unaffected. + if (i < num_outputs) { + *((uint32_t*) ((uintptr_t) output[i] + offset)) = v; + } offset += sizeof(uint32_t); } while (--channels != 0); } diff --git a/src/x32-unpool/x32-unpool-wasmsimd.c b/src/x32-unpool/x32-unpool-wasmsimd.c index 9d376cb1e95..60e03e8aa96 100644 --- a/src/x32-unpool/x32-unpool-wasmsimd.c +++ b/src/x32-unpool/x32-unpool-wasmsimd.c @@ -18,6 +18,7 @@ void xnn_x32_unpool_ukernel__wasmsimd( const uint32_t* index, uint32_t** output) { + const size_t num_outputs = kernel_elements; // Pre-initialize outputs with constant. const v128_t vfill = wasm_i32x4_splat(fill); uint32_t** os = output; @@ -43,7 +44,13 @@ void xnn_x32_unpool_ukernel__wasmsimd( size_t offset = 0; do { const uint32_t i = *index++; - *((uint32_t*) ((uintptr_t) output[i] + offset)) = *input++; + const uint32_t v = *input++; + // Ignore indices outside the kernel_elements output pointers instead of + // dereferencing output[i] out of bounds. Valid unpooling indices are + // always < kernel_elements, so well-formed input is unaffected. + if (i < num_outputs) { + *((uint32_t*) ((uintptr_t) output[i] + offset)) = v; + } offset += sizeof(uint32_t); } while (--channels != 0); }