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