Skip to content

Commit eb5b997

Browse files
authored
Fix unbounded memory usage in FriendlyNameMapper (KhronosGroup#6763)
Limit the size of friendly names suggested by FriendlyNameMapper to a maximum of 256 characters. Suggested names exceeding this limit will fall back to the string representation of the instruction ID to prevent OOM vulnerability caused by recursive OpTypeArray definitions. Fixes KhronosGroup#6756
1 parent 74d3c74 commit eb5b997

2 files changed

Lines changed: 88 additions & 4 deletions

File tree

source/name_mapper.cpp

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -78,13 +78,21 @@ void FriendlyNameMapper::SaveName(uint32_t id,
7878
const std::string& suggested_name) {
7979
if (name_for_id_.find(id) != name_for_id_.end()) return;
8080

81-
const std::string sanitized_suggested_name = Sanitize(suggested_name);
82-
std::string name = sanitized_suggested_name;
81+
std::string base_name;
82+
83+
// Limit the size of the name to limit memory usage.
84+
const uint32_t kMaxSize = 256;
85+
if (suggested_name.size() > kMaxSize) {
86+
base_name = to_string(id);
87+
} else {
88+
base_name = Sanitize(suggested_name);
89+
}
90+
std::string name = base_name;
8391
auto inserted = used_names_.insert(name);
8492
if (!inserted.second) {
85-
const std::string base_name = sanitized_suggested_name + "_";
93+
const std::string base_name_prefix = base_name + "_";
8694
for (uint32_t index = 0; !inserted.second; ++index) {
87-
name = base_name + to_string(index);
95+
name = base_name_prefix + to_string(index);
8896
inserted = used_names_.insert(name);
8997
}
9098
}

test/name_mapper_test.cpp

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,5 +344,81 @@ INSTANTIATE_TEST_SUITE_P(
344344
{"%1 = OpTypeBool\n%2 = OpConstantFalse %1", 2, "false"},
345345
}));
346346

347+
INSTANTIATE_TEST_SUITE_P(
348+
FriendlyName256CharCapLimit, FriendlyNameTest,
349+
::testing::ValuesIn(std::vector<NameIdCase>{
350+
// OpName with exactly 256 chars: expect the sanitized 256 char name.
351+
{"OpName %1 "
352+
"\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
353+
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
354+
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
355+
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"",
356+
1,
357+
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
358+
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
359+
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
360+
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"},
361+
// OpName with 257 chars: expect the string representation of the ID.
362+
{"OpName %1 "
363+
"\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
364+
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
365+
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
366+
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"",
367+
1, "1"},
368+
// OpName with 300 chars: expect the string representation of the ID.
369+
{"OpName %1 "
370+
"\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
371+
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
372+
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
373+
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
374+
"aaaaaaaaaaaaaaaaaaaaaaaaaa\"",
375+
1, "1"},
376+
// OpName with 257 chars on ID 1, and another OpName with 257 chars on
377+
// ID 2:
378+
// expect ID 1 to map to "1" and ID 2 to map to "2".
379+
{"OpName %1 "
380+
"\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
381+
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
382+
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
383+
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"\n"
384+
"OpName %2 "
385+
"\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
386+
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
387+
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
388+
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"",
389+
1, "1"},
390+
{"OpName %1 "
391+
"\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
392+
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
393+
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
394+
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"\n"
395+
"OpName %2 "
396+
"\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
397+
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
398+
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
399+
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"",
400+
2, "2"},
401+
// OpName with 257 chars on ID 2, but name "2" is already used by ID 1:
402+
// expect ID 2 to map to "2_0".
403+
{"OpName %1 \"2\"\n"
404+
"OpName %2 "
405+
"\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
406+
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
407+
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
408+
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"",
409+
2, "2_0"},
410+
// OpName with 257 chars on ID 3, but names "3" and "3_0" are already
411+
// used:
412+
// expect ID 3 to map to "3_1".
413+
{"OpName %1 \"3\"\n"
414+
"OpName %2 \"3_0\"\n"
415+
"OpName %3 "
416+
"\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
417+
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
418+
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
419+
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"",
420+
3, "3_1"},
421+
}));
422+
347423
} // namespace
348424
} // namespace spvtools

0 commit comments

Comments
 (0)