mirror of
https://github.com/SoPat712/YTLitePlus.git
synced 2025-11-01 13:23:37 -04:00
added files via upload
This commit is contained in:
196
Tweaks/FLEX/Utility/Runtime/Objc/FLEXObjcInternal.mm
Normal file
196
Tweaks/FLEX/Utility/Runtime/Objc/FLEXObjcInternal.mm
Normal file
@@ -0,0 +1,196 @@
|
||||
//
|
||||
// FLEXObjcInternal.mm
|
||||
// FLEX
|
||||
//
|
||||
// Created by Tanner Bennett on 11/1/18.
|
||||
//
|
||||
|
||||
/*
|
||||
* Copyright (c) 2005-2007 Apple Inc. All Rights Reserved.
|
||||
*
|
||||
* @APPLE_LICENSE_HEADER_START@
|
||||
*
|
||||
* This file contains Original Code and/or Modifications of Original Code
|
||||
* as defined in and that are subject to the Apple Public Source License
|
||||
* Version 2.0 (the 'License'). You may not use this file except in
|
||||
* compliance with the License. Please obtain a copy of the License at
|
||||
* http://www.opensource.apple.com/apsl/ and read it before using this
|
||||
* file.
|
||||
*
|
||||
* The Original Code and all software distributed under the License are
|
||||
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
|
||||
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
|
||||
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
|
||||
* Please see the License for the specific language governing rights and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @APPLE_LICENSE_HEADER_END@
|
||||
*/
|
||||
|
||||
#import "FLEXObjcInternal.h"
|
||||
#import <objc/runtime.h>
|
||||
// For malloc_size
|
||||
#import <malloc/malloc.h>
|
||||
// For vm_region_64
|
||||
#include <mach/mach.h>
|
||||
|
||||
#if __arm64e__
|
||||
#include <ptrauth.h>
|
||||
#endif
|
||||
|
||||
#define ALWAYS_INLINE inline __attribute__((always_inline))
|
||||
#define NEVER_INLINE inline __attribute__((noinline))
|
||||
|
||||
// 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 OBJC_HAVE_TAGGED_POINTERS
|
||||
|
||||
///////////////////
|
||||
// objc-object.h //
|
||||
///////////////////
|
||||
|
||||
////////////////////////////////////////////////
|
||||
// originally objc_object::isExtTaggedPointer //
|
||||
////////////////////////////////////////////////
|
||||
NS_INLINE BOOL flex_isExtTaggedPointer(const void *ptr) {
|
||||
return ((uintptr_t)ptr & _OBJC_TAG_EXT_MASK) == _OBJC_TAG_EXT_MASK;
|
||||
}
|
||||
|
||||
#endif // OBJC_HAVE_TAGGED_POINTERS
|
||||
|
||||
/////////////////////////////////////
|
||||
// FLEXObjectInternal //
|
||||
// No Apple code beyond this point //
|
||||
/////////////////////////////////////
|
||||
|
||||
extern "C" {
|
||||
|
||||
BOOL FLEXPointerIsReadable(const void *inPtr) {
|
||||
kern_return_t error = KERN_SUCCESS;
|
||||
|
||||
vm_size_t vmsize;
|
||||
#if __arm64e__
|
||||
// On arm64e, we need to strip the PAC from the pointer so the adress is readable
|
||||
vm_address_t address = (vm_address_t)ptrauth_strip(inPtr, ptrauth_key_function_pointer);
|
||||
#else
|
||||
vm_address_t address = (vm_address_t)inPtr;
|
||||
#endif
|
||||
vm_region_basic_info_data_t info;
|
||||
mach_msg_type_number_t info_count = VM_REGION_BASIC_INFO_COUNT_64;
|
||||
memory_object_name_t object;
|
||||
|
||||
error = vm_region_64(
|
||||
mach_task_self(),
|
||||
&address,
|
||||
&vmsize,
|
||||
VM_REGION_BASIC_INFO,
|
||||
(vm_region_info_t)&info,
|
||||
&info_count,
|
||||
&object
|
||||
);
|
||||
|
||||
if (error != KERN_SUCCESS) {
|
||||
// vm_region/vm_region_64 returned an error
|
||||
return NO;
|
||||
} else if (!(BOOL)(info.protection & VM_PROT_READ)) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
#if __arm64e__
|
||||
address = (vm_address_t)ptrauth_strip(inPtr, ptrauth_key_function_pointer);
|
||||
#else
|
||||
address = (vm_address_t)inPtr;
|
||||
#endif
|
||||
|
||||
// Read the memory
|
||||
vm_size_t size = 0;
|
||||
char buf[sizeof(uintptr_t)];
|
||||
error = vm_read_overwrite(mach_task_self(), address, sizeof(uintptr_t), (vm_address_t)buf, &size);
|
||||
if (error != KERN_SUCCESS) {
|
||||
// vm_read_overwrite returned an error
|
||||
return NO;
|
||||
}
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
/// Accepts addresses that may or may not be readable.
|
||||
/// https://blog.timac.org/2016/1124-testing-if-an-arbitrary-pointer-is-a-valid-objective-c-object/
|
||||
BOOL FLEXPointerIsValidObjcObject(const void *ptr) {
|
||||
uintptr_t pointer = (uintptr_t)ptr;
|
||||
|
||||
if (!ptr) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
#if OBJC_HAVE_TAGGED_POINTERS
|
||||
// Tagged pointers have 0x1 set, no other valid pointers do
|
||||
// objc-internal.h -> _objc_isTaggedPointer()
|
||||
if (flex_isTaggedPointer(ptr) || flex_isExtTaggedPointer(ptr)) {
|
||||
return YES;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Check pointer alignment
|
||||
if ((pointer % sizeof(uintptr_t)) != 0) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
// From LLDB:
|
||||
// Pointers in a class_t will only have bits 0 through 46 set,
|
||||
// so if any pointer has bits 47 through 63 high, we know that this is not a valid isa
|
||||
// https://llvm.org/svn/llvm-project/lldb/trunk/examples/summaries/cocoa/objc_runtime.py
|
||||
if ((pointer & 0xFFFF800000000000) != 0) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
// Make sure dereferencing this address won't crash
|
||||
if (!FLEXPointerIsReadable(ptr)) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
// http://www.sealiesoftware.com/blog/archive/2013/09/24/objc_explain_Non-pointer_isa.html
|
||||
// We check if the returned class is readable because object_getClass
|
||||
// can return a garbage value when given a non-nil pointer to a non-object
|
||||
Class cls = object_getClass((__bridge id)ptr);
|
||||
if (!cls || !FLEXPointerIsReadable((__bridge void *)cls)) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
// Just because this pointer is readable doesn't mean whatever is at
|
||||
// it's ISA offset is readable. We need to do the same checks on it's ISA.
|
||||
// Even this isn't perfect, because once we call object_isClass, we're
|
||||
// going to dereference a member of the metaclass, which may or may not
|
||||
// be readable itself. For the time being there is no way to access it
|
||||
// to check here, and I have yet to hard-code a solution.
|
||||
Class metaclass = object_getClass(cls);
|
||||
if (!metaclass || !FLEXPointerIsReadable((__bridge void *)metaclass)) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
// Does the class pointer we got appear as a class to the runtime?
|
||||
if (!object_isClass(cls)) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
// Is the allocation size at least as large as the expected instance size?
|
||||
ssize_t instanceSize = class_getInstanceSize(cls);
|
||||
if (malloc_size(ptr) < instanceSize) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
|
||||
} // End extern "C"
|
||||
Reference in New Issue
Block a user