@@ -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/* }}} */
0 commit comments