Skip to content

Commit 7897ab8

Browse files
authored
Merge pull request #27036 from jckarter/backport-getClass-security-fix
Compatibility50: Backport objc_getClass hook patch.
2 parents 1a38032 + 624ad4f commit 7897ab8

File tree

1 file changed

+53
-0
lines changed

1 file changed

+53
-0
lines changed

stdlib/toolchain/Compatibility50/Overrides.cpp

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,56 @@ __attribute__((used, section("__DATA,__swift_hooks"))) = {
3636
__attribute__((weak, visibility("hidden")))
3737
extern "C"
3838
char _swift_FORCE_LOAD_$_swiftCompatibility50 = 0;
39+
40+
// Put a getClass hook in front of the system Swift runtime's hook to prevent it
41+
// from trying to interpret symbolic references. rdar://problem/55036306
42+
43+
// FIXME: delete this #if and dlsym once we don't
44+
// need to build with older libobjc headers
45+
#if !OBJC_GETCLASSHOOK_DEFINED
46+
using objc_hook_getClass = BOOL(*)(const char * _Nonnull name,
47+
Class _Nullable * _Nonnull outClass);
48+
#endif
49+
static objc_hook_getClass OldGetClassHook;
50+
51+
static BOOL
52+
getObjCClassByMangledName_untrusted(const char * _Nonnull typeName,
53+
Class _Nullable * _Nonnull outClass) {
54+
// Scan the string for byte sequences that might be recognized as
55+
// symbolic references, and reject them.
56+
for (const char *c = typeName; *c != 0; ++c) {
57+
if (*c < 0x20) {
58+
*outClass = Nil;
59+
return NO;
60+
}
61+
}
62+
63+
if (OldGetClassHook) {
64+
return OldGetClassHook(typeName, outClass);
65+
}
66+
// In case the OS runtime for some reason didn't install a hook, fallback to
67+
// NO.
68+
return NO;
69+
}
70+
71+
__attribute__((constructor))
72+
static void installGetClassHook_untrusted() {
73+
// FIXME: delete this #if and dlsym once we don't
74+
// need to build with older libobjc headers
75+
#if !OBJC_GETCLASSHOOK_DEFINED
76+
using objc_hook_getClass = BOOL(*)(const char * _Nonnull name,
77+
Class _Nullable * _Nonnull outClass);
78+
auto objc_setHook_getClass =
79+
(void(*)(objc_hook_getClass _Nonnull,
80+
objc_hook_getClass _Nullable * _Nonnull))
81+
dlsym(RTLD_DEFAULT, "objc_setHook_getClass");
82+
#endif
83+
84+
#pragma clang diagnostic push
85+
#pragma clang diagnostic ignored "-Wunguarded-availability"
86+
if (objc_setHook_getClass) {
87+
objc_setHook_getClass(getObjCClassByMangledName_untrusted,
88+
&OldGetClassHook);
89+
}
90+
#pragma clang diagnostic pop
91+
}

0 commit comments

Comments
 (0)