Skip to content

Commit 478540b

Browse files
authored
PHPC-2325: Don't throw exception when using coalesce operator in BSON classes (#1492)
* PHPC-2325: Don't throw exception when using coalesce operator in BSON classes * Only silence certain exceptions on coalesce access * Improve tests * Remove exception in has_dimension check for BSON document
1 parent d22cc5c commit 478540b

File tree

5 files changed

+98
-10
lines changed

5 files changed

+98
-10
lines changed

src/BSON/Document.c

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
#include <php.h>
1818
#include <ext/standard/base64.h>
19+
#include <Zend/zend_exceptions.h>
1920
#include <Zend/zend_interfaces.h>
2021
#include <Zend/zend_operators.h>
2122
#include <ext/standard/php_var.h>
@@ -167,7 +168,7 @@ static PHP_METHOD(MongoDB_BSON_Document, fromPHP)
167168
RETURN_ZVAL(&zv, 1, 1);
168169
}
169170

170-
static bool php_phongo_document_get(php_phongo_document_t* intern, char* key, size_t key_len, zval* return_value)
171+
static bool php_phongo_document_get(php_phongo_document_t* intern, char* key, size_t key_len, zval* return_value, bool null_if_missing)
171172
{
172173
bson_iter_t iter;
173174

@@ -177,6 +178,11 @@ static bool php_phongo_document_get(php_phongo_document_t* intern, char* key, si
177178
}
178179

179180
if (!bson_iter_find_w_len(&iter, key, key_len)) {
181+
if (null_if_missing) {
182+
ZVAL_NULL(return_value);
183+
return true;
184+
}
185+
180186
phongo_throw_exception(PHONGO_ERROR_RUNTIME, "Could not find key \"%s\" in BSON document", key);
181187
return false;
182188
}
@@ -198,7 +204,7 @@ static PHP_METHOD(MongoDB_BSON_Document, get)
198204

199205
intern = Z_DOCUMENT_OBJ_P(getThis());
200206

201-
if (!php_phongo_document_get(intern, key, key_len, return_value)) {
207+
if (!php_phongo_document_get(intern, key, key_len, return_value, false)) {
202208
// Exception already thrown
203209
RETURN_NULL();
204210
}
@@ -327,7 +333,7 @@ static PHP_METHOD(MongoDB_BSON_Document, offsetGet)
327333
}
328334

329335
// May throw, in which case we do nothing
330-
php_phongo_document_get(intern, Z_STRVAL_P(offset), Z_STRLEN_P(offset), return_value);
336+
php_phongo_document_get(intern, Z_STRVAL_P(offset), Z_STRLEN_P(offset), return_value, false);
331337
}
332338

