Skip to content

Commit 37b08b9

Browse files
authored
PHPC:2498: Accept integer types for Document array access (#1781)
Also refactor Document::get() and property handlers
1 parent 65bbd1b commit 37b08b9

5 files changed

+137
-62
lines changed

src/BSON/Document.c

Lines changed: 67 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,36 @@ static bool php_phongo_document_get(php_phongo_document_t* intern, char* key, si
192192
return true;
193193
}
194194

195+
static bool php_phongo_document_get_by_zval(php_phongo_document_t* intern, zval* key, zval* return_value, bool null_if_missing)
196+
{
197+
if (Z_TYPE_P(key) != IS_STRING && Z_TYPE_P(key) != IS_LONG) {
198+
if (null_if_missing) {
199+
ZVAL_NULL(return_value);
200+
return true;
201+
}
202+
203+
phongo_throw_exception(PHONGO_ERROR_RUNTIME, "Could not find key of type \"%s\" in BSON document", zend_zval_type_name(key));
204+
return false;
205+
}
206+
207+
zend_string* tmp_str;
208+
zend_string* str = zval_try_get_tmp_string(key, &tmp_str);
209+
210+
if (!str) {
211+
// Exception already thrown
212+
return false;
213+
}
214+
215+
if (!php_phongo_document_get(intern, ZSTR_VAL(str), ZSTR_LEN(str), return_value, null_if_missing)) {
216+
// Exception already thrown
217+
zend_tmp_string_release(tmp_str);
218+
return false;
219+
}
220+
221+
zend_tmp_string_release(tmp_str);
222+
return true;
223+
}
224+
195225
static PHP_METHOD(MongoDB_BSON_Document, get)
196226
{
197227
php_phongo_document_t* intern;
@@ -204,10 +234,8 @@ static PHP_METHOD(MongoDB_BSON_Document, get)
204234

205235
intern = Z_DOCUMENT_OBJ_P(getThis());
206236

207-
if (!php_phongo_document_get(intern, key, key_len, return_value, false)) {
208-
// Exception already thrown
209-
RETURN_NULL();
210-
}
237+
// May throw, in which case we do nothing
238+
php_phongo_document_get(intern, key, key_len, return_value, false);
211239
}
212240

213241
static PHP_METHOD(MongoDB_BSON_Document, getIterator)
@@ -229,6 +257,30 @@ static bool php_phongo_document_has(php_phongo_document_t* intern, char* key, si
229257
return bson_iter_find_w_len(&iter, key, key_len);
230258
}
231259

260+
static bool php_phongo_document_has_by_zval(php_phongo_document_t* intern, zval* key)
261+
{
262+
if (Z_TYPE_P(key) != IS_STRING && Z_TYPE_P(key) != IS_LONG) {
263+
return false;
264+
}
265+
266+
zend_string* tmp_str;
267+
zend_string* str = zval_try_get_tmp_string(key, &tmp_str);
268+
269+
if (!str) {
270+
// Exception already thrown
271+
return false;
272+
}
273+
274+
if (!php_phongo_document_has(intern, ZSTR_VAL(str), ZSTR_LEN(str))) {
275+
// Exception may be thrown if BSON iterator could not be initialized
276+
zend_tmp_string_release(tmp_str);
277+
return false;
278+
}
279+
280+
zend_tmp_string_release(tmp_str);
281+
return true;
282+
}
283+
232284
static PHP_METHOD(MongoDB_BSON_Document, has)
233285
{
234286
php_phongo_document_t* intern;
@@ -309,11 +361,7 @@ static PHP_METHOD(MongoDB_BSON_Document, offsetExists)
309361

310362
intern = Z_DOCUMENT_OBJ_P(getThis());
311363

312-
if (Z_TYPE_P(offset) != IS_STRING) {
313-
RETURN_FALSE;
314-
}
315-
316-
RETURN_BOOL(php_phongo_document_has(intern, Z_STRVAL_P(offset), Z_STRLEN_P(offset)));
364+
RETURN_BOOL(php_phongo_document_has_by_zval(intern, offset));
317365
}
318366

319367
static PHP_METHOD(MongoDB_BSON_Document, offsetGet)
@@ -327,13 +375,8 @@ static PHP_METHOD(MongoDB_BSON_Document, offsetGet)
327375

328376
intern = Z_DOCUMENT_OBJ_P(getThis());
329377

330-
if (Z_TYPE_P(offset) != IS_STRING) {
331-
phongo_throw_exception(PHONGO_ERROR_RUNTIME, "Could not find key of type \"%s\" in BSON document", zend_zval_type_name(offset));
332-
return;
333-
}
334-
335378
// May throw, in which case we do nothing
336-
php_phongo_document_get(intern, Z_STRVAL_P(offset), Z_STRLEN_P(offset), return_value, false);
379+
php_phongo_document_get_by_zval(intern, offset, return_value, false);
337380
}
338381

