Commits

Ronald Oussoren  committed e5b19f0

Accessing magic-cookie objects crashed the interpreter

Fixes issue #50

  • Participants
  • Parent commits 3b2618f

Comments (0)

Files changed (7)

File pyobjc-core/Lib/objc/_convenience_nsobject.py

     return int(rval)
 
 def nsobject__eq__(self, other):
+    if self.__is_magic():
+        return self is other
     return bool(self.isEqualTo_(other))
 
 def nsobject__ne__(self, other):
+    if self.__is_magic():
+        return self is not other
     return bool(self.isNotEqualTo_(other))
 
 def nsobject__gt__(self, other):
+    if self.__is_magic():
+        return NotImplemented
     return bool(self.isGreaterThan_(other))
 
 def nsobject__ge__(self, other):
+    if self.__is_magic():
+        return NotImplemented
     return bool(self.isGreaterThanOrEqualTo_(other))
 
 def nsobject__lt__(self, other):
+    if self.__is_magic():
+        return NotImplemented
     return bool(self.isLessThan_(other))
 
 def nsobject__le__(self, other):
+    if self.__is_magic():
+        return NotImplemented
     return bool(self.isLessThanOrEqualTo_(other))
 
 class kvc (object):

File pyobjc-core/Modules/objc/libffi_support.m

  */
 
 static const char gCharEncoding[] = { _C_CHR, 0 };
-static const char gCFRangeEncoding[1024] = { 0 };
 
 #if defined(__ppc__)
 

File pyobjc-core/Modules/objc/objc-object.h

 #define PyObjCObject_GetFlags(object) (((PyObjCObject*)(object))->flags)
 #define PyObjCObject_IsClassic(object) (PyObjCObject_GetFlags(object) & PyObjCObject_kCLASSIC)
 #define PyObjCObject_IsBlock(object) (PyObjCObject_GetFlags(object) & PyObjCObject_kBLOCK)
+#define PyObjCObject_IsMagic(object) (PyObjCObject_GetFlags(object) & PyObjCObject_kMAGIC_COOKIE)
 #define PyObjCObject_GetBlock(object) (((PyObjCBlockObject*)(object))->signature)
 #define PyObjCObject_SET_BLOCK(object, value) (((PyObjCBlockObject*)(object))->signature = (value))
 

File pyobjc-core/Modules/objc/objc-object.m

 }
 
 static PyObject*
+meth_is_magic(PyObject* self)
+{
+    if (PyObjCObject_GetObject(self) == nil) {
+        return PyBool_FromLong(0);
+    } else {
+        return PyBool_FromLong(PyObjCObject_IsMagic(self));
+    }
+}
+
+static PyObject*
 as_cobject(PyObject* self)
 {
     if (PyObjCObject_GetObject(self) == nil) {
         return NULL;
     }
 
+    if (PyObjCObject_IsMagic(self)) {
+        /* "magic cookie" objects don't have Objective-C methods */
+        return result;
+    }
+
     cls = object_getClass(PyObjCObject_GetObject(self));
     while (cls != NULL) {
         /* Now add all instance method names */
         .ml_flags   = METH_NOARGS,
     },
     {
+        .ml_name    = "__is_magic",
+        .ml_meth    = (PyCFunction)meth_is_magic,
+        .ml_flags   = METH_NOARGS,
+    },
+    {
         .ml_name    = "__dir__",
         .ml_meth    = (PyCFunction)meth_dir,
         .ml_flags   = METH_NOARGS,

File pyobjc-core/Modules/objc/objc_support.m

          */
         if (strncmp(type,
             @encode(struct sockaddr),
-            sizeof(@encode(struct sockaddr)-1)) == 0) {
+            sizeof(@encode(struct sockaddr))-1) == 0) {
 
             return sizeof(struct sockaddr_in6);
         }
     Py_ssize_t pack;
 
     /* Hacked up support for socket addresses */
-    if (strncmp(type, @encode(struct sockaddr), sizeof(@encode(struct sockaddr)-1)) == 0) {
+    if (strncmp(type, @encode(struct sockaddr), sizeof(@encode(struct sockaddr))-1) == 0) {
         return PyObjC_SockAddrToPython(datum);
     }
 
     Py_ssize_t pack;
 
     /* Hacked in support for sockaddr structs */
-    if (strncmp(types, @encode(struct sockaddr), sizeof(@encode(struct sockaddr)-1)) == 0) {
+    if (strncmp(types, @encode(struct sockaddr), sizeof(@encode(struct sockaddr))-1) == 0) {
         return PyObjC_SockAddrFromPython(arg, datum);
     }
 

File pyobjc-core/Modules/objc/selector.m

     char buf[2048];
 
     if (PyObjCObject_Check(self)) {
-        if (PyObjCClass_HiddenSelector((PyObject*)Py_TYPE(self), sel, NO)) {
+        if (PyObjCObject_IsMagic(self) || PyObjCClass_HiddenSelector((PyObject*)Py_TYPE(self), sel, NO)) {
             PyErr_Format(PyExc_AttributeError,
                 "No attribute %s", name);
             return NULL;

File pyobjc-core/NEWS.txt

 Version 3.0
 -----------
 
+* Issue #50: Accessing Objective-C methods on "magic cookie" variables,
+  like ``LaunchServices.kLSSharedFileListItemLast`` would crash the interpreter.
+
+  This affected code like::
+
+      from LaunchServices import kLSSharedFileListItemLast
+
+      kLSSharedFileListItemLast == kLSSharedFileListItemLast
+      dir(kLSSharedFileListItemLast)
+      kLSSharedFileListItemLast.compare_
+
 * Added a decorator "python_method" than can be used to decorate methods that should
   not be registered with the Objective-C runtime and should not be converted to a
   Objective-C selector.