From 694be047e7c86a2c7965210d6900c1bf8c0b9841 Mon Sep 17 00:00:00 2001 From: LTLA Date: Sat, 20 Jul 2024 23:40:18 -0700 Subject: [PATCH] Avoid potential UB from an unused invalid pointer address. This primarily happens when doing big jumps through a 2D array; regular pointer arithmetic on a 1D array should be safe as they never need to do these jumps. --- include/tatami/dense/transpose.hpp | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/include/tatami/dense/transpose.hpp b/include/tatami/dense/transpose.hpp index a9a42560..7b79cdc5 100644 --- a/include/tatami/dense/transpose.hpp +++ b/include/tatami/dense/transpose.hpp @@ -42,15 +42,18 @@ void transpose(const Input_* input, size_t nrow, size_t ncol, size_t input_strid while (row_start < nrow) { size_t row_end = row_start + std::min(block, nrow - row_start); - auto input2 = input + col_start + row_start * input_stride; - auto output2 = output + col_start * output_stride + row_start; + // We use offsets instead of directly performing pointer + // arithmetic, to avoid creating an invalid pointer address (which + // is UB, even if unused) after the last inner loop iteration. + size_t input_offset = col_start + row_start * input_stride; + size_t output_offset = col_start * output_stride + row_start; - for (size_t c = col_start; c < col_end; ++c, ++input2, output2 += output_stride) { - auto input_copy = input2; - auto output_copy = output2; + for (size_t c = col_start; c < col_end; ++c, ++input_offset, output_offset += output_stride) { + auto input_offset_copy = input_offset; + auto output_offset_copy = output_offset; - for (size_t r = row_start; r < row_end; ++r, input_copy += input_stride, ++output_copy) { - *output_copy = *input_copy; + for (size_t r = row_start; r < row_end; ++r, input_offset_copy += input_stride, ++output_offset_copy) { + output[output_offset_copy] = input[input_offset_copy]; } }