Skip to content

Commit 922ee51

Browse files
authored
fix: invalid isa pointer access in ios 14 (#1275)
* fix: invalid isa pointer access in ios 14 * refactor: clean up * fix: add back safety nets * fix: style * chore: updates
1 parent dea65d2 commit 922ee51

5 files changed

Lines changed: 19 additions & 202 deletions

File tree

build/npm/inspector_package.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "tns-ios-inspector",
3-
"description": "Telerik NativeScript Inspector for iOS Runtime",
4-
"version": "6.5.1",
3+
"description": "NativeScript Inspector for iOS Runtime",
4+
"version": "6.5.2",
55
"keywords": [
66
"NativeScript",
77
"iOS",
@@ -12,8 +12,8 @@
1212
"url": "https://github.com/NativeScript/ios-runtime"
1313
},
1414
"author": {
15-
"name": "Telerik",
16-
"email": "support@telerik.com"
15+
"name": "NativeScript",
16+
"email": "support@nativescript.org"
1717
},
1818
"os": [
1919
"darwin"

build/npm/runtime_package.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "tns-ios",
3-
"description": "Telerik NativeScript Runtime for iOS",
4-
"version": "6.5.1",
3+
"description": "NativeScript Runtime for iOS",
4+
"version": "6.5.2",
55
"keywords": [
66
"NativeScript",
77
"iOS",
@@ -12,8 +12,8 @@
1212
"url": "https://github.com/NativeScript/ios-runtime"
1313
},
1414
"author": {
15-
"name": "Telerik",
16-
"email": "support@telerik.com"
15+
"name": "NativeScript",
16+
"email": "support@nativescript.org"
1717
},
1818
"directories": {},
1919
"files": [

plugins/TKLiveSync/Podfile.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,4 @@ SPEC CHECKSUMS:
1515

1616
PODFILE CHECKSUM: f5ca86f956288d6d48fd6aa384d742ee2b5999b3
1717

18-
COCOAPODS: 1.9.1
18+
COCOAPODS: 1.9.3

src/NativeScript/ObjC/IsObjcObject.cpp

Lines changed: 10 additions & 184 deletions
Original file line numberDiff line numberDiff line change
@@ -20,144 +20,27 @@
2020
// Objective-C runtime
2121
#include <objc/runtime.h>
2222

23-
// For dlsym
24-
#include <dlfcn.h>
25-
2623
// For malloc_size
2724
#include <malloc/malloc.h>
2825

29-
// Do not thoroughly check valid memory pointers - it's too computationally intensive and slows down the runtime by 3 to 10 times
30-
#define SKIP_CHECK_FOR_KNOWN_CLASS 1
31-
32-
#pragma mark - Expose non exported Tagged Pointer functions from objc4-706/runtime/objc-internal.h
26+
#pragma mark - Expose non exported Tagged Pointer functions from objc4-781.2/runtime/objc-internal.h
3327

3428
#if TARGET_OS_OSX && __x86_64__
35-
// 64-bit Mac - tag bit is LSB
36-
#define OBJC_MSB_TAGGED_POINTERS 0
37-
#else
38-
// Everything else - tag bit is MSB
39-
#define OBJC_MSB_TAGGED_POINTERS 1
40-
#endif
41-
42-
#define _OBJC_TAG_INDEX_MASK 0x7
43-
#define _OBJC_TAG_EXT_INDEX_MASK 0xff
44-
45-
#if OBJC_MSB_TAGGED_POINTERS
46-
#define _OBJC_TAG_MASK (1ULL << 63)
47-
#define _OBJC_TAG_INDEX_SHIFT 60
48-
#define _OBJC_TAG_EXT_INDEX_SHIFT 52
29+
// 64-bit Mac - tag bit is LSB
30+
# define _OBJC_TAG_MASK 1UL
4931
#else
50-
#define _OBJC_TAG_MASK 1
51-
#define _OBJC_TAG_INDEX_SHIFT 1
52-
#define _OBJC_TAG_EXT_INDEX_SHIFT 4
32+
// Everything else - tag bit is MSB
33+
# define _OBJC_TAG_MASK (1ULL << 63)
5334
#endif
5435

55-
#if defined __arm64__ && __arm64__
56-
#define ISA_MASK 0x0000000ffffffff8ULL
57-
#define ISA_MAGIC_MASK 0x000003f000000001ULL
58-
#define ISA_MAGIC_VALUE 0x000001a000000001ULL
59-
60-
#elif defined __x86_64__ && __x86_64__
61-
#define ISA_MASK 0x00007ffffffffff8ULL
62-
#define ISA_MAGIC_MASK 0x001f800000000001ULL
63-
#define ISA_MAGIC_VALUE 0x001d800000000001ULL
64-
65-
#elif (defined __arm__ && __arm__) || (defined __i386__ && __i386__)
66-
#define SKIP_OBJECTIVE_C_CHECKS 1
67-
#else
68-
// Available bits in isa field are architecture-specific.
69-
#error unknown architecture
70-
#endif
71-
72-
#if !defined SKIP_OBJECTIVE_C_CHECKS || !SKIP_OBJECTIVE_C_CHECKS
73-
74-
typedef enum {
75-
OBJC_TAG_NSAtom = 0,
76-
OBJC_TAG_1 = 1,
77-
OBJC_TAG_NSString = 2,
78-
OBJC_TAG_NSNumber = 3,
79-
OBJC_TAG_NSIndexPath = 4,
80-
OBJC_TAG_NSManagedObjectID = 5,
81-
OBJC_TAG_NSDate = 6,
82-
OBJC_TAG_RESERVED_7 = 7,
83-
84-
OBJC_TAG_First60BitPayload = 0,
85-
OBJC_TAG_Last60BitPayload = 6,
86-
OBJC_TAG_First52BitPayload = 8,
87-
OBJC_TAG_Last52BitPayload = 263,
88-
89-
OBJC_TAG_RESERVED_264 = 264
90-
} objc_tag_index_t;
91-
92-
static inline bool _objc_isTaggedPointer(const void* ptr) {
93-
return ((intptr_t)ptr & _OBJC_TAG_MASK) == _OBJC_TAG_MASK;
36+
static inline bool _objc_isTaggedPointer(const void * _Nullable ptr) {
37+
return ((uintptr_t)ptr & _OBJC_TAG_MASK) == _OBJC_TAG_MASK;
9438
}
9539

96-
static inline objc_tag_index_t _objc_getTaggedPointerTag(const void* ptr) {
97-
uintptr_t basicTag = ((uintptr_t)ptr >> _OBJC_TAG_INDEX_SHIFT) & _OBJC_TAG_INDEX_MASK;
98-
uintptr_t extTag = ((uintptr_t)ptr >> _OBJC_TAG_EXT_INDEX_SHIFT) & _OBJC_TAG_EXT_INDEX_MASK;
99-
if (basicTag == _OBJC_TAG_INDEX_MASK) {
100-
return (objc_tag_index_t)(extTag + OBJC_TAG_First52BitPayload);
101-
} else {
102-
return (objc_tag_index_t)basicTag;
103-
}
104-
}
105-
106-
#pragma mark - Tagged Pointer
107-
108-
/**
109-
Returns the registered class for the given tag.
110-
Returns nil if the tag is valid but has no registered class.
111-
112-
This function searches the exported function: _objc_getClassForTag(objc_tag_index_t tag)
113-
declared in https://opensource.apple.com/source/objc4/objc4-706/runtime/objc-internal.h
114-
*/
115-
static Class _objc_getClassForTag(objc_tag_index_t tag) {
116-
static bool _objc_getClassForTag_searched = false;
117-
static Class (*_objc_getClassForTag_func)(objc_tag_index_t) = NULL;
118-
if (!_objc_getClassForTag_searched) {
119-
_objc_getClassForTag_func = (Class(*)(objc_tag_index_t))dlsym(RTLD_DEFAULT, "_objc_getClassForTag");
120-
_objc_getClassForTag_searched = true;
121-
if (_objc_getClassForTag_func == NULL) {
122-
fprintf(stderr, "*** Could not find _objc_getClassForTag()!\n");
123-
}
124-
}
125-
126-
if (_objc_getClassForTag_func != NULL) {
127-
return _objc_getClassForTag_func(tag);
128-
}
129-
130-
return NULL;
131-
}
132-
133-
/**
134-
Test if a pointer is a tagged pointer
135-
136-
@param inPtr is the pointer to check
137-
@param outClass returns the registered class for the tagged pointer.
138-
@return true if the pointer is a tagged pointer.
139-
*/
140-
bool IsObjcTaggedPointer(const void* inPtr, Class* outClass) {
141-
bool isTaggedPointer = _objc_isTaggedPointer(inPtr);
142-
if (outClass != NULL) {
143-
if (isTaggedPointer) {
144-
objc_tag_index_t tagIndex = _objc_getTaggedPointerTag(inPtr);
145-
*outClass = _objc_getClassForTag(tagIndex);
146-
} else {
147-
*outClass = NULL;
148-
}
149-
}
150-
151-
return isTaggedPointer;
152-
}
153-
154-
#endif // !defined SKIP_OBJECTIVE_C_CHECKS || !SKIP_OBJECTIVE_C_CHECKS
155-
15640
#pragma mark - Readable and valid memory
15741

15842
/**
15943
Test if the pointer points to readable and valid memory.
160-
16144
@param inPtr is the pointer
16245
@return true if the pointer points to readable and valid memory.
16346
*/
@@ -214,14 +97,12 @@ bool IsObjcObject(const void* inPtr) {
21497
return false;
21598
}
21699

217-
#if !defined SKIP_OBJECTIVE_C_CHECKS || !SKIP_OBJECTIVE_C_CHECKS
218100
//
219-
// Check for tagged pointers
101+
// Check if the pointer is a tagged objc pointer
220102
//
221-
if (IsObjcTaggedPointer(inPtr, NULL)) {
103+
if (_objc_isTaggedPointer(inPtr)) {
222104
return true;
223105
}
224-
#endif
225106

226107
//
227108
// Check if the pointer is aligned
@@ -237,67 +118,13 @@ bool IsObjcObject(const void* inPtr) {
237118
return false;
238119
}
239120

240-
#if !defined SKIP_OBJECTIVE_C_CHECKS || !SKIP_OBJECTIVE_C_CHECKS
241-
//
242-
// From LLDB:
243-
// Objective-C runtime has a rule that pointers in a class_t will only have bits 0 thru 46 set
244-
// so if any pointer has bits 47 thru 63 high we know that this is not a valid isa
245-
// See http://llvm.org/svn/llvm-project/lldb/trunk/examples/summaries/cocoa/objc_runtime.py
246-
//
247-
if (((uintptr_t)inPtr & 0xFFFF800000000000) != 0) {
248-
return false;
249-
}
250-
251-
//
252-
// Get the Class from the pointer
253-
// From http://www.sealiesoftware.com/blog/archive/2013/09/24/objc_explain_Non-pointer_isa.html :
254-
// If you are writing a debugger-like tool, the Objective-C runtime exports some variables
255-
// to help decode isa fields. objc_debug_isa_class_mask describes which bits are the class pointer:
256-
// (isa & class_mask) == class pointer.
257-
// objc_debug_isa_magic_mask and objc_debug_isa_magic_value describe some bits that help
258-
// distinguish valid isa fields from other invalid values:
259-
// (isa & magic_mask) == magic_value for isa fields that are not raw class pointers.
260-
// These variables may change in the future so do not use them in application code.
261-
//
262-
263-
uintptr_t isa = (*(uintptr_t*)inPtr);
264121
Class ptrClass = NULL;
265-
266-
if ((isa & ~ISA_MASK) == 0) {
267-
ptrClass = (Class)isa;
268-
} else {
269-
if ((isa & ISA_MAGIC_MASK) == ISA_MAGIC_VALUE) {
270-
ptrClass = (Class)(isa & ISA_MASK);
271-
} else {
272-
ptrClass = (Class)isa;
273-
}
274-
}
122+
ptrClass = object_getClass((id)inPtr);
275123

276124
if (ptrClass == NULL) {
277125
return false;
278126
}
279127

280-
#if !defined(SKIP_CHECK_FOR_KNOWN_CLASS) || !SKIP_CHECK_FOR_KNOWN_CLASS
281-
//
282-
// Verifies that the found Class is a known class.
283-
//
284-
bool isKnownClass = false;
285-
286-
unsigned int numClasses = 0;
287-
Class* classesList = objc_copyClassList(&numClasses);
288-
for (unsigned i = 0; i < numClasses; i++) {
289-
if (classesList[i] == ptrClass) {
290-
isKnownClass = true;
291-
break;
292-
}
293-
}
294-
free(classesList);
295-
296-
if (!isKnownClass) {
297-
return false;
298-
}
299-
#endif // !defined(SKIP_CHECK_FOR_KNOWN_CLASS) || !SKIP_CHECK_FOR_KNOWN_CLASS
300-
301128
//
302129
// From Greg Parker
303130
// https://twitter.com/gparker/status/801894068502433792
@@ -307,7 +134,6 @@ bool IsObjcObject(const void* inPtr) {
307134
if (pointerSize > 0 && pointerSize < class_getInstanceSize(ptrClass)) {
308135
return false;
309136
}
310-
#endif // !defined SKIP_OBJECTIVE_C_CHECKS || !SKIP_OBJECTIVE_C_CHECKS
311137

312138
return true;
313139
}

src/NativeScript/ObjC/IsObjcObject.h

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,4 @@
1919
extern "C" {
2020

2121
bool IsObjcObject(const void* inPtr);
22-
23-
/**
24-
Test if a pointer is a tagged pointer
25-
26-
@param inPtr is the pointer to check
27-
@param outClass returns the registered class for the tagged pointer.
28-
@return true if the pointer is a tagged pointer.
29-
*/
30-
bool IsObjcTaggedPointer(const void* inPtr, Class* outClass);
3122
}

0 commit comments

Comments
 (0)