Skip to content

Validate the arguments of pad and tile - #2960

Open
gouarin wants to merge 1 commit into
xtensor-stack:masterfrom
gouarin:fix-pad-tile-validation
Open

gouarin wants to merge 1 commit into
xtensor-stack:masterfrom
gouarin:fix-pad-tile-validation

Conversation

@gouarin

@gouarin gouarin commented Oct 29, 2026

Copy link
Copy Markdown
Member

Checklist

  • The title and commit message(s) are descriptive.
  • Small commits made to fix your PR have been squashed to avoid history pollution.
  • Tests have been added for new features or bug fixes.
  • API of new functions and classes are documented (no public API changes).

Description

pad and tile index their argument by axis, but only checked its size with XTENSOR_ASSERT, which is off in release builds. The limits of each pad mode were not checked in release either:

xt::xtensor<int, 2> a = {{1, 2, 3}, {4, 5, 6}};
xt::pad(a, std::vector<std::vector<std::size_t>>{{1, 1}});  // heap-buffer-overflow
xt::pad(a, {{5, 5}, {1, 1}}, xt::pad_mode::wrap);           // uninitialized values
xt::xtensor<int, 1> b = {1, 2, 3};
xt::tile(b, {2u, 3u});                                      // stack-buffer-overflow
xt::xarray<int> s = 5;
xt::tile(s, 3u);                                            // null dereference

Too many pairs were silently ignored, reflect with a width of at least the axis size and edge on an empty axis returned uninitialized values, and negative widths or repetitions wrapped to huge sizes.

These cases now throw std::runtime_error before the result is allocated. The loops in tile use the dimension of the expression for every buffer they index, which also removes the GCC 13 -O3 -Wstringop-overflow warning on its slice vector.

xpad.invalid_pad_width and xpad.tile_invalid_reps fail on master under AddressSanitizer and pass with the fix. xpad.largest_pad_width checks that the largest valid width of each mode still works.

pad and tile take one value, or one pair of values, per axis of the
expression and index their argument by axis. The sizes were only
checked by XTENSOR_ASSERT, which is off in release builds, and the
limits of each pad mode were not checked at all in release:

- pad with fewer pairs than axes, or pairs with fewer than two values,
  read past the end of pad_width (heap-buffer-overflow);
- pad with more pairs than axes ignored the extra ones;
- wrap, periodic and symmetric with a width larger than the axis, or
  reflect with a width of at least its size, and edge on an empty
  axis, returned uninitialized values;
- tile with more repetitions than axes wrote past the std::array shape
  of an xtensor (stack-buffer-overflow), and with fewer it built a
  garbage shape;
- tile(e, n) on a 0-D expression wrote to an empty std::vector;
- negative widths or repetitions wrapped around to huge sizes.

These cases now throw std::runtime_error before the result is
allocated. The loops of tile use the dimension of the expression for
every buffer they index, which also removes the GCC 13 -O3
-Wstringop-overflow warning on its slice vector.
@codspeed

codspeed Bot commented Oct 29, 2026

Copy link
Copy Markdown
Contributor

Merging this PR will not alter performance

1 warning

⚠️ Unable to measure the execution of 1 benchmark

This benchmark measured no execution time, so its result is not comparable and counts as unchanged. This usually happens when the compiler removes the code under test.

Prevent compiler optimizations

See affected benchmarks

✅ 255 untouched benchmarks


Comparing gouarin:fix-pad-tile-validation (4dccb74) with master (57f3d07)

Open in CodSpeed

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant