diff --git a/io/io/src/TKey.cxx b/io/io/src/TKey.cxx index 7107b05cb1daa..3a3e196387324 100644 --- a/io/io/src/TKey.cxx +++ b/io/io/src/TKey.cxx @@ -81,6 +81,18 @@ const static TString gTDirectoryString("TDirectory"); std::atomic keyAbsNumber{0}; ClassImp(TKey); +namespace { +bool CheckKeyObjLenOverflow(const char *methodName, Int_t keyLen, Int_t objLen) +{ + constexpr auto maxInt_t = std::numeric_limits::max(); + if (keyLen > (maxInt_t - objLen)) { + Error(methodName, "fObjlen (%d) + fKeylen (%d) > max int (%d): cannot continue to read the key buffer.", objLen, + keyLen, maxInt_t); + return true; + } + return false; +} +} // namespace //////////////////////////////////////////////////////////////////////////////// /// TKey default constructor. @@ -1264,9 +1276,9 @@ void TKey::ReadKeyBuffer(char *&buffer) return; } - constexpr auto maxInt_t = std::numeric_limits::max(); - if (fKeylen > (maxInt_t - fObjlen)) { - Error("ReadKeyBuffer", "fObjlen (%d) + fKeylen (%d) > max int (%d): cannot continue to read the key buffer.", fObjlen, fKeylen, maxInt_t); + if(CheckKeyObjLenOverflow("ReadKeyBuffer", fKeylen, fObjlen)){ + fKeylen = 0; + fObjlen = 0; MakeZombie(); return; } @@ -1442,6 +1454,10 @@ void TKey::Streamer(TBuffer &b) MakeZombie(); fNbytes = 0; } + if (CheckKeyObjLenOverflow("Streamer", fKeylen, fObjlen)) { + MakeZombie(); + return; + } } else { b << fNbytes; diff --git a/tree/tree/src/TBasket.cxx b/tree/tree/src/TBasket.cxx index 8f82dcdb940d7..0d06fd9b82099 100644 --- a/tree/tree/src/TBasket.cxx +++ b/tree/tree/src/TBasket.cxx @@ -9,6 +9,7 @@ *************************************************************************/ #include +#include #include "TBasket.h" #include "TBuffer.h" @@ -32,6 +33,7 @@ const UInt_t kDisplacementMask = 0xFF000000; // In the streamer the two highest // the fEntryOffset are used to stored displacement. ClassImp(TBasket); +constexpr auto gMaxInt_t = std::numeric_limits::max(); /** \class TBasket \ingroup tree @@ -576,6 +578,31 @@ Int_t TBasket::ReadBasketBuffers(Long64_t pos, Int_t len, TFile *file) memcpy(rawCompressedBuffer, fBufferRef->Buffer(), len); } } + // Sanitize nbytes and lengths + if (fKeylen < 0) { + Error("ReadBasketBuffers", "The value of fKeylen is incorrect (%d) ; trying to recover by setting it to zero", fKeylen); + MakeZombie(); + fKeylen = 0; + return 1; + } + if (fObjlen < 0) { + Error("ReadBasketBuffers", "The value of fObjlen is incorrect (%d) ; trying to recover by setting it to zero", fObjlen); + MakeZombie(); + fObjlen = 0; + return 1; + } + if (fNbytes < 0) { + Error("ReadBasketBuffers", "The value of fNbytes is incorrect (%d) ; trying to recover by setting it to zero", fNbytes); + MakeZombie(); + fNbytes = 0; + return 1; + } + if (fKeylen > (gMaxInt_t - fObjlen)) { + Error("ReadBasketBuffers", "fObjlen (%d) + fKeylen (%d) > max int (%d): cannot continue to read the key buffer.", + fObjlen, fKeylen, gMaxInt_t); + MakeZombie(); + return 1; + } // Initialize buffer to hold the uncompressed data // Note that in previous versions we didn't allocate buffers until we verified