Author: thebeing
Date: Fri Aug  7 17:06:38 2015
New Revision: 38859

URL: http://svn.gna.org/viewcvs/gnustep?rev=38859&view=rev
Log:
Safety fix for parsing binary property lists

Added:
    libs/base/trunk/Tests/base/PropertyLists/cyclic.plist   (with props)
Modified:
    libs/base/trunk/ChangeLog
    libs/base/trunk/Source/NSPropertyList.m
    libs/base/trunk/Tests/base/PropertyLists/test01.m

Modified: libs/base/trunk/ChangeLog
URL: 
http://svn.gna.org/viewcvs/gnustep/libs/base/trunk/ChangeLog?rev=38859&r1=38858&r2=38859&view=diff
==============================================================================
--- libs/base/trunk/ChangeLog   (original)
+++ libs/base/trunk/ChangeLog   Fri Aug  7 17:06:38 2015
@@ -1,3 +1,11 @@
+2015-08-07 Niels Grewe <[email protected]>
+
+       * Source/NSPropertyList.m: Cope with certain malformed binary
+       property lists.
+       * Tests/PropertyLists/test01.m
+       * Tests/PropertyLists/cyclic.plist:
+       Test case for binary plists.
+
 2015-08-05 Riccardo Mottola <[email protected]>
 
        * Source/NSArray.m:

Modified: libs/base/trunk/Source/NSPropertyList.m
URL: 
http://svn.gna.org/viewcvs/gnustep/libs/base/trunk/Source/NSPropertyList.m?rev=38859&r1=38858&r2=38859&view=diff
==============================================================================
--- libs/base/trunk/Source/NSPropertyList.m     (original)
+++ libs/base/trunk/Source/NSPropertyList.m     Fri Aug  7 17:06:38 2015
@@ -36,6 +36,7 @@
 #import "Foundation/NSEnumerator.h"
 #import "Foundation/NSError.h"
 #import "Foundation/NSException.h"
+#import "Foundation/NSHashTable.h"
 #import "Foundation/NSPropertyList.h"
 #import "Foundation/NSSerialization.h"
 #import "Foundation/NSStream.h"
@@ -457,6 +458,7 @@
   unsigned             object_count;   // Number of objects
   unsigned             root_index;     // Index of root object
   unsigned             table_start;    // Start address of object table
+  NSHashTable           *_stack; // The stack of objects we are currently 
parsing
 }
 
 - (id) initWithData: (NSData*)plData
@@ -2774,10 +2776,18 @@
 
 
 @implementation GSBinaryPLParser
+#define PUSH_OBJ(index) if (NO == [self _pushObject: index]) \
+        { \
+          [NSException raise: NSGenericException \
+                      format: @"Cyclic object graph"]; \
+        } 
+
+#define POP_OBJ(index) do { [self _popObject: index]; } while (0)
 
 - (void) dealloc
 {
   DESTROY(data);
+  DESTROY(_stack);
   [super dealloc];
 }
 
@@ -2945,6 +2955,28 @@
   return [self objectAtIndex: root_index];
 }
 
