@@ -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,11 @@ 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 );
665658 }
666659 }
667660
@@ -691,7 +684,7 @@ bool php_phongo_bson_visit_array(const bson_iter_t *iter ARG_UNUSED, const char
691684 array_init (state .zchild );
692685#endif
693686
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 ) {
695688
696689 switch (state .map .array_type ) {
697690 case PHONGO_TYPEMAP_CLASS : {
@@ -737,6 +730,11 @@ bool php_phongo_bson_visit_array(const bson_iter_t *iter ARG_UNUSED, const char
737730#endif
738731 break ;
739732 }
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 );
740738 }
741739
742740 }
@@ -1385,7 +1383,15 @@ PHONGO_API int phongo_bson_to_zval_ex(const unsigned char *data, int data_len, p
13851383#else
13861384 array_init (state -> zchild );
13871385#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+ }
13891395
13901396 /* If php_phongo_bson_visit_binary() finds an ODM class, it should supersede
13911397 * a default type map and named root class. */
0 commit comments