@@ -179,21 +179,9 @@ bool php_phongo_bson_visit_after(const bson_iter_t *iter ARG_UNUSED, const char
179
179
}
180
180
/* }}} */
181
181
#endif
182
- void php_phongo_bson_visit_corrupt (const bson_iter_t * iter ARG_UNUSED , void * data ) /* {{{ */
182
+ void php_phongo_bson_visit_corrupt (const bson_iter_t * iter ARG_UNUSED , void * data ARG_UNUSED ) /* {{{ */
183
183
{
184
- #if PHP_VERSION_ID >= 70000
185
- zval * retval = & ((php_phongo_bson_state * )data )-> zchild ;
186
- #else
187
- zval * retval = ((php_phongo_bson_state * )data )-> zchild ;
188
- #endif
189
-
190
184
mongoc_log (MONGOC_LOG_LEVEL_TRACE , MONGOC_LOG_DOMAIN , "Corrupt BSON data detected!" );
191
-
192
- #if PHP_VERSION_ID >= 70000
193
- zval_ptr_dtor (retval );
194
- #else
195
- zval_ptr_dtor (& retval );
196
- #endif
197
185
}
198
186
/* }}} */
199
187
bool php_phongo_bson_visit_double (const bson_iter_t * iter ARG_UNUSED , const char * key , double v_double , void * data ) /* {{{ */
@@ -612,7 +600,7 @@ bool php_phongo_bson_visit_document(const bson_iter_t *iter ARG_UNUSED, const ch
612
600
array_init (state .zchild );
613
601
#endif
614
602
615
- if (!bson_iter_visit_all (& child , & php_bson_visitors , & state )) {
603
+ if (!bson_iter_visit_all (& child , & php_bson_visitors , & state ) && ! child . err_off ) {
616
604
/* If php_phongo_bson_visit_binary() finds an ODM class, it should
617
605
* supersede a default type map and named document class. */
618
606
if (state .odm && state .map .document_type == PHONGO_TYPEMAP_NONE ) {
@@ -662,6 +650,11 @@ bool php_phongo_bson_visit_document(const bson_iter_t *iter ARG_UNUSED, const ch
662
650
Z_SET_REFCOUNT_P (state .zchild , 1 );
663
651
#endif
664
652
}
653
+ } else {
654
+ /* Iteration stopped prematurely due to corruption or a failed
655
+ * visitor. Free state.zchild, which we just initialized, and return
656
+ * true to stop iteration for our parent context. */
657
+ zval_ptr_dtor (& state .zchild );
665
658
}
666
659
}
667
660
@@ -691,7 +684,7 @@ bool php_phongo_bson_visit_array(const bson_iter_t *iter ARG_UNUSED, const char
691
684
array_init (state .zchild );
692
685
#endif
693
686
694
- if (!bson_iter_visit_all (& child , & php_bson_visitors , & state )) {
687
+ if (!bson_iter_visit_all (& child , & php_bson_visitors , & state ) && ! child . err_off ) {
695
688
696
689
switch (state .map .array_type ) {
697
690
case PHONGO_TYPEMAP_CLASS : {
@@ -737,6 +730,11 @@ bool php_phongo_bson_visit_array(const bson_iter_t *iter ARG_UNUSED, const char
737
730
#endif
738
731
break ;
739
732
}
733
+ } else {
734
+ /* Iteration stopped prematurely due to corruption or a failed
735
+ * visitor. Free state.zchild, which we just initialized, and return
736
+ * true to stop iteration for our parent context. */
737
+ zval_ptr_dtor (& state .zchild );
740
738
}
741
739
742
740
}
@@ -1385,7 +1383,15 @@ PHONGO_API int phongo_bson_to_zval_ex(const unsigned char *data, int data_len, p
1385
1383
#else
1386
1384
array_init (state -> zchild );
1387
1385
#endif
1388
- bson_iter_visit_all (& iter , & php_bson_visitors , state );
1386
+
1387
+ if (bson_iter_visit_all (& iter , & php_bson_visitors , state ) || iter .err_off ) {
1388
+ /* Iteration stopped prematurely due to corruption or a failed visitor.
1389
+ * While we free the reader, state->zchild should be left as-is, since
1390
+ * the calling code may want to zval_ptr_dtor() it. */
1391
+ phongo_throw_exception (PHONGO_ERROR_UNEXPECTED_VALUE TSRMLS_CC , "Could not convert BSON document to a PHP variable" );
1392
+ bson_reader_destroy (reader );
1393
+ return 0 ;
1394
+ }
1389
1395
1390
1396
/* If php_phongo_bson_visit_binary() finds an ODM class, it should supersede
1391
1397
* a default type map and named root class. */
0 commit comments