339382
static PHP_METHOD(MongoDB_BSON_Document, offsetSet)
@@ -550,13 +593,9 @@ static HashTable* php_phongo_document_get_properties(zend_object* object)
550593

551594
zval* php_phongo_document_read_property(zend_object* object, zend_string* member, int type, void** cache_slot, zval* rv)
552595
{
553-
php_phongo_document_t* intern;
554-
char* key = ZSTR_VAL(member);
555-
size_t key_len = ZSTR_LEN(member);
556-
557-
intern = Z_OBJ_DOCUMENT(object);
596+
php_phongo_document_t* intern = Z_OBJ_DOCUMENT(object);
558597

559-
if (!php_phongo_document_get(intern, key, key_len, rv, type == BP_VAR_IS)) {
598+
if (!php_phongo_document_get(intern, ZSTR_VAL(member), ZSTR_LEN(member), rv, type == BP_VAR_IS)) {
560599
// Exception already thrown
561600
return &EG(uninitialized_zval);
562601
}
@@ -570,15 +609,11 @@ zval* php_phongo_document_write_property(zend_object* object, zend_string* membe
570609
return value;
571610
}
572611

573-
int php_phongo_document_has_property(zend_object* object, zend_string* name, int has_set_exists, void** cache_slot)
612+
int php_phongo_document_has_property(zend_object* object, zend_string* member, int has_set_exists, void** cache_slot)
574613
{
575-
php_phongo_document_t* intern;
576-
char* key = ZSTR_VAL(name);
577-
size_t key_len = ZSTR_LEN(name);
578-
579-
intern = Z_OBJ_DOCUMENT(object);
614+
php_phongo_document_t* intern = Z_OBJ_DOCUMENT(object);
580615

581-
return php_phongo_document_has(intern, key, key_len);
616+
return php_phongo_document_has(intern, ZSTR_VAL(member), ZSTR_LEN(member));
582617
}
583618

584619
void php_phongo_document_unset_property(zend_object* object, zend_string* member, void** cache_slot)
@@ -588,21 +623,9 @@ void php_phongo_document_unset_property(zend_object* object, zend_string* member
588623

589624
zval* php_phongo_document_read_dimension(zend_object* object, zval* offset, int type, zval* rv)
590625
{
591-
php_phongo_document_t* intern;
592-
593-
intern = Z_OBJ_DOCUMENT(object);
594-
595-
if (Z_TYPE_P(offset) != IS_STRING) {
596-
if (type == BP_VAR_IS) {
597-
ZVAL_NULL(rv);
598-
return rv;
599-
}
600-
601-
phongo_throw_exception(PHONGO_ERROR_RUNTIME, "Could not find key of type \"%s\" in BSON document", zend_zval_type_name(offset));
602-
return &EG(uninitialized_zval);
603-
}
626+
php_phongo_document_t* intern = Z_OBJ_DOCUMENT(object);
604627

605-
if (!php_phongo_document_get(intern, Z_STRVAL_P(offset), Z_STRLEN_P(offset), rv, type == BP_VAR_IS)) {
628+
if (!php_phongo_document_get_by_zval(intern, offset, rv, type == BP_VAR_IS)) {
606629
// Exception already thrown
607630
return &EG(uninitialized_zval);
608631
}
@@ -617,15 +640,9 @@ void php_phongo_document_write_dimension(zend_object* object, zval* offset, zval
617640

618641
int php_phongo_document_has_dimension(zend_object* object, zval* member, int check_empty)
619642
{
620-
php_phongo_document_t* intern;
621-
622-
intern = Z_OBJ_DOCUMENT(object);
623-
624-
if (Z_TYPE_P(member) != IS_STRING) {
625-
return false;
626-
}
643+
php_phongo_document_t* intern = Z_OBJ_DOCUMENT(object);
627644

628-
return php_phongo_document_has(intern, Z_STRVAL_P(member), Z_STRLEN_P(member));
645+
return php_phongo_document_has_by_zval(intern, member);
629646
}
630647

631648
void php_phongo_document_unset_dimension(zend_object* object, zval* offset)
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
--TEST--
2+
MongoDB\BSON\Document array access with integers (dimension object accessors)
3+
--FILE--
4+
<?php
5+
6+
require_once __DIR__ . '/../utils/basic.inc';
7+
8+
$document = MongoDB\BSON\Document::fromPHP([
9+
'0' => 'foo',
10+
'1' => 'bar',
11+
]);
12+
13+
// Use a variable to assert that conversion doesn't affect the original zval
14+
$key = 1;
15+
16+
var_dump(isset($document[0]));
17+
var_dump(isset($document[$key]));
18+
var_dump(isset($document[2]));
19+
20+
var_dump($document[0]);
21+
var_dump($document[$key]);
22+
23+
var_dump($key);
24+
25+
?>
26+
===DONE===
27+
<?php exit(0); ?>
28+
--EXPECT--
29+
bool(true)
30+
bool(true)
31+
bool(false)
32+
string(3) "foo"
33+
string(3) "bar"
34+
int(1)
35+
===DONE===
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
--TEST--
2+
MongoDB\BSON\Document array access with integers (ArrayAccess methods)
3+
--FILE--
4+
<?php
5+
6+
require_once __DIR__ . '/../utils/basic.inc';
7+
8+
$document = MongoDB\BSON\Document::fromPHP([
9+
'0' => 'foo',
10+
'1' => 'bar',
11+
]);
12+
13+
// Use a variable to assert that conversion doesn't affect the original zval
14+
$key = 1;
15+
16+
var_dump($document->offsetExists(0));
17+
var_dump($document->offsetExists($key));
18+
var_dump($document->offsetExists(2));
19+
20+
var_dump($document->offsetGet(0));
21+
var_dump($document->offsetGet($key));
22+
23+
var_dump($key);
24+
25+
?>
26+
===DONE===
27+
<?php exit(0); ?>
28+
--EXPECT--
29+
bool(true)
30+
bool(true)
31+
bool(false)
32+
string(3) "foo"
33+
string(3) "bar"
34+
int(1)
35+
===DONE===

tests/bson/bson-document-array-access_error-003.phpt

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,6 @@ $document = MongoDB\BSON\Document::fromPHP([
1111
'int64' => new MongoDB\BSON\Int64(123),
1212
]);
1313

14-
echo throws(function() use ($document) {
15-
$document[0];
16-
}, MongoDB\Driver\Exception\RuntimeException::class), "\n";
17-
1814
echo throws(function() use ($document) {
1915
$document[0.1];
2016
}, MongoDB\Driver\Exception\RuntimeException::class), "\n";
@@ -28,8 +24,6 @@ echo throws(function() use ($document) {
2824
<?php exit(0); ?>
2925
--EXPECT--
3026
OK: Got MongoDB\Driver\Exception\RuntimeException
31-
Could not find key of type "int" in BSON document
32-
OK: Got MongoDB\Driver\Exception\RuntimeException
3327
Could not find key of type "float" in BSON document
3428
OK: Got MongoDB\Driver\Exception\RuntimeException
3529
Could not find key of type "bool" in BSON document

tests/bson/bson-document-array-access_error-004.phpt

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,6 @@ $document = MongoDB\BSON\Document::fromPHP([
1111
'int64' => new MongoDB\BSON\Int64(123),
1212
]);
1313

14-
echo throws(function() use ($document) {
15-
$document->offsetGet(0);
16-
}, MongoDB\Driver\Exception\RuntimeException::class), "\n";
17-
1814
echo throws(function() use ($document) {
1915
$document->offsetGet(0.1);
2016
}, MongoDB\Driver\Exception\RuntimeException::class), "\n";
@@ -28,8 +24,6 @@ echo throws(function() use ($document) {
2824
<?php exit(0); ?>
2925
--EXPECT--
3026
OK: Got MongoDB\Driver\Exception\RuntimeException
31-
Could not find key of type "int" in BSON document
32-
OK: Got MongoDB\Driver\Exception\RuntimeException
3327
Could not find key of type "float" in BSON document
3428
OK: Got MongoDB\Driver\Exception\RuntimeException
3529
Could not find key of type "bool" in BSON document

0 commit comments

Comments
 (0)