Unverified Commit 00d3ed6d authored by jeffreytan81's avatar jeffreytan81 Committed by GitHub
Browse files

[Reland] Detect against invalid variant index for LibStdC++ std::variant data formatters (#69614)

This is relanding of https://github.com/llvm/llvm-project/pull/69253.
`TestTemplatePackArgs.py` is passing now.

https://github.com/llvm/llvm-project/pull/68012/files

 added new data
formatters for LibStdC++ std::variant.

However, this formatter can crash if std::variant's index field has
invalid value (exceeds the number of template arguments).
This can happen if the current IP stops at a place std::variant is not
initialized yet.

This patch fixes the crash by ensuring the index is a valid value and
fix GetNthTemplateArgument() to make sure it is not crashing.

Co-authored-by: default avatarjeffreytan81 <jeffreytan@fb.com>
parent ec064593
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -914,6 +914,11 @@ def VariantSummaryProvider(valobj, dict):
    if index == npos_value:
        return " No Value"

    # Invalid index can happen when the variant is not initialized yet.
    template_arg_count = data_obj.GetType().GetNumberOfTemplateArguments()
    if index >= template_arg_count:
        return " <Invalid>"

    active_type = data_obj.GetType().GetTemplateArgumentType(index)
    return f" Active Type = {active_type.GetDisplayTypeName()} "

+2 −1
Original line number Diff line number Diff line
@@ -7183,7 +7183,8 @@ GetNthTemplateArgument(const clang::ClassTemplateSpecializationDecl *decl,
  // (including the ones preceding the parameter pack).
  const auto &pack = args[last_idx];
  const size_t pack_idx = idx - last_idx;
  assert(pack_idx < pack.pack_size() && "parameter pack index out-of-bounds");
  if (pack_idx >= pack.pack_size())
    return nullptr;
  return &pack.pack_elements()[pack_idx];
}

+26 −0
Original line number Diff line number Diff line
@@ -71,3 +71,29 @@ class LibStdcxxVariantDataFormatterTestCase(TestBase):
            substrs=["v_many_types_no_value =  No Value"],
        )
        """

    @add_test_categories(["libstdcxx"])
    def test_invalid_variant_index(self):
        """Test LibStdC++ data formatter for std::variant with invalid index."""
        self.build()

        (self.target, self.process, thread, bkpt) = lldbutil.run_to_source_breakpoint(
            self, "// break here", lldb.SBFileSpec("main.cpp", False)
        )

        lldbutil.continue_to_breakpoint(self.process, bkpt)

        self.expect(
            "frame variable v1",
            substrs=["v1 =  Active Type = int  {", "Value = 12", "}"],
        )

        var_v1 = thread.frames[0].FindVariable("v1")
        var_v1_raw_obj = var_v1.GetNonSyntheticValue()
        index_obj = var_v1_raw_obj.GetChildMemberWithName("_M_index")
        self.assertTrue(index_obj and index_obj.IsValid())

        INVALID_INDEX = "100"
        index_obj.SetValueFromCString(INVALID_INDEX)

        self.expect("frame variable v1", substrs=["v1 =  <Invalid>"])