Skip to content

Commit 6dc2f9d

Browse files
committed
Merge pull request #575
2 parents 04b4bf0 + 52eae8b commit 6dc2f9d

File tree

9 files changed

+180
-137
lines changed

9 files changed

+180
-137
lines changed

phongo_compat.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@
130130
# define ADD_NEXT_INDEX_STRINGL(_zv, _value, _len) add_next_index_stringl(_zv, _value, _len, 1);
131131
# define Z_PHPDATE_P(object) ((php_date_obj*)zend_object_store_get_object(object TSRMLS_CC))
132132
# define Z_ISUNDEF(x) !x
133+
# define ZVAL_UNDEF(x) do { (*x) = NULL; } while (0)
133134
# define phongo_free_object_arg void
134135
# define phongo_zpp_char_len int
135136
# define ZEND_HASH_APPLY_PROTECTION(ht) true

php_phongo.c

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -385,11 +385,7 @@ zend_bool phongo_writeconcernerror_init(zval *return_value, bson_t *bson TSRMLS_
385385

386386
if (!phongo_bson_to_zval(data, len, &intern->info)) {
387387
zval_ptr_dtor(&intern->info);
388-
#if PHP_VERSION_ID >= 70000
389388
ZVAL_UNDEF(&intern->info);
390-
#else
391-
intern->info = NULL;
392-
#endif
393389

394390
return false;
395391
}
@@ -426,11 +422,7 @@ zend_bool phongo_writeerror_init(zval *return_value, bson_t *bson TSRMLS_DC) /*
426422

427423
if (!phongo_bson_to_zval(data, len, &intern->info)) {
428424
zval_ptr_dtor(&intern->info);
429-
#if PHP_VERSION_ID >= 70000
430425
ZVAL_UNDEF(&intern->info);
431-
#else
432-
intern->info = NULL;
433-
#endif
434426

435427
return false;
436428
}

src/MongoDB/Cursor.c

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,7 @@ static void php_phongo_cursor_free_current(php_phongo_cursor_t *cursor) /* {{{ *
4444
{
4545
if (!Z_ISUNDEF(cursor->visitor_data.zchild)) {
4646
zval_ptr_dtor(&cursor->visitor_data.zchild);
47-
#if PHP_VERSION_ID >= 70000
4847
ZVAL_UNDEF(&cursor->visitor_data.zchild);
49-
#else
50-
cursor->visitor_data.zchild = NULL;
51-
#endif
5248
}
5349
} /* }}} */
5450

src/bson.c

Lines changed: 36 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1019,15 +1019,16 @@ void object_to_bson(zval *object, php_phongo_bson_flags_t flags, const char *key
10191019
zval *obj_data = NULL;
10201020
#endif
10211021
bson_t child;
1022-
HashTable *tmp_ht;
1022+
10231023
#if PHP_VERSION_ID >= 70000
10241024
zend_call_method_with_0_params(object, NULL, NULL, BSON_SERIALIZE_FUNC_NAME, &obj_data);
10251025
#else
10261026
zend_call_method_with_0_params(&object, NULL, NULL, BSON_SERIALIZE_FUNC_NAME, &obj_data);
10271027
#endif
10281028

10291029
if (Z_ISUNDEF(obj_data)) {
1030-
/* zend_call_method() failed */
1030+
/* zend_call_method() failed or bsonSerialize() threw an
1031+
* exception. Either way, there is nothing else to do. */
10311032
return;
10321033
}
10331034

@@ -1060,16 +1061,6 @@ void object_to_bson(zval *object, php_phongo_bson_flags_t flags, const char *key
10601061
return;
10611062
}
10621063

1063-
#if PHP_VERSION_ID >= 70000
1064-
tmp_ht = HASH_OF(&obj_data);
1065-
#else
1066-
tmp_ht = HASH_OF(obj_data);
1067-
#endif
1068-
1069-
if (tmp_ht && ZEND_HASH_APPLY_PROTECTION(tmp_ht)) {
1070-
ZEND_HASH_INC_APPLY_COUNT(tmp_ht);
1071-
}
1072-
10731064
/* Persistable objects must always be serialized as BSON documents;
10741065
* otherwise, infer based on bsonSerialize()'s return value. */
10751066
#if PHP_VERSION_ID >= 70000
@@ -1101,9 +1092,6 @@ void object_to_bson(zval *object, php_phongo_bson_flags_t flags, const char *key
11011092
bson_append_array_end(bson, &child);
11021093
}
11031094

1104-
if (tmp_ht && ZEND_HASH_APPLY_PROTECTION(tmp_ht)) {
1105-
ZEND_HASH_DEC_APPLY_COUNT(tmp_ht);
1106-
}
11071095
zval_ptr_dtor(&obj_data);
11081096
return;
11091097
}
@@ -1176,20 +1164,10 @@ void object_to_bson(zval *object, php_phongo_bson_flags_t flags, const char *key
11761164
phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE TSRMLS_CC, "Unexpected %s instance: %s", ZSTR_VAL(php_phongo_type_ce->name), ZSTR_VAL(Z_OBJCE_P(object)->name));
11771165
return;
11781166
} else {
1179-
HashTable *tmp_ht = HASH_OF(object);
1180-
1181-
if (tmp_ht && ZEND_HASH_APPLY_PROTECTION(tmp_ht)) {
1182-
ZEND_HASH_INC_APPLY_COUNT(tmp_ht);
1183-
}
1184-
11851167
mongoc_log(MONGOC_LOG_LEVEL_TRACE, MONGOC_LOG_DOMAIN, "encoding document");
11861168
bson_append_document_begin(bson, key, key_len, &child);
11871169
phongo_zval_to_bson(object, flags, &child, NULL TSRMLS_CC);
11881170
bson_append_document_end(bson, &child);
1189-
1190-
if (tmp_ht && ZEND_HASH_APPLY_PROTECTION(tmp_ht)) {
1191-
ZEND_HASH_DEC_APPLY_COUNT(tmp_ht);
1192-
}
11931171
}
11941172
}
11951173

