From d05cd28ed7dcac4e1d31b6cc96ae588bb30e5132 Mon Sep 17 00:00:00 2001 From: Sheldon Bernstein Date: Fri, 5 Jun 2026 16:07:28 -0600 Subject: [PATCH 1/2] Bound header_length and check shape-product overflow when loading .npy Adds input validation to read_header/comp_size (reported in #44): - cap the attacker-controlled v2 header_length (16 MiB, well above any real header) before allocating, so a tiny crafted file can no longer force a multi-gigabyte allocation (CWE-789) - reject shape-dimension products that overflow ndarray_len_t (CWE-190) --- include/npy.hpp | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/include/npy.hpp b/include/npy.hpp index 3898e87..447d370 100644 --- a/include/npy.hpp +++ b/include/npy.hpp @@ -445,6 +445,15 @@ inline std::string read_header(std::istream &istream) { throw std::runtime_error("unsupported file format version"); } + // Bound the attacker-controlled header_length before allocating: a crafted .npy can + // declare header_length up to 4 GiB (v2 u32), forcing a huge allocation (DoS). The cap + // is generous (well above any real header, which is at most a few hundred KB even for + // large structured dtypes) so legitimate v1 and v2 files are unaffected; tune as needed. + static const uint32_t max_header_length = 16u * 1024u * 1024u; + if (header_length > max_header_length) { + throw std::runtime_error("invalid file format: header_length exceeds maximum"); + } + auto buf_v = std::vector(header_length); istream.read(buf_v.data(), header_length); std::string header(buf_v.data(), header_length); @@ -454,7 +463,13 @@ inline std::string read_header(std::istream &istream) { inline ndarray_len_t comp_size(const shape_t &shape) { ndarray_len_t size = 1; - for (ndarray_len_t i : shape) size *= i; + for (ndarray_len_t i : shape) { + // Reject overflow of the shape product (CWE-190): a wrapped product yields a + // silent undersized buffer or a giant allocation downstream. + if (i != 0 && size > std::numeric_limits::max() / i) + throw std::runtime_error("invalid file format: shape product overflow"); + size *= i; + } return size; } From eef12f90f7e0434225645732ccfbb962e23289b8 Mon Sep 17 00:00:00 2001 From: Sheldon Bernstein Date: Sat, 6 Jun 2026 11:56:48 -0600 Subject: [PATCH 2/2] Add missing #include for std::numeric_limits (fixes CI build) --- include/npy.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/include/npy.hpp b/include/npy.hpp index 447d370..2bd1261 100644 --- a/include/npy.hpp +++ b/include/npy.hpp @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include