From 70257cc409c6d21ee07eecb3153bb1dfc7f6be1e Mon Sep 17 00:00:00 2001 From: Nicholas Gates Date: Thu, 27 Aug 2026 13:19:06 -0400 Subject: [PATCH 1/3] ci: reject implicit engine buffer allocation Signed-off-by: Nicholas Gates --- .github/workflows/ci.yml | 5 +++ scripts/check-buffer-allocators.py | 59 ++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+) create mode 100644 scripts/check-buffer-allocators.py diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b364f0e8aca..08c6ca330bc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -349,6 +349,10 @@ jobs: id: fmt continue-on-error: true run: cargo +$NIGHTLY_TOOLCHAIN fmt --all --check + - name: Buffer allocator check + id: buffer-allocators + continue-on-error: true + run: python3 scripts/check-buffer-allocators.py - name: Rustc check id: check continue-on-error: true @@ -372,6 +376,7 @@ jobs: script: | const failed = Object.entries({ fmt: '${{ steps.fmt.outcome }}', + 'buffer-allocators': '${{ steps.buffer-allocators.outcome }}', check: '${{ steps.check.outcome }}', 'check-release': '${{ steps.check-release.outcome }}', 'clippy-all': '${{ steps.clippy-all.outcome }}', diff --git a/scripts/check-buffer-allocators.py b/scripts/check-buffer-allocators.py new file mode 100644 index 00000000000..13b7eab3f6b --- /dev/null +++ b/scripts/check-buffer-allocators.py @@ -0,0 +1,59 @@ +#!/usr/bin/env python3 + +import re +from pathlib import Path + + +ROOT = Path(__file__).resolve().parent.parent +PATHS = ( + "vortex-array/src/arrays/filter/execute", + "vortex-array/src/arrays/fixed_width/filter.rs", + "vortex-array/src/arrays/fixed_width/take", + "vortex-array/src/arrays/interleave/execute", + "vortex-array/src/patches.rs", + "vortex-array/src/scalar_fn/fns", +) +TYPES = r"(?:ByteBuffer|Buffer|BitBuffer|ByteBufferMut|BufferMut|BitBufferMut)" +METHODS = "|".join( + ( + "with_capacity", + "with_capacity_aligned", + "with_capacity_preferred_aligned", + "zeroed", + "zeroed_aligned", + "empty", + "empty_aligned", + "copy_from", + "copy_from_aligned", + "full", + "new_set", + "new_unset", + "collect_bool", + "collect_bool_multiversioned", + "from_trusted_len_iter", + "try_from_trusted_len_iter", + ) +) +STATIC_ALLOCATION = re.compile(rf"\b{TYPES}::(?:{METHODS})\s*\(") + + +def rust_files(path: Path): + files = path.rglob("*.rs") if path.is_dir() else (path,) + return ( + file + for file in files + if file.name != "tests.rs" and "tests" not in file.relative_to(ROOT).parts + ) + + +failures = [] +for relative in PATHS: + for file in rust_files(ROOT / relative): + for number, line in enumerate(file.read_text().splitlines(), 1): + if STATIC_ALLOCATION.search(line): + failures.append(f"{file.relative_to(ROOT)}:{number}: {line.strip()}") + +if failures: + print("Engine buffers must use an allocator-aware constructor ending in `_in`.") + print("\n".join(failures)) + raise SystemExit(1) From 5f284a8ede205e89a29127d4e5b65a7ed3d68cb1 Mon Sep 17 00:00:00 2001 From: Nicholas Gates Date: Fri, 28 Aug 2026 16:57:09 -0400 Subject: [PATCH 2/3] chore: license allocator enforcement script Signed-off-by: Nicholas Gates --- scripts/check-buffer-allocators.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/check-buffer-allocators.py b/scripts/check-buffer-allocators.py index 13b7eab3f6b..2d1634d4d08 100644 --- a/scripts/check-buffer-allocators.py +++ b/scripts/check-buffer-allocators.py @@ -1,4 +1,6 @@ #!/usr/bin/env python3 +# SPDX-License-Identifier: Apache-2.0 +# SPDX-FileCopyrightText: Copyright the Vortex contributors import re from pathlib import Path From 3e98c72135b794563e9dc46fd14fe4c71209f76e Mon Sep 17 00:00:00 2001 From: Nicholas Gates Date: Fri, 28 Aug 2026 20:01:05 -0400 Subject: [PATCH 3/3] chore: format allocator enforcement script Signed-off-by: Nicholas Gates --- scripts/check-buffer-allocators.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/scripts/check-buffer-allocators.py b/scripts/check-buffer-allocators.py index 2d1634d4d08..4b94503f83a 100644 --- a/scripts/check-buffer-allocators.py +++ b/scripts/check-buffer-allocators.py @@ -5,7 +5,6 @@ import re from pathlib import Path - ROOT = Path(__file__).resolve().parent.parent PATHS = ( "vortex-array/src/arrays/filter/execute", @@ -41,11 +40,7 @@ def rust_files(path: Path): files = path.rglob("*.rs") if path.is_dir() else (path,) - return ( - file - for file in files - if file.name != "tests.rs" and "tests" not in file.relative_to(ROOT).parts - ) + return (file for file in files if file.name != "tests.rs" and "tests" not in file.relative_to(ROOT).parts) failures = []