Skip to content

Commit 5034e3a

Browse files
committed
[tree] fix handling of corrupt zip buffer in TTreeCacheUnzip
1 parent 7e90e88 commit 5034e3a

File tree

2 files changed

+35
-4
lines changed

2 files changed

+35
-4
lines changed

io/io/test/ZipHeader.cxx

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <TMemFile.h>
1111
#include <TNamed.h>
1212
#include <TTree.h>
13+
#include <TTreeCacheUnzip.h>
1314

1415
#include <cstring>
1516
#include <memory>
@@ -165,7 +166,7 @@ TEST(RZip, CorruptHeaderTKey)
165166
EXPECT_TRUE(verifyFile.Get<TNamed>("tnamed"));
166167
}
167168

168-
TEST(RZip, CorruptHeaderTBasket)
169+
TEST(RZip, CorruptHeaderTTree)
169170
{
170171
TMemFile writableFile("memfile.root", "RECREATE");
171172
writableFile.SetCompressionSettings(101);
@@ -178,13 +179,15 @@ TEST(RZip, CorruptHeaderTBasket)
178179

179180
auto keysInfo = writableFile.WalkTKeys();
180181
std::size_t posTBasket = 0;
182+
std::size_t keylenTBasket = 0;
181183
for (const auto &ki : keysInfo) {
182184
if (ki.fClassName != "TBasket")
183185
continue;
184186

185187
EXPECT_EQ(0u, posTBasket); // We expect only one basket
186188
EXPECT_LT(ki.fLen, ki.fObjLen); // ensure it's compressed
187189
posTBasket = ki.fSeekKey + ki.fKeyLen;
190+
keylenTBasket = ki.fKeyLen;
188191
}
189192
EXPECT_GT(posTBasket, 0);
190193

@@ -207,6 +210,27 @@ TEST(RZip, CorruptHeaderTBasket)
207210
buffer[posTBasket + headerOffset]--;
208211
}
209212

213+
{
214+
TMemFile verifyFile("memfile.root", TMemFile::ZeroCopyView_t(buffer.get(), writableFile.GetSize()));
215+
216+
tree = verifyFile.Get<TTree>("t");
217+
218+
TTreeCacheUnzip cache(tree);
219+
char *dest = nullptr;
220+
221+
for (int headerOffset : {3, 6}) {
222+
ROOT::TestSupport::CheckDiagsRAII checkDiag;
223+
checkDiag.requiredDiag(kError, "TTreeCacheUnzip::UnzipBuffer", "nbytes", /* matchFullMessage= */ false);
224+
225+
buffer[posTBasket + headerOffset]++;
226+
EXPECT_EQ(-1, cache.UnzipBuffer(&dest, &buffer[posTBasket - keylenTBasket]));
227+
buffer[posTBasket + headerOffset]--;
228+
}
229+
230+
EXPECT_GT(cache.UnzipBuffer(&dest, &buffer[posTBasket - keylenTBasket]), 0);
231+
delete[] dest;
232+
}
233+
210234
TMemFile verifyFile("memfile.root", TMemFile::ZeroCopyView_t(buffer.get(), writableFile.GetSize()));
211235
tree = verifyFile.Get<TTree>("t");
212236
tree->SetBranchAddress("val", &val);

tree/tree/src/TTreeCacheUnzip.cxx

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -858,11 +858,15 @@ Int_t TTreeCacheUnzip::UnzipBuffer(char **dest, char *src)
858858
Int_t nbytes = 0, objlen = 0, keylen = 0;
859859
GetRecordHeader(src, hlen, nbytes, objlen, keylen);
860860

861+
Int_t nbytesRemain = nbytes - keylen;
862+
Int_t objlenRemain = objlen;
863+
861864
if (!(*dest)) {
862865
/* early consistency check */
863866
UChar_t *bufcur = (UChar_t *) (src + keylen);
864867
Int_t nin, nbuf;
865-
if(objlen > nbytes - keylen && R__unzip_header(&nin, bufcur, &nbuf) != 0) {
868+
if((objlen > nbytes - keylen) &&
869+
((nbytesRemain < ROOT::Internal::kZipHeaderSize) || (R__unzip_header(&nin, bufcur, &nbuf) != 0))) {
866870
Error("UnzipBuffer", "Inconsistency found in header (nin=%d, nbuf=%d)", nin, nbuf);
867871
uzlen = -1;
868872
return uzlen;
@@ -893,9 +897,10 @@ Int_t TTreeCacheUnzip::UnzipBuffer(char **dest, char *src)
893897
Int_t nout = 0;
894898
Int_t noutot = 0;
895899

896-
while (true) {
900+
while (nbytesRemain >= ROOT::Internal::kZipHeaderSize) {
897901
Int_t hc = R__unzip_header(&nin, bufcur, &nbuf);
898-
if (hc != 0) break;
902+
if ((hc != 0) || (nin > nbytesRemain) || (nbuf > objlenRemain))
903+
break;
899904
if (gDebug > 2)
900905
Info("UnzipBuffer", " nin:%d, nbuf:%d, bufcur[3] :%d, bufcur[4] :%d, bufcur[5] :%d ",
901906
nin, nbuf, bufcur[3], bufcur[4], bufcur[5]);
@@ -920,6 +925,8 @@ Int_t TTreeCacheUnzip::UnzipBuffer(char **dest, char *src)
920925
if (noutot >= objlen) break;
921926
bufcur += nin;
922927
objbuf += nout;
928+
nbytesRemain -= nin;
929+
objlenRemain -= nout;
923930
}
924931

925932
if (noutot != objlen) {

0 commit comments

Comments
 (0)