333339
static PHP_METHOD(MongoDB_BSON_Document, offsetSet)
@@ -552,7 +558,7 @@ zval* php_phongo_document_read_property(phongo_compat_object_handler_type* objec
552558

553559
PHONGO_COMPAT_PROPERTY_ACCESSOR_NAME_TO_STRING(member, key, key_len);
554560

555-
if (!php_phongo_document_get(intern, key, key_len, rv)) {
561+
if (!php_phongo_document_get(intern, key, key_len, rv, type == BP_VAR_IS)) {
556562
// Exception already thrown
557563
return &EG(uninitialized_zval);
558564
}
@@ -591,11 +597,16 @@ zval* php_phongo_document_read_dimension(phongo_compat_object_handler_type* obje
591597
intern = Z_OBJ_DOCUMENT(PHONGO_COMPAT_GET_OBJ(object));
592598

593599
if (Z_TYPE_P(offset) != IS_STRING) {
600+
if (type == BP_VAR_IS) {
601+
ZVAL_NULL(rv);
602+
return rv;
603+
}
604+
594605
phongo_throw_exception(PHONGO_ERROR_RUNTIME, "Could not find key of type \"%s\" in BSON document", PHONGO_ZVAL_CLASS_OR_TYPE_NAME_P(offset));
595606
return &EG(uninitialized_zval);
596607
}
597608

598-
if (!php_phongo_document_get(intern, Z_STRVAL_P(offset), Z_STRLEN_P(offset), rv)) {
609+
if (!php_phongo_document_get(intern, Z_STRVAL_P(offset), Z_STRLEN_P(offset), rv, type == BP_VAR_IS)) {
599610
// Exception already thrown
600611
return &EG(uninitialized_zval);
601612
}
@@ -615,7 +626,6 @@ int php_phongo_document_has_dimension(phongo_compat_object_handler_type* object,
615626
intern = Z_OBJ_DOCUMENT(PHONGO_COMPAT_GET_OBJ(object));
616627

617628
if (Z_TYPE_P(member) != IS_STRING) {
618-
phongo_throw_exception(PHONGO_ERROR_RUNTIME, "Could not find key of type \"%s\" in BSON document", PHONGO_ZVAL_CLASS_OR_TYPE_NAME_P(member));
619629
return false;
620630
}
621631

src/BSON/PackedArray.c

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include <php.h>
1818
#include <ext/standard/base64.h>
1919
#include <Zend/zend_interfaces.h>
20+
#include <Zend/zend_exceptions.h>
2021
#include <Zend/zend_operators.h>
2122
#include <ext/standard/php_var.h>
2223
#include <zend_smart_str.h>
@@ -117,7 +118,7 @@ static bool seek_iter_to_index(bson_iter_t* iter, zend_long index)
117118
return true;
118119
}
119120

120-
static bool php_phongo_packedarray_get(php_phongo_packedarray_t* intern, zend_long index, zval* return_value)
121+
static bool php_phongo_packedarray_get(php_phongo_packedarray_t* intern, zend_long index, zval* return_value, bool null_if_missing)
121122
{
122123
bson_iter_t iter;
123124

@@ -127,6 +128,11 @@ static bool php_phongo_packedarray_get(php_phongo_packedarray_t* intern, zend_lo
127128
}
128129

129130
if (!seek_iter_to_index(&iter, index)) {
131+
if (null_if_missing) {
132+
ZVAL_NULL(return_value);
133+
return true;
134+
}
135+
130136
phongo_throw_exception(PHONGO_ERROR_RUNTIME, "Could not find index \"%d\" in BSON array", index);
131137
return false;
132138
}
@@ -147,7 +153,7 @@ static PHP_METHOD(MongoDB_BSON_PackedArray, get)
147153

148154
intern = Z_PACKEDARRAY_OBJ_P(getThis());
149155

150-
if (!php_phongo_packedarray_get(intern, index, return_value)) {
156+
if (!php_phongo_packedarray_get(intern, index, return_value, false)) {
151157
// Exception already thrown
152158
RETURN_NULL();
153159
}
@@ -254,7 +260,7 @@ static PHP_METHOD(MongoDB_BSON_PackedArray, offsetGet)
254260
}
255261

256262
// May throw, in which case we do nothing
257-
php_phongo_packedarray_get(intern, Z_LVAL_P(key), return_value);
263+
php_phongo_packedarray_get(intern, Z_LVAL_P(key), return_value, false);
258264
}
259265

260266
static PHP_METHOD(MongoDB_BSON_PackedArray, offsetSet)
@@ -477,11 +483,16 @@ zval* php_phongo_packedarray_read_dimension(phongo_compat_object_handler_type* o
477483
intern = Z_OBJ_PACKEDARRAY(PHONGO_COMPAT_GET_OBJ(object));
478484

479485
if (Z_TYPE_P(offset) != IS_LONG) {
486+
if (type == BP_VAR_IS) {
487+
ZVAL_NULL(rv);
488+
return rv;
489+
}
490+
480491
phongo_throw_exception(PHONGO_ERROR_RUNTIME, "Could not find index of type \"%s\" in BSON array", PHONGO_ZVAL_CLASS_OR_TYPE_NAME_P(offset));
481492
return &EG(uninitialized_zval);
482493
}
483494

484-
if (!php_phongo_packedarray_get(intern, Z_LVAL_P(offset), rv)) {
495+
if (!php_phongo_packedarray_get(intern, Z_LVAL_P(offset), rv, type == BP_VAR_IS)) {
485496
// Exception already thrown
486497
return &EG(uninitialized_zval);
487498
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
--TEST--
2+
MongoDB\BSON\Document array access (coalesce operator)
3+
--FILE--
4+
<?php
5+
6+
require_once __DIR__ . '/../utils/basic.inc';
7+
8+
$document = MongoDB\BSON\Document::fromPHP([]);
9+
10+
var_dump(isset($document['foo']));
11+
var_dump($document['foo'] ?? 'fallback');
12+
13+
var_dump(isset($document[0]));
14+
var_dump($document[0] ?? 'fallback');
15+
16+
?>
17+
===DONE===
18+
<?php exit(0); ?>
19+
--EXPECT--
20+
bool(false)
21+
string(8) "fallback"
22+
bool(false)
23+
string(8) "fallback"
24+
===DONE===
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
--TEST--
2+
MongoDB\BSON\Document property access (coalesce operator)
3+
--FILE--
4+
<?php
5+
6+
require_once __DIR__ . '/../utils/basic.inc';
7+
8+
$document = MongoDB\BSON\Document::fromPHP([]);
9+
10+
var_dump(isset($document->foo));
11+
var_dump($document->foo ?? 'fallback');
12+
13+
?>
14+
===DONE===
15+
<?php exit(0); ?>
16+
--EXPECT--
17+
bool(false)
18+
string(8) "fallback"
19+
===DONE===
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
--TEST--
2+
MongoDB\BSON\PackedArray array access (coalesce operator)
3+
--FILE--
4+
<?php
5+
6+
require_once __DIR__ . '/../utils/basic.inc';
7+
8+
$array = MongoDB\BSON\PackedArray::fromPHP([]);
9+
10+
var_dump(isset($array[0]));
11+
var_dump($array[0] ?? 'fallback');
12+
13+
var_dump(isset($array['foo']));
14+
var_dump($array['foo'] ?? 'fallback');
15+
16+
?>
17+
===DONE===
18+
<?php exit(0); ?>
19+
--EXPECT--
20+
bool(false)
21+
string(8) "fallback"
22+
bool(false)
23+
string(8) "fallback"
24+
===DONE===

0 commit comments

Comments
 (0)