@@ -1238,6 +1216,11 @@ static void phongo_bson_append(bson_t *bson, php_phongo_bson_flags_t flags, cons
12381216
bson_t child;
12391217
HashTable *tmp_ht = HASH_OF(entry);
12401218

1219+
if (tmp_ht && ZEND_HASH_GET_APPLY_COUNT(tmp_ht) > 0) {
1220+
phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE TSRMLS_CC, "Detected recursion for fieldname \"%s\"", key);
1221+
break;
1222+
}
1223+
12411224
if (tmp_ht && ZEND_HASH_APPLY_PROTECTION(tmp_ht)) {
12421225
ZEND_HASH_INC_APPLY_COUNT(tmp_ht);
12431226
}
@@ -1252,9 +1235,25 @@ static void phongo_bson_append(bson_t *bson, php_phongo_bson_flags_t flags, cons
12521235
break;
12531236
}
12541237
/* break intentionally omitted */
1255-
case IS_OBJECT:
1238+
case IS_OBJECT: {
1239+
HashTable *tmp_ht = HASH_OF(entry);
1240+
1241+
if (tmp_ht && ZEND_HASH_GET_APPLY_COUNT(tmp_ht) > 0) {
1242+
phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE TSRMLS_CC, "Detected recursion for fieldname \"%s\"", key);
1243+
break;
1244+
}
1245+
1246+
if (tmp_ht && ZEND_HASH_APPLY_PROTECTION(tmp_ht)) {
1247+
ZEND_HASH_INC_APPLY_COUNT(tmp_ht);
1248+
}
1249+
12561250
object_to_bson(entry, flags, key, key_len, bson TSRMLS_CC);
1251+
1252+
if (tmp_ht && ZEND_HASH_APPLY_PROTECTION(tmp_ht)) {
1253+
ZEND_HASH_DEC_APPLY_COUNT(tmp_ht);
1254+
}
12571255
break;
1256+
}
12581257

