Преглед на файлове

Don't access ivars on tagged pointers

Tanner Bennett преди 6 години
родител
ревизия
5d919eb329

+ 2 - 0
Classes/Utility/Categories/NSString+FLEX.h

@@ -14,6 +14,8 @@
 @property (nonatomic, readonly) BOOL flex_typeIsConst;
 /// @return the first char in the type encoding that is not the const specifier
 @property (nonatomic, readonly) FLEXTypeEncoding flex_firstNonConstType;
+/// @return the first char in the type encoding after the pointer specifier, if it is a pointer
+@property (nonatomic, readonly) FLEXTypeEncoding flex_pointeeType;
 /// @return whether this type is an objc object of any kind, even if it's const
 @property (nonatomic, readonly) BOOL flex_typeIsObjectOrClass;
 /// @return the class named in this type encoding if it is of the form \c @"MYClass"

+ 10 - 0
Classes/Utility/Categories/NSString+FLEX.m

@@ -75,6 +75,16 @@
     return [self characterAtIndex:(self.flex_typeIsConst ? 1 : 0)];
 }
 
+- (FLEXTypeEncoding)flex_pointeeType {
+    if (!self.length) return FLEXTypeEncodingNull;
+    
+    if (self.flex_firstNonConstType == FLEXTypeEncodingPointer) {
+        return [self characterAtIndex:(self.flex_typeIsConst ? 2 : 1)];
+    }
+    
+    return FLEXTypeEncodingNull;
+}
+
 - (BOOL)flex_typeIsObjectOrClass {
     FLEXTypeEncoding type = self.flex_firstNonConstType;
     return type == FLEXTypeEncodingObjcObject || type == FLEXTypeEncodingObjcClass;

+ 45 - 1
Classes/Utility/Runtime/Objc/FLEXObjcInternal.h

@@ -11,7 +11,51 @@
 extern "C" {
 #endif
 
-BOOL FLEXPointerIsReadable(const void *inPtr);
+// The macros below are copied straight from
+// objc-internal.h, objc-private.h, objc-object.h, and objc-config.h with
+// as few modifications as possible. Changes are noted in boxed comments.
+// https://opensource.apple.com/source/objc4/objc4-723/
+// https://opensource.apple.com/source/objc4/objc4-723/runtime/objc-internal.h.auto.html
+// https://opensource.apple.com/source/objc4/objc4-723/runtime/objc-object.h.auto.html
+
+/////////////////////
+// objc-internal.h //
+/////////////////////
+
+#if __LP64__
+#define OBJC_HAVE_TAGGED_POINTERS 1
+#endif
+
+#if OBJC_HAVE_TAGGED_POINTERS
+
+#if TARGET_OS_OSX && __x86_64__
+// 64-bit Mac - tag bit is LSB
+#   define OBJC_MSB_TAGGED_POINTERS 0
+#else
+// Everything else - tag bit is MSB
+#   define OBJC_MSB_TAGGED_POINTERS 1
+#endif
+
+#if OBJC_MSB_TAGGED_POINTERS
+#   define _OBJC_TAG_MASK (1UL<<63)
+#   define _OBJC_TAG_EXT_MASK (0xfUL<<60)
+#else
+#   define _OBJC_TAG_MASK 1UL
+#   define _OBJC_TAG_EXT_MASK 0xfUL
+#endif
+
+#endif // OBJC_HAVE_TAGGED_POINTERS
+
+//////////////////////////////////////
+// originally _objc_isTaggedPointer //
+//////////////////////////////////////
+NS_INLINE BOOL flex_isTaggedPointer(const void *ptr)  {
+    return ((uintptr_t)ptr & _OBJC_TAG_MASK) == _OBJC_TAG_MASK;
+}
+
+#define FLEXIsTaggedPointer(obj) flex_isTaggedPointer((__bridge void *)obj)
+
+BOOL FLEXPointerIsReadable(const void * ptr);
 
 /// @brief Assumes memory is valid and readable.
 /// @discussion objc-internal.h, objc-private.h, and objc-config.h

+ 6 - 29
Classes/Utility/Runtime/Objc/FLEXObjcInternal.mm

@@ -53,35 +53,8 @@
 // objc-internal.h //
 /////////////////////
 
-#if __LP64__
-#define OBJC_HAVE_TAGGED_POINTERS 1
-#endif
-
 #if OBJC_HAVE_TAGGED_POINTERS
 
-#if TARGET_OS_OSX && __x86_64__
-// 64-bit Mac - tag bit is LSB
-#   define OBJC_MSB_TAGGED_POINTERS 0
-#else
-// Everything else - tag bit is MSB
-#   define OBJC_MSB_TAGGED_POINTERS 1
-#endif
-
-#if OBJC_MSB_TAGGED_POINTERS
-#   define _OBJC_TAG_MASK (1UL<<63)
-#   define _OBJC_TAG_EXT_MASK (0xfUL<<60)
-#else
-#   define _OBJC_TAG_MASK 1UL
-#   define _OBJC_TAG_EXT_MASK 0xfUL
-#endif
-
-//////////////////////////////////////
-// originally _objc_isTaggedPointer //
-//////////////////////////////////////
-static BOOL flex_isTaggedPointer(const void *ptr)  {
-    return ((uintptr_t)ptr & _OBJC_TAG_MASK) == _OBJC_TAG_MASK;
-}
-
 ///////////////////
 // objc-object.h //
 ///////////////////
@@ -89,11 +62,11 @@ static BOOL flex_isTaggedPointer(const void *ptr)  {
 ////////////////////////////////////////////////
 // originally objc_object::isExtTaggedPointer //
 ////////////////////////////////////////////////
-static BOOL flex_isExtTaggedPointer(const void *ptr)  {
+NS_INLINE BOOL flex_isExtTaggedPointer(const void *ptr)  {
     return ((uintptr_t)ptr & _OBJC_TAG_EXT_MASK) == _OBJC_TAG_EXT_MASK;
 }
 
-#endif
+#endif // OBJC_HAVE_TAGGED_POINTERS
 
 /////////////////////////////////////
 // FLEXObjectInternal              //
@@ -102,6 +75,10 @@ static BOOL flex_isExtTaggedPointer(const void *ptr)  {
 
 extern "C" {
 
+BOOL FLEXPointerIsTaggedPointer(const void *pointer) {
+    return flex_isTaggedPointer(pointer);
+}
+
 BOOL FLEXPointerIsReadable(const void *inPtr) {
     kern_return_t error = KERN_SUCCESS;
 

+ 11 - 2
Classes/Utility/Runtime/Objc/Reflection/FLEXIvar.m

@@ -11,6 +11,8 @@
 #import "FLEXRuntimeUtility.h"
 #import "FLEXRuntimeSafety.h"
 #import "FLEXTypeEncodingParser.h"
+#import "NSString+FLEX.h"
+#include "FLEXObjcInternal.h"
 #include <dlfcn.h>
 
 @interface FLEXIvar () {
@@ -97,7 +99,9 @@
 
 - (id)getValue:(id)target {
     id value = nil;
-    if (!FLEXIvarIsSafe(_objc_ivar) || _type == FLEXTypeEncodingNull) {
+    if (!FLEXIvarIsSafe(_objc_ivar) ||
+        _type == FLEXTypeEncodingNull ||
+        FLEXIsTaggedPointer(target)) {
         return nil;
     }
 
@@ -147,9 +151,14 @@
 }
 
 - (id)getPotentiallyUnboxedValue:(id)target {
+    NSString *type = self.typeEncoding;
+    if (type.flex_typeIsNonObjcPointer && type.flex_pointeeType != FLEXTypeEncodingVoid) {
+        return [self getValue:target];
+    }
+    
     return [FLEXRuntimeUtility
         potentiallyUnwrapBoxedPointer:[self getValue:target]
-        type:self.typeEncoding.UTF8String
+        type:type.UTF8String
     ];
 }
 

+ 21 - 1
FLEXTests/FLEXTests.m

@@ -14,8 +14,13 @@
 #import "FLEXProperty.h"
 #import "FLEXUtility.h"
 #import "FLEXMethod.h"
+#import "FLEXIvar.h"
 
-@interface Subclass : NSObject @end
+@interface Subclass : NSObject {
+    @public
+    NSUInteger *_indexes;
+}
+@end
 @implementation Subclass @end
 
 @interface FLEXTests : XCTestCase
@@ -101,4 +106,19 @@
     XCTAssert(props.count == 1);
 }
 
+- (void)testIvarUnboxing {
+    NSUInteger array[4] = { 0xaa, 0xbb, 0xcc, 0x00 };
+    Subclass *obj = [Subclass new];
+    obj->_indexes = array;
+    
+    FLEXIvar *ivar = [Subclass flex_ivarNamed:@"_indexes"];
+    
+    NSValue *arrayValue = [ivar getPotentiallyUnboxedValue:obj];
+    NSUInteger *pointerValue = arrayValue.pointerValue;
+    
+    XCTAssert(pointerValue != nil);
+    XCTAssertEqual(pointerValue, (NSUInteger *)&array);
+    XCTAssertEqual(pointerValue[0], 0xaa);
+}
+
 @end