Skip to content

Commit b7ce888

Browse files
committed
[net] fix handling of corrupt zip buffer in TMessage
1 parent f161165 commit b7ce888

File tree

2 files changed

+73
-6
lines changed

2 files changed

+73
-6
lines changed

io/io/test/ZipHeader.cxx

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,11 @@
55
#include <ROOT/RNTupleZip.hxx>
66
#include <ROOT/TestSupport.hxx>
77

8+
#include <Bytes.h>
89
#include <RZip.h>
910
#include <TKey.h>
1011
#include <TMemFile.h>
12+
#include <TMessage.h>
1113
#include <TNamed.h>
1214
#include <TTree.h>
1315
#include <TTreeCacheUnzip.h>
@@ -238,3 +240,43 @@ TEST(RZip, CorruptHeaderTTree)
238240
EXPECT_EQ(sizeof(int), tree->GetEntry(0));
239241
EXPECT_EQ(137, val);
240242
}
243+
244+
TEST(RZip, CorruptHeaderMessage)
245+
{
246+
TNamed named;
247+
named.SetName(std::string(1000, 'x').c_str());
248+
TMessage msg(kMESS_OBJECT | kMESS_ZIP);
249+
msg.SetCompressionSettings(101);
250+
msg.WriteObject(&named);
251+
252+
EXPECT_EQ(0, msg.Compress());
253+
EXPECT_TRUE(msg.CompBuffer());
254+
EXPECT_LT(msg.CompLength(), 1000);
255+
EXPECT_GT(msg.CompLength(), 9);
256+
257+
Int_t ziplen;
258+
Int_t what;
259+
Int_t length;
260+
char *bufcur = msg.CompBuffer();
261+
262+
frombuf(bufcur, &ziplen);
263+
EXPECT_EQ(msg.CompLength() - sizeof(UInt_t), ziplen);
264+
frombuf(bufcur, &what);
265+
EXPECT_EQ(kMESS_OBJECT | kMESS_ZIP, what);
266+
frombuf(bufcur, &length);
267+
EXPECT_EQ(length, msg.Length());
268+
269+
{
270+
ROOT::TestSupport::CheckDiagsRAII checkDiag;
271+
checkDiag.requiredDiag(kError, "TMessage::Uncompress", "objlenRemain", /* matchFullMessage= */ false);
272+
273+
bufcur[3]++;
274+
EXPECT_NE(0, msg.Uncompress());
275+
bufcur[3]--;
276+
bufcur[6]++;
277+
EXPECT_NE(0, msg.Uncompress());
278+
bufcur[6]--;
279+
}
280+
281+
EXPECT_EQ(0, msg.Uncompress());
282+
}

net/net/src/TMessage.cxx

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -409,15 +409,27 @@ Int_t TMessage::Uncompress()
409409
if (!fBufComp || !(fWhat & kMESS_ZIP))
410410
return -1;
411411

412+
Int_t nbytesRemain = CompLength();
413+
if (nbytesRemain < static_cast<Int_t>(3 * sizeof(Int_t))) {
414+
Error("Uncompress", "Compressed buffer too short (%d)", CompLength());
415+
return -1;
416+
}
412417
Int_t buflen;
413418
Int_t hdrlen = 2*sizeof(UInt_t);
414419
char *bufcur1 = fBufComp + hdrlen;
415420
frombuf(bufcur1, &buflen);
416421
UChar_t *bufcur = (UChar_t*)bufcur1;
422+
nbytesRemain -= 3 * sizeof(Int_t);
423+
424+
if (buflen < hdrlen) {
425+
Error("Uncompress", "Uncompressed buffer length too short (%d)", buflen);
426+
return -1;
427+
}
417428

418429
/* early consistency check */
419-
Int_t nin, nbuf;
420-
if(R__unzip_header(&nin, bufcur, &nbuf)!=0) {
430+
Int_t nin = 0;
431+
Int_t nbuf = 0;
432+
if ((nbytesRemain < ROOT::Internal::kZipHeaderSize) || R__unzip_header(&nin, bufcur, &nbuf) != 0) {
421433
Error("Uncompress", "Inconsistency found in header (nin=%d, nbuf=%d)", nin, nbuf);
422434
return -1;
423435
}
@@ -427,21 +439,34 @@ Int_t TMessage::Uncompress()
427439
fBufCur = fBuffer + sizeof(UInt_t) + sizeof(fWhat);
428440
fBufMax = fBuffer + fBufSize;
429441
char *messbuf = fBuffer + hdrlen;
430-
442+
431443
// Force being owner of the newly created buffer
432444
SetBit(kIsOwner);
433445

434-
Int_t nout;
446+
Int_t nout = 0;
435447
Int_t noutot = 0;
436-
while (1) {
448+
Int_t objlenRemain = buflen - hdrlen;
449+
while (nbytesRemain >= ROOT::Internal::kZipHeaderSize) {
437450
Int_t hc = R__unzip_header(&nin, bufcur, &nbuf);
438-
if (hc!=0) break;
451+
if ((hc != 0) || (nin > nbytesRemain) || (nbuf > objlenRemain))
452+
break;
439453
R__unzip(&nin, bufcur, &nbuf, (unsigned char*) messbuf, &nout);
440454
if (!nout) break;
441455
noutot += nout;
442456
if (noutot >= buflen - hdrlen) break;
443457
bufcur += nin;
444458
messbuf += nout;
459+
nbytesRemain -= nin;
460+
objlenRemain -= nout;
461+
}
462+
463+
if (noutot != buflen - hdrlen) {
464+
Error("Uncompress", "buflen = %d, objlenRemain = %d, noutot = %d, nout=%d, nin=%d, nbuf=%d", buflen, objlenRemain,
465+
noutot, nout, nin, nbuf);
466+
delete[] fBuffer;
467+
fBuffer = fBufCur = fBufMax = nullptr;
468+
fBufSize = 0;
469+
return -1;
445470
}
446471

447472
fWhat &= ~kMESS_ZIP;

0 commit comments

Comments
 (0)