mirror of
https://github.com/boykopovar/AnyPS5.git
synced 2026-10-28 00:35:47 +00:00
Merge pull request #10605 from harisibrar1/fix/rtti-ambiguous-private-base
fix(libc): reject a catch or upcast to a base that a private path repeats
This commit is contained in:
3 files changed
+20
-2
No files matched your search
@@ -202,12 +202,15 @@ void VisitBases(const std::type_info* type, BaseLocation location, bool publicPa
|
||||
|
||||
void Bases(const std::type_info* type, void* object, Search& search) {
|
||||
std::uintptr_t identity = 0;
|
||||
bool reachedPublicly = false;
|
||||
auto visitor = [&](const std::type_info* candidate, BaseLocation location, bool publicPath) {
|
||||
if (!publicPath || !Equal(candidate, search.wanted)) return;
|
||||
if (!search.count) { search.found = location.object; identity = location.identity; search.count = 1; }
|
||||
if (!Equal(candidate, search.wanted)) return;
|
||||
if (!search.count) { search.found = location.object; identity = location.identity; search.count = 1; reachedPublicly = publicPath; }
|
||||
else if (search.found != location.object || identity != location.identity) search.count = 2;
|
||||
else if (publicPath) reachedPublicly = true;
|
||||
};
|
||||
VisitBases(type, {object, 0}, true, visitor);
|
||||
if (search.count == 1 && !reachedPublicly) search.count = 0;
|
||||
}
|
||||
|
||||
bool PointerMatch(const __cxxabiv1::__pbase_type_info* caught, const __cxxabiv1::__pbase_type_info* thrown,
|
||||
|
||||
@@ -40,6 +40,7 @@ struct Virtual : virtual Base {};
|
||||
struct Left : Base {};
|
||||
struct Right : Base {};
|
||||
struct Repeated : Left, Right {};
|
||||
struct MixedRepeated : Left, private Right {};
|
||||
struct LeftVirtual : virtual Base {};
|
||||
struct RightVirtual : virtual Base {};
|
||||
struct Diamond : LeftVirtual, RightVirtual {};
|
||||
@@ -59,6 +60,9 @@ void CheckRtti() {
|
||||
try { throw static_cast<Repeated*>(nullptr); }
|
||||
catch (Base*) { assert(false); }
|
||||
catch (Repeated* p) { assert(p == nullptr); }
|
||||
try { throw MixedRepeated(); }
|
||||
catch (Base&) { assert(false); }
|
||||
catch (MixedRepeated&) {}
|
||||
try { throw static_cast<Diamond*>(nullptr); }
|
||||
catch (Base* p) { assert(p == nullptr); }
|
||||
try { throw nullptr; }
|
||||
|
||||
@@ -56,6 +56,17 @@ static void TestTypeInfoVtables() {
|
||||
if (!upcastType(&multiple, &base, &object) || object != storage.data() + 16) throw std::runtime_error("multiple RTTI upcast failed");
|
||||
object = storage.data();
|
||||
if (catchType(&other, &single, &object, 0)) throw std::runtime_error("unrelated RTTI catch succeeded");
|
||||
TypeRecord shared {classTable + 2 * sizeof(void*), "6Shared"};
|
||||
SingleRecord publicPath {{singleTable + 2 * sizeof(void*), "10PublicPath"}, &shared};
|
||||
SingleRecord privatePath {{singleTable + 2 * sizeof(void*), "11PrivatePath"}, &shared};
|
||||
MultipleRecord mixed {{multipleTable + 2 * sizeof(void*), "5Mixed"}, 1, 2, {{&publicPath.type, 2}, {&privatePath.type, 16 << 8}}};
|
||||
MultipleRecord hidden {{multipleTable + 2 * sizeof(void*), "6Hidden"}, 0, 1, {{&privatePath.type, 0}, {}}};
|
||||
object = storage.data();
|
||||
if (catchType(&shared, &mixed, &object, 0) || object != storage.data()) throw std::runtime_error("RTTI catch of a base repeated through a private path succeeded");
|
||||
if (upcastType(&mixed, &shared, &object) || object != storage.data()) throw std::runtime_error("RTTI upcast to a base repeated through a private path succeeded");
|
||||
if (!catchType(&publicPath, &mixed, &object, 0) || object != storage.data()) throw std::runtime_error("RTTI catch of the public path failed");
|
||||
object = storage.data();
|
||||
if (catchType(&shared, &hidden, &object, 0)) throw std::runtime_error("RTTI catch of a privately inherited base succeeded");
|
||||
}
|
||||
|
||||
extern "C" [[noreturn]] void NotImplemented_nid_no_patch(const char*);
|
||||
|
||||
Reference in new issue
Block a user