Skip to content

Commit 00d3ed6

Browse files
jeffreytan81jeffreytan81
and
jeffreytan81
authored
[Reland] Detect against invalid variant index for LibStdC++ std::variant data formatters (#69614)
This is relanding of #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]>
1 parent ec06459 commit 00d3ed6

File tree

3 files changed

+33
-1
lines changed

3 files changed

+33
-1
lines changed

lldb/examples/synthetic/gnu_libstdcpp.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -914,6 +914,11 @@ def get_variant_npos_value(index_byte_size):
914914
if index == npos_value:
915915
return " No Value"
916916

917+
# Invalid index can happen when the variant is not initialized yet.
918+
template_arg_count = data_obj.GetType().GetNumberOfTemplateArguments()
919+
if index >= template_arg_count:
920+
return " <Invalid>"
921+
917922
active_type = data_obj.GetType().GetTemplateArgumentType(index)
918923
return f" Active Type = {active_type.GetDisplayTypeName()} "
919924

lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7183,7 +7183,8 @@ GetNthTemplateArgument(const clang::ClassTemplateSpecializationDecl *decl,
71837183
// (including the ones preceding the parameter pack).
71847184
const auto &pack = args[last_idx];
71857185
const size_t pack_idx = idx - last_idx;
7186-
assert(pack_idx < pack.pack_size() && "parameter pack index out-of-bounds");
7186+
if (pack_idx >= pack.pack_size())
7187+
return nullptr;
71877188
return &pack.pack_elements()[pack_idx];
71887189
}
71897190

lldb/test/API/functionalities/data-formatter/data-formatter-stl/libstdcpp/variant/TestDataFormatterLibStdcxxVariant.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,3 +71,29 @@ def test_with_run_command(self):
7171
substrs=["v_many_types_no_value = No Value"],
7272
)
7373
"""
74+
75+
@add_test_categories(["libstdcxx"])
76+
def test_invalid_variant_index(self):
77+
"""Test LibStdC++ data formatter for std::variant with invalid index."""
78+
self.build()
79+
80+
(self.target, self.process, thread, bkpt) = lldbutil.run_to_source_breakpoint(
81+
self, "// break here", lldb.SBFileSpec("main.cpp", False)
82+
)
83+
84+
lldbutil.continue_to_breakpoint(self.process, bkpt)
85+
86+
self.expect(
87+
"frame variable v1",
88+
substrs=["v1 = Active Type = int {", "Value = 12", "}"],
89+
)
90+
91+
var_v1 = thread.frames[0].FindVariable("v1")
92+
var_v1_raw_obj = var_v1.GetNonSyntheticValue()
93+
index_obj = var_v1_raw_obj.GetChildMemberWithName("_M_index")
94+
self.assertTrue(index_obj and index_obj.IsValid())
95+
96+
INVALID_INDEX = "100"
97+
index_obj.SetValueFromCString(INVALID_INDEX)
98+
99+
self.expect("frame variable v1", substrs=["v1 = <Invalid>"])

0 commit comments

Comments
 (0)