12591258
#if PHP_VERSION_ID >= 70000
12601259
case IS_INDIRECT:
@@ -1285,6 +1284,8 @@ void phongo_zval_to_bson(zval *data, php_phongo_bson_flags_t flags, bson_t *bson
12851284
* properties, we'll need to filter them out later. */
12861285
bool ht_data_from_properties = false;
12871286

1287+
ZVAL_UNDEF(&obj_data);
1288+
12881289
switch(Z_TYPE_P(data)) {
12891290
case IS_OBJECT:
12901291
if (instanceof_function(Z_OBJCE_P(data), php_phongo_serializable_ce TSRMLS_CC)) {
@@ -1295,8 +1296,9 @@ void phongo_zval_to_bson(zval *data, php_phongo_bson_flags_t flags, bson_t *bson
12951296
#endif
12961297

12971298
if (Z_ISUNDEF(obj_data)) {
1298-
/* zend_call_method() failed */
1299-
break;
1299+
/* zend_call_method() failed or bsonSerialize() threw an
1300+
* exception. Either way, there is nothing else to do. */
1301+
return;
13001302
}
13011303

13021304
#if PHP_VERSION_ID >= 70000
@@ -1324,7 +1326,7 @@ void phongo_zval_to_bson(zval *data, php_phongo_bson_flags_t flags, bson_t *bson
13241326
)
13251327
);
13261328

1327-
break;
1329+
goto cleanup;
13281330
}
13291331

13301332
#if PHP_VERSION_ID >= 70000
@@ -1349,7 +1351,7 @@ void phongo_zval_to_bson(zval *data, php_phongo_bson_flags_t flags, bson_t *bson
13491351
if (instanceof_function(Z_OBJCE_P(data), php_phongo_type_ce TSRMLS_CC)) {
13501352
phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE TSRMLS_CC, "%s instance %s cannot be serialized as a root element", ZSTR_VAL(php_phongo_type_ce->name), ZSTR_VAL(Z_OBJCE_P(data)->name));
13511353

1352-
break;
1354+
return;
13531355
}
13541356

13551357
ht_data = Z_OBJ_HT_P(data)->get_properties(data TSRMLS_CC);
@@ -1364,19 +1366,6 @@ void phongo_zval_to_bson(zval *data, php_phongo_bson_flags_t flags, bson_t *bson
13641366
return;
13651367
}
13661368

1367-
if (!ht_data || ZEND_HASH_GET_APPLY_COUNT(ht_data) > 1) {
1368-
#if PHP_VERSION_ID >= 70000
1369-
if (Z_TYPE_P(data) == IS_OBJECT && instanceof_function(Z_OBJCE_P(data), php_phongo_serializable_ce TSRMLS_CC)) {
1370-
#endif
1371-
if (!Z_ISUNDEF(obj_data)) {
1372-
zval_ptr_dtor(&obj_data);
1373-
}
1374-
#if PHP_VERSION_ID >= 70000
1375-
}
1376-
#endif
1377-
return;
1378-
}
1379-
13801369
#if PHP_VERSION_ID >= 70000
13811370
{
13821371
zend_string *string_key = NULL;
@@ -1483,15 +1472,11 @@ void phongo_zval_to_bson(zval *data, php_phongo_bson_flags_t flags, bson_t *bson
14831472
}
14841473
}
14851474
}
1486-
#if PHP_VERSION_ID >= 70000
1487-
if (Z_TYPE_P(data) == IS_OBJECT && instanceof_function(Z_OBJCE_P(data), php_phongo_serializable_ce TSRMLS_CC)) {
1488-
#endif
1489-
if (!Z_ISUNDEF(obj_data)) {
1490-
zval_ptr_dtor(&obj_data);
1491-
}
1492-
#if PHP_VERSION_ID >= 70000
1475+
1476+
cleanup:
1477+
if (!Z_ISUNDEF(obj_data)) {
1478+
zval_ptr_dtor(&obj_data);
14931479
}
1494-
#endif
14951480
}
14961481

14971482
/* }}} */

tests/bson/bson-fromPHP-004.phpt

Lines changed: 0 additions & 38 deletions
This file was deleted.

tests/bson/bson-fromPHP-006.phpt

Lines changed: 0 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -5,58 +5,22 @@ BSON\fromPHP(): PHP documents with null bytes in field name
55

66
require_once __DIR__ . '/../utils/tools.php';
77

8-
echo "\nTesting array with one leading null byte in field name\n";
9-
echo throws(function() {
10-
fromPHP(["\0" => 1]);
11-
}, 'MongoDB\Driver\Exception\UnexpectedValueException'), "\n";
12-
13-
echo "\nTesting array with one trailing null byte in field name\n";
14-
echo throws(function() {
15-
fromPHP(["a\0" => 1]);
16-
}, 'MongoDB\Driver\Exception\UnexpectedValueException'), "\n";
17-
18-
echo "\nTesting array with multiple null bytes in field name\n";
19-
echo throws(function() {
20-
fromPHP(["\0\0\0" => 1]);
21-
}, 'MongoDB\Driver\Exception\UnexpectedValueException'), "\n";
22-
238
/* Per PHPC-884, field names with a leading null byte are ignored when encoding
249
* a document from an object's property hash table, since PHP uses leading bytes
2510
* to denote protected and private properties. */
2611
echo "\nTesting object with one leading null byte in field name\n";
2712
hex_dump(fromPHP((object) ["\0" => 1]));
2813

29-
echo "\nTesting object with one trailing null byte in field name\n";
30-
echo throws(function() {
31-
fromPHP((object) ["a\0" => 1]);
32-
}, 'MongoDB\Driver\Exception\UnexpectedValueException'), "\n";
33-
3414
echo "\nTesting object with multiple null bytes in field name\n";
3515
hex_dump(fromPHP((object) ["\0\0\0" => 1]));
3616

3717
?>
3818
===DONE===
3919
<?php exit(0); ?>
4020
--EXPECT--
41-
Testing array with one leading null byte in field name
42-
OK: Got MongoDB\Driver\Exception\UnexpectedValueException
43-
BSON keys cannot contain null bytes. Unexpected null byte after "".
44-
45-
Testing array with one trailing null byte in field name
46-
OK: Got MongoDB\Driver\Exception\UnexpectedValueException
47-
BSON keys cannot contain null bytes. Unexpected null byte after "a".
48-
49-
Testing array with multiple null bytes in field name
50-
OK: Got MongoDB\Driver\Exception\UnexpectedValueException
51-
BSON keys cannot contain null bytes. Unexpected null byte after "".
52-
5321
Testing object with one leading null byte in field name
5422
0 : 05 00 00 00 00 [.....]
5523

56-
Testing object with one trailing null byte in field name
57-
OK: Got MongoDB\Driver\Exception\UnexpectedValueException
58-
BSON keys cannot contain null bytes. Unexpected null byte after "a".
59-
6024
Testing object with multiple null bytes in field name
6125
0 : 05 00 00 00 00 [.....]
6226
===DONE===
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
--TEST--
2+
BSON\fromPHP(): PHP documents with circular references
3+
--FILE--
4+
<?php
5+
6+
require_once __DIR__ . '/../utils/tools.php';
7+
8+
echo "\nTesting packed array with circular reference\n";
9+
10+
echo throws(function() {
11+
$document = ['x' => 1, 'y' => []];
12+
$document['y'][] = &$document['y'];
13+
fromPHP($document);
14+
}, 'MongoDB\Driver\Exception\UnexpectedValueException'), "\n";
15+
16+
echo "\nTesting associative array with circular reference\n";
17+
18+
echo throws(function() {
19+
$document = ['x' => 1, 'y' => []];
20+
$document['y']['z'] = &$document['y'];
21+
fromPHP($document);
22+
}, 'MongoDB\Driver\Exception\UnexpectedValueException'), "\n";
23+
24+
echo "\nTesting object with circular reference\n";
25+
26+
echo throws(function() {
27+
$document = (object) ['x' => 1, 'y' => (object) []];
28+
$document->y->z = &$document->y;
29+
fromPHP($document);
30+
}, 'MongoDB\Driver\Exception\UnexpectedValueException'), "\n";
31+
32+
?>
33+
===DONE===
34+
<?php exit(0); ?>
35+
--EXPECTF--
36+
Testing packed array with circular reference
37+
OK: Got MongoDB\Driver\Exception\UnexpectedValueException
38+
Detected recursion for fieldname "0"
39+
40+
Testing associative array with circular reference
41+
OK: Got MongoDB\Driver\Exception\UnexpectedValueException
42+
Detected recursion for fieldname "z"
43+
44+
Testing object with circular reference
45+
OK: Got MongoDB\Driver\Exception\UnexpectedValueException
46+
Detected recursion for fieldname "z"
47+
===DONE===

0 commit comments

Comments
 (0)