From 12d461cc9f4d7f9ab3946d4b4e839b0b59b2c166 Mon Sep 17 00:00:00 2001 From: silverweed Date: Wed, 29 Oct 2025 16:30:55 +0100 Subject: [PATCH] [ntuple] RNTupleDecompressor::Unzip: replace some asserts with exceptions These errors are due to misconstructed input rather than programming mistakes, so we should not assert on them, but give the caller the chance to handle them. --- tree/ntuple/inc/ROOT/RNTupleZip.hxx | 16 ++++++++++------ tree/ntuple/test/ntuple_zip.cxx | 13 +++++++++++++ 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/tree/ntuple/inc/ROOT/RNTupleZip.hxx b/tree/ntuple/inc/ROOT/RNTupleZip.hxx index 6a1cd72a3ff35..77bbd5f217e68 100644 --- a/tree/ntuple/inc/ROOT/RNTupleZip.hxx +++ b/tree/ntuple/inc/ROOT/RNTupleZip.hxx @@ -17,6 +17,8 @@ #include #include +#include + #include #include #include @@ -116,15 +118,17 @@ public: int szSource; int szTarget; int retval = R__unzip_header(&szSource, source, &szTarget); - R__ASSERT(retval == 0); - R__ASSERT(szSource > 0); - R__ASSERT(szTarget > szSource); - R__ASSERT(static_cast(szSource) <= nbytes); - R__ASSERT(static_cast(szTarget) <= dataLen); + if (R__unlikely(!((retval == 0) && (szSource > 0) && (szTarget > szSource) && + (static_cast(szSource) <= nbytes) && + (static_cast(szTarget) <= dataLen)))) { + throw ROOT::RException(R__FAIL("failed to unzip buffer header")); + } int unzipBytes = 0; R__unzip(&szSource, source, &szTarget, target, &unzipBytes); - R__ASSERT(unzipBytes == szTarget); + if (R__unlikely(unzipBytes != szTarget)) + throw ROOT::RException(R__FAIL(std::string("unexpected length after unzipping the buffer (wanted: ") + + std::to_string(szTarget) + ", got: " + std::to_string(unzipBytes) + ")")); target += szTarget; source += szSource; diff --git a/tree/ntuple/test/ntuple_zip.cxx b/tree/ntuple/test/ntuple_zip.cxx index c5eefffd9e08c..d1a2da7e91ae8 100644 --- a/tree/ntuple/test/ntuple_zip.cxx +++ b/tree/ntuple/test/ntuple_zip.cxx @@ -56,3 +56,16 @@ TEST(RNTupleZip, LargeWithOutputBuffer) RNTupleDecompressor::Unzip(zipBuffer.get(), szZip, N, unzipBuffer.get()); EXPECT_EQ(data, std::string_view(unzipBuffer.get(), N)); } + +TEST(RNTupleZip, CorruptedInput) +{ + std::string data = "xxxxxxxxxxxxxxxxxxxxxxxx"; + auto zipBuffer = MakeUninitArray(data.length()); + auto szZipped = RNTupleCompressor::Zip(data.data(), data.length(), 101, zipBuffer.get()); + EXPECT_LT(szZipped, data.length()); + auto unzipBuffer = MakeUninitArray(data.length()); + // corrupt the buffer header + memset(zipBuffer.get() + 1, 0xCD, 5); + EXPECT_THROW(RNTupleDecompressor::Unzip(zipBuffer.get(), szZipped, data.length(), unzipBuffer.get()), + ROOT::RException); +}