@@ -179,21 +179,9 @@ bool php_phongo_bson_visit_after(const bson_iter_t *iter ARG_UNUSED, const char
179179}
180180/* }}} */
181181#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 ) /* {{{ */
183183{
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-
190184 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
197185}
198186/* }}} */
199187bool 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
612600 array_init (state .zchild );
613601#endif
614602
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 ) {
616604 /* If php_phongo_bson_visit_binary() finds an ODM class, it should
617605 * supersede a default type map and named document class. */
618606 if (state .odm && state .map .document_type == PHONGO_TYPEMAP_NONE ) {
@@ -662,6 +650,12 @@ bool php_phongo_bson_visit_document(const bson_iter_t *iter ARG_UNUSED, const ch
662650 Z_SET_REFCOUNT_P (state .zchild , 1 );
663651#endif
664652 }
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 );
658+ return true;
665659 }
666660 }
667661
@@ -691,7 +685,7 @@ bool php_phongo_bson_visit_array(const bson_iter_t *iter ARG_UNUSED, const char
691685 array_init (state .zchild );
692686#endif
693687
694- if (!bson_iter_visit_all (& child , & php_bson_visitors , & state )) {
688+ if (!bson_iter_visit_all (& child , & php_bson_visitors , & state ) && ! child . err_off ) {
695689
696690 switch (state .map .array_type ) {
697691 case PHONGO_TYPEMAP_CLASS : {
@@ -737,6 +731,12 @@ bool php_phongo_bson_visit_array(const bson_iter_t *iter ARG_UNUSED, const char
737731#endif
738732 break ;
739733 }
734+ } else {
735+ /* Iteration stopped prematurely due to corruption or a failed
736+ * visitor. Free state.zchild, which we just initialized, and return
737+ * true to stop iteration for our parent context. */
738+ zval_ptr_dtor (& state .zchild );
739+ return true;
740740 }
741741
742742 }
@@ -1385,7 +1385,15 @@ PHONGO_API int phongo_bson_to_zval_ex(const unsigned char *data, int data_len, p
13851385#else
13861386 array_init (state -> zchild );
13871387#endif
1388- bson_iter_visit_all (& iter , & php_bson_visitors , state );
1388+
1389+ if (bson_iter_visit_all (& iter , & php_bson_visitors , state ) || iter .err_off ) {
1390+ /* Iteration stopped prematurely due to corruption or a failed visitor.
1391+ * While we free the reader, state->zchild should be left as-is, since
1392+ * the calling code may want to zval_ptr_dtor() it. */
1393+ phongo_throw_exception (PHONGO_ERROR_UNEXPECTED_VALUE TSRMLS_CC , "Could not convert BSON document to a PHP variable" );
1394+ bson_reader_destroy (reader );
1395+ return 0 ;
1396+ }
13891397
13901398 /* If php_phongo_bson_visit_binary() finds an ODM class, it should supersede
13911399 * a default type map and named root class. */
0 commit comments