Skip to content

Commit 3ddb549

Browse files
[Remarks] YAMLRemarkSerializer: Fix StringRef out-of-bounds read (#159759)
YAML IO `mapRequired` expects a null-terminated `const char *` Key, so we can't legally pass a StringRef to it. We should add StringRef Key support to YAML IO, but for now just copy the key into a correctly null-terminated string. Pull Request: #159759
1 parent 9469ea2 commit 3ddb549

File tree

2 files changed

+36
-2
lines changed

2 files changed

+36
-2
lines changed

llvm/lib/Remarks/YAMLRemarkSerializer.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,11 +114,15 @@ template <> struct MappingTraits<Argument> {
114114
static void mapping(IO &io, Argument &A) {
115115
assert(io.outputting() && "input not yet implemented");
116116

117+
// A.Key.data() is not necessarily null-terminated, so we must make a copy,
118+
// otherwise we potentially read out of bounds.
119+
// FIXME: Add support for StringRef Keys in YAML IO.
120+
std::string Key(A.Key);
117121
if (StringRef(A.Val).count('\n') > 1) {
118122
StringBlockVal S(A.Val);
119-
io.mapRequired(A.Key.data(), S);
123+
io.mapRequired(Key.c_str(), S);
120124
} else {
121-
io.mapRequired(A.Key.data(), A.Val);
125+
io.mapRequired(Key.c_str(), A.Val);
122126
}
123127
io.mapOptional("DebugLoc", A.Loc);
124128
}

llvm/unittests/Remarks/YAMLRemarksSerializerTest.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,3 +163,33 @@ TEST(YAMLRemarks, SerializerRemarkParsedStrTabStandaloneNoStrTab) {
163163
"...\n"),
164164
std::move(PreFilledStrTab));
165165
}
166+
167+
TEST(YAMLRemarks, SerializerRemarkStringRefOOBRead) {
168+
remarks::Remark R;
169+
R.RemarkType = remarks::Type::Missed;
170+
R.PassName = StringRef("passAAAA", 4);
171+
R.RemarkName = StringRef("nameAAAA", 4);
172+
R.FunctionName = StringRef("funcAAAA", 4);
173+
R.Loc = remarks::RemarkLocation{StringRef("pathAAAA", 4), 3, 4};
174+
R.Hotness = 5;
175+
R.Args.emplace_back();
176+
R.Args.back().Key = StringRef("keyAAAA", 3);
177+
R.Args.back().Val = StringRef("valueAAAA", 5);
178+
R.Args.emplace_back();
179+
R.Args.back().Key = StringRef("keydebugAAAA", 8);
180+
R.Args.back().Val = StringRef("valuedebugAAAA", 10);
181+
R.Args.back().Loc =
182+
remarks::RemarkLocation{StringRef("argpathAAAA", 7), 6, 7};
183+
checkStandalone(remarks::Format::YAML, R,
184+
"--- !Missed\n"
185+
"Pass: pass\n"
186+
"Name: name\n"
187+
"DebugLoc: { File: path, Line: 3, Column: 4 }\n"
188+
"Function: func\n"
189+
"Hotness: 5\n"
190+
"Args:\n"
191+
" - key: value\n"
192+
" - keydebug: valuedebug\n"
193+
" DebugLoc: { File: argpath, Line: 6, Column: 7 }\n"
194+
"...\n");
195+
}

0 commit comments

Comments
 (0)