Skip to content

Commit 4686fed

Browse files
committed
[ntuple] Implement RField<TObject>::ReadInClusterImpl
Otherwise RFieldBase::ReadInClusterImpl tries to use the principal column to translate to a global index, which results in a nullptr dereference. Fixes #18404
1 parent 57406f3 commit 4686fed

File tree

3 files changed

+48
-0
lines changed

3 files changed

+48
-0
lines changed

Diff for: tree/ntuple/inc/ROOT/RField.hxx

+1
Original file line numberDiff line numberDiff line change
@@ -473,6 +473,7 @@ protected:
473473
std::size_t AppendImpl(const void *from) final;
474474
void ReadTObject(void *to, UInt_t uniqueID, UInt_t bits);
475475
void ReadGlobalImpl(ROOT::NTupleSize_t globalIndex, void *to) final;
476+
void ReadInClusterImpl(RNTupleLocalIndex localIndex, void *to) final;
476477

477478
void AfterConnectPageSource() final;
478479

Diff for: tree/ntuple/src/RFieldMeta.cxx

+8
Original file line numberDiff line numberDiff line change
@@ -1005,6 +1005,14 @@ void ROOT::RField<TObject>::ReadGlobalImpl(ROOT::NTupleSize_t globalIndex, void
10051005
ReadTObject(to, uniqueID, bits);
10061006
}
10071007

1008+
void ROOT::RField<TObject>::ReadInClusterImpl(RNTupleLocalIndex localIndex, void *to)
1009+
{
1010+
UInt_t uniqueID, bits;
1011+
CallReadOn(*fSubfields[0], localIndex, &uniqueID);
1012+
CallReadOn(*fSubfields[1], localIndex, &bits);
1013+
ReadTObject(to, uniqueID, bits);
1014+
}
1015+
10081016
void ROOT::RField<TObject>::AfterConnectPageSource()
10091017
{
10101018
if (GetOnDiskTypeVersion() != 1) {

Diff for: tree/ntuple/test/rfield_vector.cxx

+39
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
#include "ntuple_test.hxx"
22

3+
#include <TObject.h>
4+
35
// A layer of indirection to hide std::vector's second template parameter.
46
// This way we can generalize tests over RVec and std::vector using a template template parameter (see below).
57
template <typename T>
@@ -494,3 +496,40 @@ TEST(RNTuple, VectorOfBitset)
494496
EXPECT_EQ("111", ptrVecOfBitset->at(0).to_string());
495497
EXPECT_EQ("000", ptrVecOfBitset->at(1).to_string());
496498
}
499+
500+
TEST(RNTuple, VectorOfTObject)
501+
{
502+
FileRaii fileGuard("test_ntuple_vector_of_tobject.root");
503+
{
504+
auto model = RNTupleModel::Create();
505+
auto objs = model->MakeField<std::vector<TObject>>("objs");
506+
auto writer = RNTupleWriter::Recreate(std::move(model), "ntpl", fileGuard.GetPath());
507+
508+
TObject obj;
509+
obj.SetUniqueID(42);
510+
objs->push_back(obj);
511+
obj.SetUniqueID(43);
512+
objs->push_back(obj);
513+
writer->Fill();
514+
writer->CommitCluster();
515+
516+
objs->clear();
517+
obj.SetUniqueID(44);
518+
objs->push_back(obj);
519+
writer->Fill();
520+
}
521+
522+
auto reader = RNTupleReader::Open("ntpl", fileGuard.GetPath());
523+
ASSERT_EQ(2u, reader->GetNEntries());
524+
auto &entry = reader->GetModel().GetDefaultEntry();
525+
auto objs = entry.GetPtr<std::vector<TObject>>("objs");
526+
527+
reader->LoadEntry(0);
528+
ASSERT_EQ(2u, objs->size());
529+
EXPECT_EQ(42u, objs->at(0).GetUniqueID());
530+
EXPECT_EQ(43u, objs->at(1).GetUniqueID());
531+
532+
reader->LoadEntry(1);
533+
ASSERT_EQ(1u, objs->size());
534+
EXPECT_EQ(44u, objs->at(0).GetUniqueID());
535+
}

0 commit comments

Comments
 (0)