]> git.saurik.com Git - cycript.git/blobdiff - ObjectiveC/Library.mm
Fix quote when stringifying C/Objective-C strings.
[cycript.git] / ObjectiveC / Library.mm
index 8c1528da369542e7ce6ad23a26302ae9855fa1f4..ec806658f9d983d86e61d66ba7e83d65d674dd4b 100644 (file)
 
 #include "cycript.hpp"
 
-#include "ObjectiveC/Internal.hpp"
+#include <cmath>
+
+#include <map>
+#include <set>
+
+#include <dlfcn.h>
+
+#ifdef __APPLE__
+#include <malloc/malloc.h>
+#include <mach/mach.h>
+#endif
 
 #include <objc/message.h>
 #include <objc/runtime.h>
 
-#include <Foundation/Foundation.h>
-
 #ifdef __APPLE__
 #include <CoreFoundation/CoreFoundation.h>
 #include <JavaScriptCore/JSStringRefCF.h>
 #endif
 
-#ifdef __APPLE__
-#include <malloc/malloc.h>
-#include <mach/mach.h>
-#endif
+#include <Foundation/Foundation.h>
 
 #include "Code.hpp"
 #include "Error.hpp"
 #include "String.hpp"
 #include "Execute.hpp"
 
-#include <cmath>
-#include <map>
-#include <set>
-
-#include <dlfcn.h>
+#include "ObjectiveC/Internal.hpp"
 
 #define CYObjectiveTry_ { \
     try
@@ -57,7 +58,7 @@
     try
 #define CYObjectiveCatch \
     catch (const CYException &error) { \
-        @throw CYCastNSObject(NULL, context, error.CastJSValue(context)); \
+        @throw CYCastNSObject(NULL, context, error.CastJSValue(context, "Error")); \
     } \
 }
 
@@ -151,12 +152,18 @@ Type_ CYPoolRelease(CYPool *pool, Type_ object) {
 }
 /* }}} */
 /* Objective-C Strings {{{ */
-const char *CYPoolCString(CYPool &pool, JSContextRef context, NSString *value) {
-    size_t size([value maximumLengthOfBytesUsingEncoding:NSUTF8StringEncoding] + 1);
-    char *string(new(pool) char[size]);
+CYUTF8String CYPoolUTF8String(CYPool &pool, JSContextRef context, NSString *value) {
+    size_t size([value maximumLengthOfBytesUsingEncoding:NSUTF8StringEncoding]);
+    char *string(new(pool) char[size + 1]);
     if (![value getCString:string maxLength:size encoding:NSUTF8StringEncoding])
         throw CYJSError(context, "[NSString getCString:maxLength:encoding:] == NO");
-    return string;
+    return CYUTF8String(string, [value lengthOfBytesUsingEncoding:NSUTF8StringEncoding]);
+}
+
+const char *CYPoolCString(CYPool &pool, JSContextRef context, NSString *value) {
+    CYUTF8String utf8(CYPoolUTF8String(pool, context, value));
+    _assert(memchr(utf8.data, '\0', utf8.size) == NULL);
+    return utf8.data;
 }
 
 #ifdef __clang__
@@ -174,7 +181,7 @@ JSStringRef CYCopyJSString(JSContextRef context, NSObject *value) {
     return CYCopyJSString(context, string);
 #else
     CYPool pool;
-    return CYCopyJSString(CYPoolCString(pool, context, string));
+    return CYCopyJSString(CYPoolUTF8String(pool, context, string));
 #endif
 }
 
@@ -1142,7 +1149,7 @@ NSObject *CYCopyNSObject(CYPool &pool, JSContextRef context, JSValueRef value) {
     if (!objective)
         str << '@';
     CYUTF8String string(CYCastUTF8String(self));
-    CYStringify(str, string.data, string.size);
+    CYStringify(str, string.data, string.size, true);
     std::string value(str.str());
     return CYCastNSString(NULL, CYUTF8String(value.c_str(), value.size()));
 }
@@ -1988,11 +1995,6 @@ static JSValueRef Internal_getProperty(JSContextRef context, JSObjectRef object,
     id self(internal->GetValue());
     const char *name(CYPoolCString(pool, context, property));
 
-#ifdef __arm64__
-    if (strcmp(name, "isa") == 0)
-        return CYCastJSValue(context, object_getClass(self));
-#endif
-
     if (objc_ivar *ivar = object_getInstanceVariable(self, name, NULL)) {
         ptrdiff_t offset(ivar_getOffset(ivar));
         void *data(reinterpret_cast<uint8_t *>(self) + offset);
@@ -2008,6 +2010,12 @@ static JSValueRef Internal_getProperty(JSContextRef context, JSObjectRef object,
             uintptr_t mask((1 << length) - 1);
             return CYCastJSValue(context, (field >> shift) & mask);
         } else {
+#if defined(__APPLE__) && defined(__LP64__)
+            // XXX: maybe do even more verifications here
+            if (strcmp(name, "isa") == 0)
+                return CYCastJSValue(context, object_getClass(self));
+#endif
+
             auto type(new(pool) Type_privateData(encoding));
             return CYFromFFI(context, type->type_, type->GetFFI(), data);
         }
@@ -2150,22 +2158,20 @@ static void ObjectiveC_Image_Classes_getPropertyNames(JSContextRef context, JSOb
 
 static JSValueRef ObjectiveC_Images_getProperty(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry {
     CYPool pool;
-    const char *name(CYPoolCString(pool, context, property));
+    CYUTF8String name(CYPoolUTF8String(pool, context, property));
+
     unsigned int size;
     const char **data(objc_copyImageNames(&size));
+    pool.atexit(free, data);
+
     for (size_t i(0); i != size; ++i)
-        if (strcmp(name, data[i]) == 0) {
-            name = data[i];
-            goto free;
+        if (name == data[i]) {
+            JSObjectRef value(JSObjectMake(context, NULL, NULL));
+            CYSetProperty(context, value, CYJSString("classes"), JSObjectMake(context, ObjectiveC_Image_Classes_, const_cast<char *>(data[i])));
+            return value;
         }
-    name = NULL;
-  free:
-    free(data);
-    if (name == NULL)
-        return NULL;
-    JSObjectRef value(JSObjectMake(context, NULL, NULL));
-    CYSetProperty(context, value, CYJSString("classes"), JSObjectMake(context, ObjectiveC_Image_Classes_, const_cast<char *>(name)));
-    return value;
+
+    return NULL;
 } CYCatch(NULL) }
 
 static void ObjectiveC_Images_getPropertyNames(JSContextRef context, JSObjectRef object, JSPropertyNameAccumulatorRef names) {
@@ -2234,7 +2240,7 @@ static void choose_(task_t task, void *baton, unsigned type, vm_range_t *ranges,
             continue;
 
         uintptr_t *pointers(reinterpret_cast<uintptr_t *>(data));
-#ifdef __arm64__
+#if defined(__APPLE__) && defined(__LP64__)
         Class isa(reinterpret_cast<Class>(pointers[0] & 0x1fffffff8));
 #else
         Class isa(reinterpret_cast<Class>(pointers[0]));