Skip to content

[io] TList is not correctly reconstructed from TBuffer #17206

Open
@linev

Description

@linev

Check duplicate issues.

  • Checked for duplicates

Description

Following list is not correctly reconstructed:

   TList lst0;
   lst0.Add(new TNamed("name0", "title0"));  // without option
   lst0.Add(new TNamed("name1", "title1"), ""); // with empty option
   lst0.Add(new TNamed("name2", "title2"), "option2"); // with non-empty option

Problem is second element - with empty option.
In the TList it is stored as TObjOptLink. One can change option and option is independent from the object itself.

If such TList read from buffer, for second entry TObjLink is created. Means option cannot be changed. And link->GetOption() returns option from the object - which can be not empty.

Both caveats lead to problems with TPad list of primitives. If TCanvas read from the file, suddenly draw option for histogram or for title may be changed - while instead reading empty option from TObjOptLink some default option from histogram or from title will be returned. Also TObject::SetDrawOption() will fail.

Related problem with JSON storage was resolved in #17198

Reproducer

TEST(TMemFile, TList_Add_Without_Option)
{
   TList lst0;
   lst0.Add(new TNamed("name0", "title0"));  // without option
   lst0.Add(new TNamed("name1", "title1"), ""); // with empty option
   lst0.Add(new TNamed("name2", "title2"), "option2"); // with non-empty option

   auto f = new TMemFile("test.root", "RECREATE");
   f->WriteTObject(&lst0, "list");

   lst0.Delete();

   auto lst1 = f->Get<TList>("list");
   delete f;

   EXPECT_NE(lst1, nullptr);

   auto link = lst1->FirstLink();

   EXPECT_STREQ("name0", link->GetObject()->GetName());
   EXPECT_STREQ("title0", link->GetObject()->GetTitle());
   EXPECT_STREQ("", link->GetAddOption()); // by default empty string returned
   EXPECT_EQ(dynamic_cast<TObjOptLink *>(link), nullptr);

   link = link->Next();

   EXPECT_STREQ("name1", link->GetObject()->GetName());
   EXPECT_STREQ("title1", link->GetObject()->GetTitle());
   EXPECT_STREQ("", link->GetAddOption());

    // this line fails
    EXPECT_NE(dynamic_cast<TObjOptLink *>(link), nullptr); 

   link = link->Next();

   EXPECT_STREQ("name2", link->GetObject()->GetName());
   EXPECT_STREQ("title2", link->GetObject()->GetTitle());
   EXPECT_STREQ("option2", link->GetAddOption());
   EXPECT_NE(dynamic_cast<TObjOptLink *>(link), nullptr);

   link = link->Next();

   EXPECT_EQ(link, nullptr);
}

ROOT version

master, but also ROOT versions for at least 16 years back are affected

Installation method

Build from source

Operating system

OpenSUSE Linux

Additional context

No response

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions