Просмотр исходного кода

Harden checks for empty keys

The empty key check needs to recurse into nested arrays and objects. This fixes an error where using a document with an empty key in an atomic update operator wasn't properly detected.
Andreas Braun 8 лет назад
Родитель
Сommit
4228631552
2 измененных файлов с 42 добавлено и 9 удалено
  1. 6 2
      lib/Mongo/MongoCollection.php
  2. 36 7
      tests/Alcaeus/MongoDbAdapter/Mongo/MongoCollectionTest.php

+ 6 - 2
lib/Mongo/MongoCollection.php

@@ -980,12 +980,16 @@ class MongoCollection
         return $options;
         return $options;
     }
     }
 
 
-    private function checkKeys($array)
+    private function checkKeys(array $array)
     {
     {
-        foreach (array_keys($array) as $key) {
+        foreach ($array as $key => $value) {
             if (empty($key) && $key !== 0) {
             if (empty($key) && $key !== 0) {
                 throw new \MongoException('zero-length keys are not allowed, did you use $ with double quotes?');
                 throw new \MongoException('zero-length keys are not allowed, did you use $ with double quotes?');
             }
             }
+
+            if (is_object($value) || is_array($value)) {
+                $this->checkKeys((array) $value);
+            }
         }
         }
     }
     }
 
 

+ 36 - 7
tests/Alcaeus/MongoDbAdapter/Mongo/MongoCollectionTest.php

@@ -103,12 +103,22 @@ class MongoCollectionTest extends TestCase
         $this->assertSame(1, $this->getCollection()->count(['*' => 'foo']));
         $this->assertSame(1, $this->getCollection()->count(['*' => 'foo']));
     }
     }
 
 
-    public function testInsertWithEmptyKey()
+    public function getDocumentsWithEmptyKey()
+    {
+        return [
+            'array' => [['' => 'foo']],
+            'object' => [(object) ['' => 'foo']],
+        ];
+    }
+
+    /**
+     * @dataProvider getDocumentsWithEmptyKey
+     */
+    public function testInsertWithEmptyKey($document)
     {
     {
         $this->expectException(\MongoException::class);
         $this->expectException(\MongoException::class);
         $this->expectExceptionMessage('zero-length keys are not allowed, did you use $ with double quotes?');
         $this->expectExceptionMessage('zero-length keys are not allowed, did you use $ with double quotes?');
 
 
-        $document = ['' => 'foo'];
         $this->getCollection()->insert($document);
         $this->getCollection()->insert($document);
     }
     }
 
 
@@ -263,12 +273,15 @@ class MongoCollectionTest extends TestCase
         $this->assertSame(1, $this->getCollection()->count(['*' => 'foo']));
         $this->assertSame(1, $this->getCollection()->count(['*' => 'foo']));
     }
     }
 
 
-    public function testBatchInsertWithEmptyKey()
+    /**
+     * @dataProvider getDocumentsWithEmptyKey
+     */
+    public function testBatchInsertWithEmptyKey($document)
     {
     {
         $this->expectException(\MongoException::class);
         $this->expectException(\MongoException::class);
         $this->expectExceptionMessage('zero-length keys are not allowed, did you use $ with double quotes?');
         $this->expectExceptionMessage('zero-length keys are not allowed, did you use $ with double quotes?');
 
 
-        $documents = [['' => 'foo']];
+        $documents = [$document];
         $this->getCollection()->batchInsert($documents);
         $this->getCollection()->batchInsert($documents);
     }
     }
 
 
@@ -433,7 +446,10 @@ class MongoCollectionTest extends TestCase
         $this->assertSame(1, $this->getCollection()->count(['*' => 'foo']));
         $this->assertSame(1, $this->getCollection()->count(['*' => 'foo']));
     }
     }
 
 
-    public function testUpdateWithEmptyKey()
+    /**
+     * @dataProvider getDocumentsWithEmptyKey
+     */
+    public function testUpdateWithEmptyKey($updateDocument)
     {
     {
         $document = ['foo' => 'bar'];
         $document = ['foo' => 'bar'];
         $this->getCollection()->insert($document);
         $this->getCollection()->insert($document);
@@ -441,8 +457,21 @@ class MongoCollectionTest extends TestCase
         $this->expectException(\MongoException::class);
         $this->expectException(\MongoException::class);
         $this->expectExceptionMessage('zero-length keys are not allowed, did you use $ with double quotes?');
         $this->expectExceptionMessage('zero-length keys are not allowed, did you use $ with double quotes?');
 
 
-        $update_document = ['' => 'foo'];
-        $this->getCollection()->update($document, $update_document);
+        $this->getCollection()->update($document, $updateDocument);
+    }
+
+    /**
+     * @dataProvider getDocumentsWithEmptyKey
+     */
+    public function testAtomicUpdateWithEmptyKey($updateDocument)
+    {
+        $document = ['foo' => 'bar'];
+        $this->getCollection()->insert($document);
+
+        $this->expectException(\MongoException::class);
+        $this->expectExceptionMessage('zero-length keys are not allowed, did you use $ with double quotes?');
+
+        $this->getCollection()->update($document, ['$set' => $updateDocument]);
     }
     }
 
 
     public function testRemoveMultiple()
     public function testRemoveMultiple()