|
21 | 21 | #include "ext/standard/basic_functions.h" |
22 | 22 | #include "ext/standard/file.h" |
23 | 23 | #include "ext/standard/user_filters_arginfo.h" |
| 24 | +#include "zend_exceptions.h" |
24 | 25 |
|
25 | 26 | #define PHP_STREAM_BRIGADE_RES_NAME "userfilter.bucket brigade" |
26 | 27 | #define PHP_STREAM_BUCKET_RES_NAME "userfilter.bucket" |
@@ -148,12 +149,29 @@ php_stream_filter_status_t userfilter_filter( |
148 | 149 | stream->flags |= PHP_STREAM_FLAG_NO_FCLOSE; |
149 | 150 |
|
150 | 151 | /* Give the userfilter class a hook back to the stream */ |
151 | | - zval *stream_prop = zend_hash_str_find(Z_OBJPROP_P(obj), "stream", sizeof("stream")-1); |
152 | | - if (stream_prop) { |
| 152 | + zend_class_entry *old_scope = EG(fake_scope); |
| 153 | + EG(fake_scope) = Z_OBJCE_P(obj); |
| 154 | + |
| 155 | + zend_string *stream_name = ZSTR_INIT_LITERAL("stream", 0); |
| 156 | + if (Z_OBJ_HT_P(obj)->has_property(Z_OBJ_P(obj), stream_name, ZEND_PROPERTY_EXISTS, NULL)) { |
153 | 157 | zval stream_zval; |
154 | 158 | php_stream_to_zval(stream, &stream_zval); |
155 | | - zend_update_property(Z_OBJCE_P(obj), Z_OBJ_P(obj), "stream", sizeof("stream")-1, &stream_zval); |
| 159 | + zend_update_property_ex(Z_OBJCE_P(obj), Z_OBJ_P(obj), stream_name, &stream_zval); |
| 160 | + /* If property update threw an exception, skip filter execution */ |
| 161 | + if (EG(exception)) { |
| 162 | + if (buckets_in->head) { |
| 163 | + php_error_docref(NULL, E_WARNING, "Unprocessed filter buckets remaining on input brigade"); |
| 164 | + } |
| 165 | + zend_string_release(stream_name); |
| 166 | + EG(fake_scope) = old_scope; |
| 167 | + stream->flags &= ~PHP_STREAM_FLAG_NO_FCLOSE; |
| 168 | + stream->flags |= orig_no_fclose; |
| 169 | + return PSFS_ERR_FATAL; |
| 170 | + } |
156 | 171 | } |
| 172 | + zend_string_release(stream_name); |
| 173 | + |
| 174 | + EG(fake_scope) = old_scope; |
157 | 175 |
|
158 | 176 | ZVAL_STRINGL(&func_name, "filter", sizeof("filter")-1); |
159 | 177 |
|
@@ -196,8 +214,19 @@ php_stream_filter_status_t userfilter_filter( |
196 | 214 | /* filter resources are cleaned up by the stream destructor, |
197 | 215 | * keeping a reference to the stream resource here would prevent it |
198 | 216 | * from being destroyed properly */ |
| 217 | + zend_property_info *prop_info = zend_hash_str_find_ptr(&Z_OBJCE_P(obj)->properties_info, "stream", sizeof("stream")-1); |
| 218 | + zval *stream_prop = zend_hash_str_find(Z_OBJPROP_P(obj), "stream", sizeof("stream")-1); |
| 219 | + |
199 | 220 | if (stream_prop) { |
200 | | - zend_update_property_null(Z_OBJCE_P(obj), Z_OBJ_P(obj), "stream", sizeof("stream")-1); |
| 221 | + if (prop_info) { |
| 222 | + /* Declared property: set to UNDEF to make it uninitialized */ |
| 223 | + zval_ptr_dtor(stream_prop); |
| 224 | + ZVAL_UNDEF(stream_prop); |
| 225 | + } else { |
| 226 | + /* Dynamic property: set to null */ |
| 227 | + zval_ptr_dtor(stream_prop); |
| 228 | + ZVAL_NULL(stream_prop); |
| 229 | + } |
201 | 230 | } |
202 | 231 |
|
203 | 232 | zval_ptr_dtor(&args[3]); |
|
0 commit comments