Skip to content

Commit

Permalink
[Reland] Detect against invalid variant index for LibStdC++ std::vari…
Browse files Browse the repository at this point in the history
…ant data formatters (llvm#69614)

This is relanding of llvm#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: jeffreytan81 <[email protected]>
  • Loading branch information
jeffreytan81 and jeffreytan81 authored Oct 24, 2023
1 parent ec06459 commit 00d3ed6
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 1 deletion.
5 changes: 5 additions & 0 deletions lldb/examples/synthetic/gnu_libstdcpp.py
Original file line number Diff line number Diff line change
Expand Up @@ -914,6 +914,11 @@ def get_variant_npos_value(index_byte_size):
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()} "

Expand Down
3 changes: 2 additions & 1 deletion lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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];
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,3 +71,29 @@ def test_with_run_command(self):
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>"])

0 comments on commit 00d3ed6

Please sign in to comment.