Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions io/io/src/TBufferFile.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -2963,9 +2963,12 @@ Version_t TBufferFile::ReadVersion(UInt_t *startpos, UInt_t *bcnt, const TClass
if (version<=1) {
if (version <= 0) {
if (cl) {
if (cl->GetClassVersion() != 0
auto clversion = cl->GetClassVersion();
if ((clversion != 0
// If v.cnt < 6 then we have a class with a version that used to be zero and so there is no checksum.
&& (v.cnt && v.cnt >= 6)
&& (v.cnt && v.cnt >= 6)) ||
// ::WriteVersion for a foreign class (no ClassDef) but defining Class_Version() { return 0; } does write checksum.
(clversion == 0 && version == 0 && cl->IsForeign())
) {
UInt_t checksum = 0;
//*this >> checksum;
Expand All @@ -2975,11 +2978,11 @@ Version_t TBufferFile::ReadVersion(UInt_t *startpos, UInt_t *bcnt, const TClass
return vinfo->TStreamerInfo::GetClassVersion(); // Try to get inlining.
} else {
// There are some cases (for example when the buffer was stored outside of
// a ROOT file) where we do not have a TStreamerInfo. If the checksum is
// a ROOT file) where we do not have a TStreamerInfo. If the checksum is
// the one from the current class, we can still assume that we can read
// the data so let use it.
if (checksum==cl->GetCheckSum() || cl->MatchLegacyCheckSum(checksum)) {
version = cl->GetClassVersion();
version = clversion;
} else {
if (fParent) {
Error("ReadVersion", "Could not find the StreamerInfo with a checksum of 0x%x for the class \"%s\" in %s.",
Expand Down
21 changes: 21 additions & 0 deletions io/io/test/TBufferFileTests.cxx
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
#include "gtest/gtest.h"

#include "TBufferFile.h"
#include "TMemFile.h"
#include "TClass.h"
#include "TInterpreter.h"
#include <vector>
#include <iostream>

Expand All @@ -26,3 +28,22 @@ TEST(TBufferFile, ROOT_8367)
EXPECT_FLOAT_EQ(v2[6], 7.);
EXPECT_EQ(v2.size(), 7);
}

// https://github.com/root-project/root/issues/19371
#define MYSTRUCT0 struct MyS0 { static constexpr short Class_Version() { return 0; } };
#define MYSTRUCT1 struct MyS1 { static constexpr short Class_Version() { return 1; } };
MYSTRUCT0
MYSTRUCT1
#define TO_LITERAL(string) _QUOTE_(string)
TEST(TBufferFile, ForeignZeroVersionClass)
{
gInterpreter->Declare(TO_LITERAL(MYSTRUCT0));
gInterpreter->Declare(TO_LITERAL(MYSTRUCT1));
MyS0 s0;
MyS1 s1;
TMemFile f("mem19371.root", "RECREATE");
f.WriteObject(&s0, "s0");
f.WriteObject(&s1, "s1");
EXPECT_NE(f.Get<MyS0>("s0"), nullptr); // Before the fix, even if return was already not nullptr, this line was raising an Error thus test would fail with unexpected diagnostic
EXPECT_NE(f.Get<MyS1>("s1"), nullptr);
}
Loading