@@ -1296,6 +1296,132 @@ void TKey::ReadKeyBuffer(char *&buffer)
12961296 fTitle .ReadBuffer (buffer);
12971297}
12981298
1299+ // //////////////////////////////////////////////////////////////////////////////
1300+ // / Decode input buffer.
1301+ // / \return true if decoding was successful.
1302+
1303+ bool TKey::ReadKeyBuffer (char *&buffer, std::size_t bufsize)
1304+ {
1305+ // NOTE: this is not a lambda because we want [[nodiscard]].
1306+ struct {
1307+ TKey *fOuter ;
1308+ std::size_t fRemainingBufSize ;
1309+ [[nodiscard]] bool operator ()(std::size_t additionalBytesNeeded) {
1310+ if (R__unlikely (additionalBytesNeeded > fRemainingBufSize )) {
1311+ fOuter ->Error (" ReadKeyBuffer" , " The given buffer is too small to fit this TKey." );
1312+ fOuter ->MakeZombie ();
1313+ return false ;
1314+ }
1315+ fRemainingBufSize -= additionalBytesNeeded;
1316+ return true ;
1317+ }
1318+ } ConsumeBufCapacity{this , bufsize};
1319+
1320+ // Min size of the buffer for reading the common key header data
1321+ constexpr std::size_t kMinBufSize =
1322+ sizeof (fNbytes ) + sizeof (Version_t) + sizeof (fObjlen ) + sizeof (fKeylen ) + sizeof (fCycle );
1323+ if (!ConsumeBufCapacity (kMinBufSize ))
1324+ return false ;
1325+
1326+ frombuf (buffer, &fNbytes );
1327+ if (fNbytes < 0 ) {
1328+ Error (" ReadKeyBuffer" , " The value of fNbytes is negative (%d): cannot continue to read the key buffer." , fNbytes );
1329+ MakeZombie ();
1330+ fNbytes = 0 ;
1331+ return false ;
1332+ }
1333+ Version_t version;
1334+ frombuf (buffer,&version);
1335+ fVersion = (Int_t)version;
1336+ frombuf (buffer, &fObjlen );
1337+ if (fObjlen < 0 ) {
1338+ Error (" ReadKeyBuffer" , " The value of fObjlen is negative (%d): cannot continue to read the key buffer." , fObjlen );
1339+ MakeZombie ();
1340+ fObjlen = 0 ;
1341+ return false ;
1342+ }
1343+ fDatime .ReadBuffer (buffer);
1344+ frombuf (buffer, &fKeylen );
1345+ if (fKeylen < 0 ) {
1346+ Error (" ReadKeyBuffer" , " The value of fKeylen is negative (%d): cannot continue to read the key buffer." , fKeylen );
1347+ MakeZombie ();
1348+ fKeylen = 0 ;
1349+ return false ;
1350+ }
1351+
1352+ if (fNbytes < fKeylen ) {
1353+ Error (" ReadKeyBuffer" , " fNbytes (%d) < fKeylen (%d): cannot continue to read the key buffer." , fNbytes , fKeylen );
1354+ MakeZombie ();
1355+ return false ;
1356+ }
1357+
1358+ constexpr auto maxInt_t = std::numeric_limits<Int_t>::max ();
1359+ if (fKeylen > (maxInt_t - fObjlen )) {
1360+ Error (" ReadKeyBuffer" , " fObjlen (%d) + fKeylen (%d) > max int (%d): cannot continue to read the key buffer." , fObjlen , fKeylen , maxInt_t);
1361+ MakeZombie ();
1362+ return false ;
1363+ }
1364+
1365+ frombuf (buffer, &fCycle );
1366+ // The initial bufsize check guarantees that we could read up to here.
1367+ // From now on we need to be careful.
1368+
1369+ if (fVersion > 1000 ) {
1370+ if (!ConsumeBufCapacity (sizeof (fSeekKey ) + sizeof (Long64_t)))
1371+ return false ;
1372+
1373+ frombuf (buffer, &fSeekKey );
1374+
1375+ // We currently store in the 16 highest bit of fSeekPdir the value of
1376+ // fPidOffset. This offset is used when a key (or basket) is transferred from one
1377+ // file to the other. In this case the TRef and TObject might have stored a
1378+ // pid index (to retrieve TProcessIDs) which refered to their order on the original
1379+ // file, the fPidOffset is to be added to those values to correctly find the
1380+ // TProcessID. This fPidOffset needs to be increment if the key/basket is copied
1381+ // and need to be zero for new key/basket.
1382+ Long64_t pdir;
1383+ frombuf (buffer, &pdir);
1384+ fPidOffset = pdir >> kPidOffsetShift ;
1385+ fSeekPdir = pdir & kPidOffsetMask ;
1386+ } else {
1387+ if (!ConsumeBufCapacity (2 * sizeof (UInt_t)))
1388+ return false ;
1389+
1390+ UInt_t seekkey,seekdir;
1391+ frombuf (buffer, &seekkey);
1392+ fSeekKey = (Long64_t)seekkey;
1393+ frombuf (buffer, &seekdir);
1394+ fSeekPdir = (Long64_t)seekdir;
1395+ }
1396+
1397+ auto nRead = fClassName .ReadBuffer (buffer, ConsumeBufCapacity.fRemainingBufSize );
1398+ if (!nRead) {
1399+ MakeZombie ();
1400+ return false ;
1401+ }
1402+ ConsumeBufCapacity.fRemainingBufSize -= nRead;
1403+
1404+ // the following test required for forward and backward compatibility
1405+ if (fClassName == " TDirectory" ) {
1406+ fClassName = " TDirectoryFile" ;
1407+ SetBit (kIsDirectoryFile );
1408+ }
1409+
1410+ nRead = fName .ReadBuffer (buffer, ConsumeBufCapacity.fRemainingBufSize );
1411+ if (!nRead) {
1412+ MakeZombie ();
1413+ return false ;
1414+ }
1415+ ConsumeBufCapacity.fRemainingBufSize -= nRead;
1416+
1417+ nRead = fTitle .ReadBuffer (buffer, ConsumeBufCapacity.fRemainingBufSize );
1418+ if (!nRead) {
1419+ MakeZombie ();
1420+ return false ;
1421+ }
1422+ return true ;
1423+ }
1424+
12991425// //////////////////////////////////////////////////////////////////////////////
13001426// / Read the key structure from the file
13011427
0 commit comments