+- (BOOL)_pushObject: (NSUInteger)index
+{
+  uintptr_t val;
+  if (nil == _stack)
+    {
+      _stack = NSCreateHashTable(NSIntegerHashCallBacks,
+                                 5);
+    }
+  val = (index == 0) ? UINTPTR_MAX : (uintptr_t)(void*)index;
+  // NSHashInsertIfAbsent() returns NULL on success
+  return NO == NSHashInsertIfAbsent(_stack, (void*)val);
+}
+
+- (void)_popObject: (NSUInteger)index
+{
+  if (_stack != nil)
+    {
+      uintptr_t val = (index == 0) ? UINTPTR_MAX : (uintptr_t)(void*)index;
+      NSHashRemove(_stack, (void*)val);
+    }
+}
+
 - (id) objectAtIndex: (NSUInteger)index
 {
   unsigned char        next;
@@ -3148,14 +3180,14 @@
       unsigned len = next - 0xA0;
       unsigned i;
       id       objects[len];
-
+      PUSH_OBJ(index);
       for (i = 0; i < len; i++)
         {
          int oid = [self readObjectIndexAt: &counter];
 
          objects[i] = [self objectAtIndex: oid];
        }
-
+      POP_OBJ(index);
       if (mutability == NSPropertyListMutableContainersAndLeaves
        || mutability == NSPropertyListMutableContainers)
        {
@@ -3175,14 +3207,14 @@
 
       len = [self readCountAt: &counter];
       objects = NSAllocateCollectable(sizeof(id) * len, NSScannedOption);
-
+      PUSH_OBJ(index);
       for (i = 0; i < len; i++)
         {
          int oid = [self readObjectIndexAt: &counter];
 
          objects[i] = [self objectAtIndex: oid];
        }
-
+      POP_OBJ(index);
       if (mutability == NSPropertyListMutableContainersAndLeaves
        || mutability == NSPropertyListMutableContainers)
        {
@@ -3201,14 +3233,13 @@
       unsigned i;
       id       keys[len];
       id       values[len];
-
+      PUSH_OBJ(index);
       for (i = 0; i < len; i++)
         {
          int oid = [self readObjectIndexAt: &counter];
 
          keys[i] = [self objectAtIndex: oid];
        }
-
       for (i = 0; i < len; i++)
         {
          int oid = [self readObjectIndexAt: &counter];
@@ -3216,6 +3247,7 @@
          values[i] = [self objectAtIndex: oid];
        }
 
+      POP_OBJ(index);
       if (mutability == NSPropertyListMutableContainersAndLeaves
        || mutability == NSPropertyListMutableContainers)
        {
@@ -3241,6 +3273,7 @@
       len = [self readCountAt: &counter];
       keys = NSAllocateCollectable(sizeof(id) * len * 2, NSScannedOption);
       values = keys + len;
+      PUSH_OBJ(index);
       for (i = 0; i < len; i++)
         {
          int oid = [self readObjectIndexAt: &counter];
@@ -3254,7 +3287,7 @@
 
          values[i] = [self objectAtIndex: oid];
        }
-
+      POP_OBJ(index);
       if (mutability == NSPropertyListMutableContainersAndLeaves
        || mutability == NSPropertyListMutableContainers)
        {
@@ -3278,7 +3311,8 @@
 
   return result;
 }
-
+#undef PUSH_OBJ
+#undef POP_OBJ
 @end
 
 /* Test two items for equality ... both are objects.

Added: libs/base/trunk/Tests/base/PropertyLists/cyclic.plist
URL: 
http://svn.gna.org/viewcvs/gnustep/libs/base/trunk/Tests/base/PropertyLists/cyclic.plist?rev=38859&view=auto
==============================================================================
Binary file - no diff available.

Propchange: libs/base/trunk/Tests/base/PropertyLists/cyclic.plist
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Modified: libs/base/trunk/Tests/base/PropertyLists/test01.m
URL: 
http://svn.gna.org/viewcvs/gnustep/libs/base/trunk/Tests/base/PropertyLists/test01.m?rev=38859&r1=38858&r2=38859&view=diff
==============================================================================
--- libs/base/trunk/Tests/base/PropertyLists/test01.m   (original)
+++ libs/base/trunk/Tests/base/PropertyLists/test01.m   Fri Aug  7 17:06:38 2015
@@ -329,6 +329,21 @@
 }
 #endif
 
+#if     defined(GNUSTEP_BASE_LIBRARY)
+{
+  NSData               *d = [NSData dataWithContentsOfFile: @"cyclic.plist"];
+  NSPropertyListFormat format;
+  id                   u = nil;
+  PASS_EXCEPTION(
+  u = [NSPropertyListSerialization propertyListFromData: d
+    mutabilityOption: NSPropertyListImmutable
+    format: &format
+    errorDescription: 0];, NSGenericException, "Does not crash on binary plist 
with cyclic references." );
+  PASS(nil == u, "Rejects cyclic plist");
+}
+#endif
+
+
   [arp release]; arp = nil;
   return 0;
 }


_______________________________________________
Gnustep-cvs mailing list
[email protected]
https://mail.gna.org/listinfo/gnustep-cvs

Reply via email to