Skip to content

Commit cdfceda

Browse files
committed
[io] Properly abort when buffer size overflows max integer
Fixes #14770
1 parent a0eb247 commit cdfceda

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

81 files changed

+394
-299
lines changed

core/base/inc/TBuffer.h

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,9 @@ class TBuffer : public TObject {
6464
void operator=(const TBuffer &) = delete;
6565

6666
Int_t Read(const char *name) override { return TObject::Read(name); }
67-
Int_t Write(const char *name, Int_t opt, Int_t bufsize) override
67+
Int_t Write(const char *name, Int_t opt, Long64_t bufsize) override
6868
{ return TObject::Write(name, opt, bufsize); }
69-
Int_t Write(const char *name, Int_t opt, Int_t bufsize) const override
69+
Int_t Write(const char *name, Int_t opt, Long64_t bufsize) const override
7070
{ return TObject::Write(name, opt, bufsize); }
7171

7272
public:
@@ -78,16 +78,16 @@ class TBuffer : public TObject {
7878
enum { kInitialSize = 1024, kMinimalSize = 128 };
7979

8080
TBuffer(EMode mode);
81-
TBuffer(EMode mode, Int_t bufsize);
82-
TBuffer(EMode mode, Int_t bufsize, void *buf, Bool_t adopt = kTRUE, ReAllocCharFun_t reallocfunc = nullptr);
81+
TBuffer(EMode mode, Long64_t bufsize);
82+
TBuffer(EMode mode, Long64_t bufsize, void *buf, Bool_t adopt = kTRUE, ReAllocCharFun_t reallocfunc = nullptr);
8383
virtual ~TBuffer();
8484

8585
Int_t GetBufferVersion() const { return fVersion; }
8686
Bool_t IsReading() const { return (fMode & kWrite) == 0; }
8787
Bool_t IsWriting() const { return (fMode & kWrite) != 0; }
8888
void SetReadMode();
8989
void SetWriteMode();
90-
void SetBuffer(void *buf, UInt_t bufsize = 0, Bool_t adopt = kTRUE, ReAllocCharFun_t reallocfunc = nullptr);
90+
void SetBuffer(void *buf, Long64_t bufsize = 0, Bool_t adopt = kTRUE, ReAllocCharFun_t reallocfunc = nullptr);
9191
ReAllocCharFun_t GetReAllocFunc() const;
9292
void SetReAllocFunc(ReAllocCharFun_t reallocfunc = nullptr);
9393
void SetBufferOffset(Int_t offset = 0) { fBufCur = fBuffer+offset; }
@@ -98,8 +98,8 @@ class TBuffer : public TObject {
9898
Int_t BufferSize() const { return fBufSize; }
9999
void DetachBuffer() { fBuffer = nullptr; }
100100
Int_t Length() const { return (Int_t)(fBufCur - fBuffer); }
101-
void Expand(Int_t newsize, Bool_t copy = kTRUE); // expand buffer to newsize
102-
void AutoExpand(Int_t size_needed); // expand buffer to newsize
101+
void Expand(Long64_t newsize, Bool_t copy = kTRUE); // expand buffer to newsize
102+
void AutoExpand(Long64_t size_needed); // expand buffer to newsize
103103
Bool_t ByteSwapBuffer(Long64_t n, EDataType type); // Byte-swap N primitive-elements in the buffer
104104

105105
virtual Bool_t CheckObject(const TObject *obj) = 0;

core/base/inc/TDirectory.h

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -254,20 +254,20 @@ can be replaced with the simpler and exception safe:
254254
virtual void Save() {}
255255
virtual Int_t SaveObjectAs(const TObject * /*obj*/, const char * /*filename*/="", Option_t * /*option*/="") const;
256256
virtual void SaveSelf(Bool_t /*force*/ = kFALSE) {}
257-
virtual void SetBufferSize(Int_t /* bufsize */) {}
257+
virtual void SetBufferSize(Long64_t /* bufsize */) {}
258258
virtual void SetModified() {}
259259
virtual void SetMother(TObject *mother) {fMother = (TObject*)mother;}
260260
void SetName(const char* newname) override;
261261
virtual void SetTRefAction(TObject * /*ref*/, TObject * /*parent*/) {}
262262
virtual void SetSeekDir(Long64_t) {}
263263
virtual void SetWritable(Bool_t) {}
264264
Int_t Sizeof() const override {return 0;}
265-
virtual Int_t Write(const char * /*name*/=nullptr, Int_t /*opt*/=0, Int_t /*bufsize*/=0) override {return 0;}
266-
virtual Int_t Write(const char * /*name*/=nullptr, Int_t /*opt*/=0, Int_t /*bufsize*/=0) const override {return 0;}
267-
virtual Int_t WriteTObject(const TObject *obj, const char *name =nullptr, Option_t * /*option*/="", Int_t /*bufsize*/ =0);
265+
virtual Int_t Write(const char * /*name*/=nullptr, Int_t /*opt*/=0, Long64_t /*bufsize*/=0) override {return 0;}
266+
virtual Int_t Write(const char * /*name*/=nullptr, Int_t /*opt*/=0, Long64_t /*bufsize*/=0) const override {return 0;}
267+
virtual Int_t WriteTObject(const TObject *obj, const char *name =nullptr, Option_t * /*option*/="", Long64_t /*bufsize*/ =0);
268268
private:
269269
/// \cond HIDDEN_SYMBOLS
270-
Int_t WriteObject(void *obj, const char* name, Option_t *option="", Int_t bufsize=0); // Intentionally not implemented.
270+
Int_t WriteObject(void *obj, const char* name, Option_t *option="", Long64_t bufsize=0); // Intentionally not implemented.
271271
/// \endcond
272272
public:
273273
/// \brief Write an object with proper type checking.
@@ -280,7 +280,7 @@ can be replaced with the simpler and exception safe:
280280
/// from TObject. The method redirects to TDirectory::WriteObjectAny.
281281
template <typename T>
282282
inline std::enable_if_t<!std::is_base_of<TObject, T>::value, Int_t>
283-
WriteObject(const T *obj, const char *name, Option_t *option = "", Int_t bufsize = 0)
283+
WriteObject(const T *obj, const char *name, Option_t *option = "", Long64_t bufsize = 0)
284284
{
285285
return WriteObjectAny(obj, TClass::GetClass<T>(), name, option, bufsize);
286286
}
@@ -294,12 +294,12 @@ can be replaced with the simpler and exception safe:
294294
/// TObject. The method redirects to TDirectory::WriteTObject.
295295
template <typename T>
296296
inline std::enable_if_t<std::is_base_of<TObject, T>::value, Int_t>
297-
WriteObject(const T *obj, const char *name, Option_t *option = "", Int_t bufsize = 0)
297+
WriteObject(const T *obj, const char *name, Option_t *option = "", Long64_t bufsize = 0)
298298
{
299299
return WriteTObject(obj, name, option, bufsize);
300300
}
301-
virtual Int_t WriteObjectAny(const void *, const char * /*classname*/, const char * /*name*/, Option_t * /*option*/="", Int_t /*bufsize*/ =0) {return 0;}
302-
virtual Int_t WriteObjectAny(const void *, const TClass * /*cl*/, const char * /*name*/, Option_t * /*option*/="", Int_t /*bufsize*/ =0) {return 0;}
301+
virtual Int_t WriteObjectAny(const void *, const char * /*classname*/, const char * /*name*/, Option_t * /*option*/="", Long64_t /*bufsize*/ =0) {return 0;}
302+
virtual Int_t WriteObjectAny(const void *, const TClass * /*cl*/, const char * /*name*/, Option_t * /*option*/="", Long64_t /*bufsize*/ =0) {return 0;}
303303
virtual void WriteDirHeader() {}
304304
virtual void WriteKeys() {}
305305

core/base/inc/TObject.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -170,8 +170,8 @@ class TObject {
170170
virtual void SetDrawOption(Option_t *option=""); // *MENU*
171171
virtual void SetUniqueID(UInt_t uid);
172172
virtual void UseCurrentStyle();
173-
virtual Int_t Write(const char *name = nullptr, Int_t option = 0, Int_t bufsize = 0);
174-
virtual Int_t Write(const char *name = nullptr, Int_t option = 0, Int_t bufsize = 0) const;
173+
virtual Int_t Write(const char *name = nullptr, Int_t option = 0, Long64_t bufsize = 0);
174+
virtual Int_t Write(const char *name = nullptr, Int_t option = 0, Long64_t bufsize = 0) const;
175175

176176
/// IsDestructed
177177
///

core/base/src/TBuffer.cxx

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -70,10 +70,10 @@ TBuffer::TBuffer(EMode mode)
7070
/// Create an I/O buffer object. Mode should be either TBuffer::kRead or
7171
/// TBuffer::kWrite.
7272

73-
TBuffer::TBuffer(EMode mode, Int_t bufsize)
73+
TBuffer::TBuffer(EMode mode, Long64_t bufsize)
7474
{
75-
if (bufsize < 0)
76-
Fatal("TBuffer","Request to create a buffer with a negative size, likely due to an integer overflow: 0x%x for a max of 0x%x.", bufsize, kMaxBufferSize);
75+
if (bufsize > kMaxBufferSize)
76+
Fatal("TBuffer","Request to create a too large buffer: 0x%llx for a max of 0x%x.", bufsize, kMaxBufferSize);
7777
if (bufsize < kMinimalSize) bufsize = kMinimalSize;
7878
fBufSize = bufsize;
7979
fMode = mode;
@@ -101,10 +101,10 @@ TBuffer::TBuffer(EMode mode, Int_t bufsize)
101101
/// is provided, a Fatal error will be issued if the Buffer attempts to
102102
/// expand.
103103

104-
TBuffer::TBuffer(EMode mode, Int_t bufsize, void *buf, Bool_t adopt, ReAllocCharFun_t reallocfunc)
104+
TBuffer::TBuffer(EMode mode, Long64_t bufsize, void *buf, Bool_t adopt, ReAllocCharFun_t reallocfunc)
105105
{
106-
if (bufsize < 0)
107-
Fatal("TBuffer","Request to create a buffer with a negative size, likely due to an integer overflow: 0x%x for a max of 0x%x.", bufsize, kMaxBufferSize);
106+
if (bufsize > kMaxBufferSize)
107+
Fatal("TBuffer","Request to create a too large buffer: 0x%llx for a max of 0x%x.", bufsize, kMaxBufferSize);
108108
fBufSize = bufsize;
109109
fMode = mode;
110110
fVersion = 0;
@@ -155,10 +155,10 @@ TBuffer::~TBuffer()
155155
/// If the size_needed is larger than the current size, the policy
156156
/// is to expand to double the current size or the size_needed which ever is largest.
157157

158-
void TBuffer::AutoExpand(Int_t size_needed)
158+
void TBuffer::AutoExpand(Long64_t size_needed)
159159
{
160-
if (size_needed < 0) {
161-
Fatal("AutoExpand","Request to expand to a negative size, likely due to an integer overflow: 0x%x for a max of 0x%x.", size_needed, kMaxBufferSize);
160+
if (size_needed > kMaxBufferSize) {
161+
Fatal("AutoExpand","Request to expand a too large buffer: 0x%llx for a max of 0x%x.", size_needed, kMaxBufferSize);
162162
}
163163
if (size_needed > fBufSize) {
164164
Long64_t doubling = 2LLU * fBufSize;
@@ -184,8 +184,10 @@ void TBuffer::AutoExpand(Int_t size_needed)
184184
/// is provided, a Fatal error will be issued if the Buffer attempts to
185185
/// expand.
186186

187-
void TBuffer::SetBuffer(void *buf, UInt_t newsiz, Bool_t adopt, ReAllocCharFun_t reallocfunc)
187+
void TBuffer::SetBuffer(void *buf, Long64_t newsiz, Bool_t adopt, ReAllocCharFun_t reallocfunc)
188188
{
189+
if (newsiz > kMaxBufferSize)
190+
Fatal("SetBuffer","Request to create a too large buffer: 0x%llx for a max of 0x%x.", newsiz, kMaxBufferSize);
189191
if (fBuffer && TestBit(kIsOwner))
190192
delete [] fBuffer;
191193

@@ -220,19 +222,19 @@ void TBuffer::SetBuffer(void *buf, UInt_t newsiz, Bool_t adopt, ReAllocCharFun_t
220222
/// In order to avoid losing data, if the current length is greater than
221223
/// the requested size, we only shrink down to the current length.
222224

223-
void TBuffer::Expand(Int_t newsize, Bool_t copy)
225+
void TBuffer::Expand(Long64_t newsize, Bool_t copy)
224226
{
225227
Int_t l = Length();
226-
if ( (l > newsize) && copy ) {
228+
if ( (Long64_t(l) > newsize) && copy ) {
227229
newsize = l;
228230
}
229231
const Int_t extraspace = (fMode&kWrite)!=0 ? kExtraSpace : 0;
230232

231-
if ( ((Long64_t)newsize+extraspace) > kMaxBufferSize) {
233+
if ( newsize > kMaxBufferSize - kExtraSpace) {
232234
if (l < kMaxBufferSize) {
233235
newsize = kMaxBufferSize - extraspace;
234236
} else {
235-
Fatal("Expand","Requested size (%d) is too large (max is %d).", newsize, kMaxBufferSize);
237+
Fatal("Expand","Requested size (%lld) is too large (max is %d).", newsize, kMaxBufferSize);
236238
}
237239
}
238240
if ( (fMode&kWrite)!=0 ) {

core/base/src/TDirectory.cxx

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -343,11 +343,12 @@ static TBuffer* R__CreateBuffer()
343343
if (!creator) {
344344
R__LOCKGUARD(gROOTMutex);
345345
TClass *c = TClass::GetClass("TBufferFile");
346-
TMethod *m = c->GetMethodWithPrototype("TBufferFile","TBuffer::EMode,Int_t",kFALSE,ROOT::kExactMatch);
346+
TMethod *m = c->GetMethodWithPrototype("TBufferFile","TBuffer::EMode,Long64_t",kFALSE,ROOT::kExactMatch);
347+
assert(m != nullptr);
347348
creator = (tcling_callfunc_Wrapper_t)( m->InterfaceMethod() );
348349
}
349350
TBuffer::EMode mode = TBuffer::kWrite;
350-
Int_t size = 10000;
351+
Long64_t size = 10000;
351352
void *args[] = { &mode, &size };
352353
TBuffer *result;
353354
creator(nullptr,2,args,&result);
@@ -1424,9 +1425,9 @@ void TDirectory::RegisterGDirectory(TDirectory::SharedGDirectory_t &gdirectory_p
14241425
}
14251426

14261427
////////////////////////////////////////////////////////////////////////////////
1427-
/// \copydoc TDirectoryFile::WriteObject(const T*,const char*,Option_t*,Int_t).
1428+
/// \copydoc TDirectoryFile::WriteObject(const T*,const char*,Option_t*,Long64_t).
14281429

1429-
Int_t TDirectory::WriteTObject(const TObject *obj, const char *name, Option_t * /*option*/, Int_t /*bufsize*/)
1430+
Int_t TDirectory::WriteTObject(const TObject *obj, const char *name, Option_t * /*option*/, Long64_t /*bufsize*/)
14301431
{
14311432
const char *objname = "no name specified";
14321433
if (name) objname = name;

core/base/src/TObject.cxx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -940,7 +940,7 @@ void TObject::UseCurrentStyle()
940940
/// The function returns the total number of bytes written to the file.
941941
/// It returns 0 if the object cannot be written.
942942

943-
Int_t TObject::Write(const char *name, Int_t option, Int_t bufsize) const
943+
Int_t TObject::Write(const char *name, Int_t option, Long64_t bufsize) const
944944
{
945945
if (R__unlikely(option & kOnlyPrepStep))
946946
return 0;
@@ -962,7 +962,7 @@ Int_t TObject::Write(const char *name, Int_t option, Int_t bufsize) const
962962
/// Write this object to the current directory. For more see the
963963
/// const version of this method.
964964

965-
Int_t TObject::Write(const char *name, Int_t option, Int_t bufsize)
965+
Int_t TObject::Write(const char *name, Int_t option, Long64_t bufsize)
966966
{
967967
return ((const TObject*)this)->Write(name, option, bufsize);
968968
}

core/cont/inc/TCollection.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -206,8 +206,8 @@ class TCollection : public TObject {
206206
void SetName(const char *name) { fName = name; }
207207
virtual void SetOwner(Bool_t enable = kTRUE);
208208
virtual bool UseRWLock(Bool_t enable = true);
209-
Int_t Write(const char *name = nullptr, Int_t option = 0, Int_t bufsize = 0) override;
210-
Int_t Write(const char *name = nullptr, Int_t option = 0, Int_t bufsize = 0) const override;
209+
Int_t Write(const char *name = nullptr, Int_t option = 0, Long64_t bufsize = 0) override;
210+
Int_t Write(const char *name = nullptr, Int_t option = 0, Long64_t bufsize = 0) const override;
211211

212212
R__ALWAYS_INLINE Bool_t IsUsingRWLock() const { return TestBit(TCollection::kUseRWLock); }
213213

core/cont/inc/TMap.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,8 @@ friend class TMapIter;
8484
TPair *RemoveEntry(TObject *key);
8585
virtual void SetOwnerValue(Bool_t enable = kTRUE);
8686
virtual void SetOwnerKeyValue(Bool_t ownkeys = kTRUE, Bool_t ownvals = kTRUE);
87-
Int_t Write(const char *name=nullptr, Int_t option=0, Int_t bufsize=0) override;
88-
Int_t Write(const char *name=nullptr, Int_t option=0, Int_t bufsize=0) const override;
87+
Int_t Write(const char *name=nullptr, Int_t option=0, Long64_t bufsize=0) override;
88+
Int_t Write(const char *name=nullptr, Int_t option=0, Long64_t bufsize=0) const override;
8989

9090
ClassDefOverride(TMap,3) //A (key,value) map
9191
};

core/cont/src/TCollection.cxx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -678,7 +678,7 @@ void TCollection::Streamer(TBuffer &b)
678678
/// objects using a single key specify a name and set option to
679679
/// TObject::kSingleKey (i.e. 1).
680680

681-
Int_t TCollection::Write(const char *name, Int_t option, Int_t bufsize) const
681+
Int_t TCollection::Write(const char *name, Int_t option, Long64_t bufsize) const
682682
{
683683
if ((option & kSingleKey)) {
684684
return TObject::Write(name, option, bufsize);
@@ -702,7 +702,7 @@ Int_t TCollection::Write(const char *name, Int_t option, Int_t bufsize) const
702702
/// objects using a single key specify a name and set option to
703703
/// TObject::kSingleKey (i.e. 1).
704704

705-
Int_t TCollection::Write(const char *name, Int_t option, Int_t bufsize)
705+
Int_t TCollection::Write(const char *name, Int_t option, Long64_t bufsize)
706706
{
707707
return ((const TCollection*)this)->Write(name,option,bufsize);
708708
}

core/cont/src/TMap.cxx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -402,7 +402,7 @@ void TMap::Streamer(TBuffer &b)
402402
/// objects using a single key specify a name and set option to
403403
/// TObject::kSingleKey (i.e. 1).
404404

405-
Int_t TMap::Write(const char *name, Int_t option, Int_t bufsize) const
405+
Int_t TMap::Write(const char *name, Int_t option, Long64_t bufsize) const
406406
{
407407
if ((option & kSingleKey)) {
408408
return TObject::Write(name, option, bufsize);
@@ -429,7 +429,7 @@ Int_t TMap::Write(const char *name, Int_t option, Int_t bufsize) const
429429
/// objects using a single key specify a name and set option to
430430
/// TObject::kSingleKey (i.e. 1).
431431

432-
Int_t TMap::Write(const char *name, Int_t option, Int_t bufsize)
432+
Int_t TMap::Write(const char *name, Int_t option, Long64_t bufsize)
433433
{
434434
return ((const TMap*)this)->Write(name,option,bufsize);
435435
}

0 commit comments

Comments
 (0)