From dc47f83c1ae45b4d179d8fa62551618b919d30d8 Mon Sep 17 00:00:00 2001 From: RJ Ascani Date: Fri, 1 May 2026 16:51:33 -0700 Subject: [PATCH] Validate non-null data pointer in Tensor accessors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Summary: Add null-data-pointer validation to all six data accessor methods on the `Tensor` class (`const_data_ptr`, `mutable_data_ptr`, and deprecated `data_ptr` — two overloads each). The check fires when `numel() > 0` but the underlying `data_` pointer is null, which indicates an invalid tensor state. This prevents null pointer dereferences in all 225+ kernel implementations that call these accessors. The Lionhead fuzzer (`FuzzKernels` harness, T234178948) has been filing 50-100+ crash tasks because it constructs tensors with non-zero numel but null data pointers. Every kernel that dereferences the result of `const_data_ptr()` crashes. This centralized check catches the invalid state at the accessor level, eliminating the entire class of fuzzer findings. Tensors with `numel() == 0` and a null data pointer remain valid (empty tensors). Differential Revision: D103467785 --- runtime/core/portable_type/tensor.h | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/runtime/core/portable_type/tensor.h b/runtime/core/portable_type/tensor.h index 775bccc1b52..1a8644928b5 100644 --- a/runtime/core/portable_type/tensor.h +++ b/runtime/core/portable_type/tensor.h @@ -8,6 +8,7 @@ #pragma once +#include #include #include @@ -118,33 +119,57 @@ class Tensor { /// Returns a pointer of type T to the constant underlying data blob. template inline const T* const_data_ptr() const { + ET_CHECK_MSG( + numel() == 0 || impl_->data() != nullptr, + "Tensor has non-zero numel (%zd) but null data pointer", + (ssize_t)numel()); return impl_->data(); } /// Returns a pointer to the constant underlying data blob. inline const void* const_data_ptr() const { + ET_CHECK_MSG( + numel() == 0 || impl_->data() != nullptr, + "Tensor has non-zero numel (%zd) but null data pointer", + (ssize_t)numel()); return impl_->data(); } /// Returns a pointer of type T to the mutable underlying data blob. template inline T* mutable_data_ptr() const { + ET_CHECK_MSG( + numel() == 0 || impl_->data() != nullptr, + "Tensor has non-zero numel (%zd) but null data pointer", + (ssize_t)numel()); return impl_->mutable_data(); } /// Returns a pointer to the mutable underlying data blob. inline void* mutable_data_ptr() const { + ET_CHECK_MSG( + numel() == 0 || impl_->data() != nullptr, + "Tensor has non-zero numel (%zd) but null data pointer", + (ssize_t)numel()); return impl_->mutable_data(); } /// DEPRECATED: Use const_data_ptr or mutable_data_ptr instead. template ET_DEPRECATED inline T* data_ptr() const { + ET_CHECK_MSG( + numel() == 0 || impl_->data() != nullptr, + "Tensor has non-zero numel (%zd) but null data pointer", + (ssize_t)numel()); return impl_->mutable_data(); } /// DEPRECATED: Use const_data_ptr or mutable_data_ptr instead. ET_DEPRECATED inline void* data_ptr() const { + ET_CHECK_MSG( + numel() == 0 || impl_->data() != nullptr, + "Tensor has non-zero numel (%zd) but null data pointer", + (ssize_t)numel()); return impl_->mutable_data(); }