]> granicus.if.org Git - php/commitdiff
Fix SPL objects initialization checks
authorStanislav Malyshev <stas@php.net>
Sun, 27 Jul 2014 01:00:16 +0000 (18:00 -0700)
committerStanislav Malyshev <stas@php.net>
Sun, 27 Jul 2014 01:59:16 +0000 (18:59 -0700)
ext/spl/spl_directory.c
ext/spl/spl_iterators.c
ext/spl/tests/bug54281.phpt

index 4159d1ae3442cb64bd7ff45eca3c20479f348ca5..495314abeb4442338c5206605856d46255416818 100644 (file)
@@ -1617,7 +1617,7 @@ SPL_METHOD(GlobIterator, count)
                return;
        }
 
-       if (php_stream_is(intern->u.dir.dirp ,&php_glob_stream_ops)) {
+       if (intern->u.dir.dirp && php_stream_is(intern->u.dir.dirp ,&php_glob_stream_ops)) {
                RETURN_LONG(php_glob_stream_get_count(intern->u.dir.dirp, NULL));
        } else {
                /* should not happen */
@@ -2098,7 +2098,7 @@ static int spl_filesystem_file_call(spl_filesystem_object *intern, zend_function
        zend_fcall_info fci;
        zend_fcall_info_cache fcic;
        zval z_fname;
-       zval * zresource_ptr = &intern->u.file.zresource, *retval;
+       zval * zresource_ptr = &intern->u.file.zresource, *retval = NULL;
        int result;
        int num_args = pass_num_args + (arg2 ? 2 : 1);
 
@@ -2132,7 +2132,7 @@ static int spl_filesystem_file_call(spl_filesystem_object *intern, zend_function
 
        result = zend_call_function(&fci, &fcic TSRMLS_CC);
        
-       if (result == FAILURE) {
+       if (result == FAILURE || retval == NULL) {
                RETVAL_FALSE;
        } else {
                ZVAL_ZVAL(return_value, retval, 1, 1);
@@ -2265,6 +2265,10 @@ static int spl_filesystem_file_read_line(zval * this_ptr, spl_filesystem_object
 
 static void spl_filesystem_file_rewind(zval * this_ptr, spl_filesystem_object *intern TSRMLS_DC) /* {{{ */
 {
+       if(!intern->u.file.stream) {
+               zend_throw_exception_ex(spl_ce_RuntimeException, 0 TSRMLS_CC, "Object not initialized");
+               return;
+       }
        if (-1 == php_stream_rewind(intern->u.file.stream)) {
                zend_throw_exception_ex(spl_ce_RuntimeException, 0 TSRMLS_CC, "Cannot rewind file %s", intern->file_name);
        } else {
@@ -2397,6 +2401,11 @@ SPL_METHOD(SplFileObject, eof)
                return;
        }
 
+       if(!intern->u.file.stream) {
+               zend_throw_exception_ex(spl_ce_RuntimeException, 0 TSRMLS_CC, "Object not initialized");
+               return;
+       }
+
        RETURN_BOOL(php_stream_eof(intern->u.file.stream));
 } /* }}} */
 
@@ -2413,6 +2422,9 @@ SPL_METHOD(SplFileObject, valid)
        if (SPL_HAS_FLAG(intern->flags, SPL_FILE_OBJECT_READ_AHEAD)) {
                RETURN_BOOL(intern->u.file.current_line || intern->u.file.current_zval);
        } else {
+               if(!intern->u.file.stream) {
+                       RETURN_FALSE;
+               }
                RETVAL_BOOL(!php_stream_eof(intern->u.file.stream));
        }
 } /* }}} */
@@ -2427,6 +2439,11 @@ SPL_METHOD(SplFileObject, fgets)
                return;
        }
 
+       if(!intern->u.file.stream) {
+               zend_throw_exception_ex(spl_ce_RuntimeException, 0 TSRMLS_CC, "Object not initialized");
+               return;
+       }
+
        if (spl_filesystem_file_read(intern, 0 TSRMLS_CC) == FAILURE) {
                RETURN_FALSE;
        }
@@ -2443,6 +2460,11 @@ SPL_METHOD(SplFileObject, current)
                return;
        }
 
+       if(!intern->u.file.stream) {
+               zend_throw_exception_ex(spl_ce_RuntimeException, 0 TSRMLS_CC, "Object not initialized");
+               return;
+       }
+
        if (!intern->u.file.current_line && !intern->u.file.current_zval) {
                spl_filesystem_file_read_line(getThis(), intern, 1 TSRMLS_CC);
        }
@@ -2585,6 +2607,12 @@ SPL_METHOD(SplFileObject, fgetcsv)
        int d_len = 0, e_len = 0, esc_len = 0;
        
        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sss", &delim, &d_len, &enclo, &e_len, &esc, &esc_len) == SUCCESS) {
+
+               if(!intern->u.file.stream) {
+                       zend_throw_exception_ex(spl_ce_RuntimeException, 0 TSRMLS_CC, "Object not initialized");
+                       return;
+               }
+
                switch(ZEND_NUM_ARGS())
                {
                case 3:
@@ -2726,6 +2754,11 @@ SPL_METHOD(SplFileObject, fflush)
 {
        spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
 
+       if(!intern->u.file.stream) {
+               zend_throw_exception_ex(spl_ce_RuntimeException, 0 TSRMLS_CC, "Object not initialized");
+               return;
+       }
+
        RETURN_BOOL(!php_stream_flush(intern->u.file.stream));
 } /* }}} */
 
@@ -2734,7 +2767,14 @@ SPL_METHOD(SplFileObject, fflush)
 SPL_METHOD(SplFileObject, ftell)
 {
        spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);      
-       long ret = php_stream_tell(intern->u.file.stream);
+       long ret;
+
+       if(!intern->u.file.stream) {
+               zend_throw_exception_ex(spl_ce_RuntimeException, 0 TSRMLS_CC, "Object not initialized");
+               return;
+       }
+
+       ret = php_stream_tell(intern->u.file.stream);
 
        if (ret == -1) {
                RETURN_FALSE;
@@ -2754,6 +2794,11 @@ SPL_METHOD(SplFileObject, fseek)
                return;
        }
 
+       if(!intern->u.file.stream) {
+               zend_throw_exception_ex(spl_ce_RuntimeException, 0 TSRMLS_CC, "Object not initialized");
+               return;
+       }
+
        spl_filesystem_file_free_line(intern TSRMLS_CC);
        RETURN_LONG(php_stream_seek(intern->u.file.stream, pos, whence));
 } /* }}} */
@@ -2766,6 +2811,11 @@ SPL_METHOD(SplFileObject, fgetc)
        char buf[2];
        int result;
 
+       if(!intern->u.file.stream) {
+               zend_throw_exception_ex(spl_ce_RuntimeException, 0 TSRMLS_CC, "Object not initialized");
+               return;
+       }
+
        spl_filesystem_file_free_line(intern TSRMLS_CC);
 
        result = php_stream_getc(intern->u.file.stream);
@@ -2791,6 +2841,11 @@ SPL_METHOD(SplFileObject, fgetss)
        zval *arg2 = NULL;
        MAKE_STD_ZVAL(arg2);
 
+       if(!intern->u.file.stream) {
+               zend_throw_exception_ex(spl_ce_RuntimeException, 0 TSRMLS_CC, "Object not initialized");
+               return;
+       }
+
        if (intern->u.file.max_line_len > 0) {
                ZVAL_LONG(arg2, intern->u.file.max_line_len);
        } else {
@@ -2811,6 +2866,11 @@ SPL_METHOD(SplFileObject, fpassthru)
 {
        spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
 
+       if(!intern->u.file.stream) {
+               zend_throw_exception_ex(spl_ce_RuntimeException, 0 TSRMLS_CC, "Object not initialized");
+               return;
+       }
+
        RETURN_LONG(php_stream_passthru(intern->u.file.stream));
 } /* }}} */
 
@@ -2820,6 +2880,11 @@ SPL_METHOD(SplFileObject, fscanf)
 {
        spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
 
+       if(!intern->u.file.stream) {
+               zend_throw_exception_ex(spl_ce_RuntimeException, 0 TSRMLS_CC, "Object not initialized");
+               return;
+       }
+
        spl_filesystem_file_free_line(intern TSRMLS_CC);
        intern->u.file.current_line_num++;
 
@@ -2840,6 +2905,11 @@ SPL_METHOD(SplFileObject, fwrite)
                return;
        }
 
+       if(!intern->u.file.stream) {
+               zend_throw_exception_ex(spl_ce_RuntimeException, 0 TSRMLS_CC, "Object not initialized");
+               return;
+       }
+
        if (ZEND_NUM_ARGS() > 1) {
                str_len = MAX(0, MIN(length, str_len));
        }
@@ -2859,6 +2929,11 @@ SPL_METHOD(SplFileObject, fread)
                return;
        }
 
+       if(!intern->u.file.stream) {
+               zend_throw_exception_ex(spl_ce_RuntimeException, 0 TSRMLS_CC, "Object not initialized");
+               return;
+       }
+
        if (length <= 0) {
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Length parameter must be greater than 0");
                RETURN_FALSE;
@@ -2888,6 +2963,11 @@ SPL_METHOD(SplFileObject, ftruncate)
                return;
        }
 
+       if(!intern->u.file.stream) {
+               zend_throw_exception_ex(spl_ce_RuntimeException, 0 TSRMLS_CC, "Object not initialized");
+               return;
+       }
+
        if (!php_stream_truncate_supported(intern->u.file.stream)) {
                zend_throw_exception_ex(spl_ce_LogicException, 0 TSRMLS_CC, "Can't truncate file %s", intern->file_name);
                RETURN_FALSE;
@@ -2902,15 +2982,20 @@ SPL_METHOD(SplFileObject, seek)
 {
        spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
        long line_pos;
-       
+
        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &line_pos) == FAILURE) {
                return;
        }
+       if(!intern->u.file.stream) {
+               zend_throw_exception_ex(spl_ce_RuntimeException, 0 TSRMLS_CC, "Object not initialized");
+               return;
+       }
+
        if (line_pos < 0) {
                zend_throw_exception_ex(spl_ce_LogicException, 0 TSRMLS_CC, "Can't seek file %s to negative line %ld", intern->file_name, line_pos);
                RETURN_FALSE;           
        }
-       
+
        spl_filesystem_file_rewind(getThis(), intern TSRMLS_CC);
        
        while(intern->u.file.current_line_num < line_pos) {
index cade34efd45b671da5166ae6772e2eb5d7270f8e..3ca0bda3bdae4aa86690c9b6a5c1679ba23e5ab2 100644 (file)
@@ -139,6 +139,19 @@ static zend_object_handlers spl_handlers_dual_it;
                (var) = it; \
        } while (0)
 
+#define SPL_FETCH_SUB_ELEMENT(var, object, element) \
+       do { \
+               if(!(object)->iterators) { \
+                       zend_throw_exception_ex(spl_ce_LogicException, 0 TSRMLS_CC, \
+                               "The object is in an invalid state as the parent constructor was not called"); \
+                       return; \
+               } \
+               (var) = (object)->iterators[(object)->level].element; \
+       } while (0)
+
+#define SPL_FETCH_SUB_ITERATOR(var, object) SPL_FETCH_SUB_ELEMENT(var, object, iterator)
+
+
 static void spl_recursive_it_dtor(zend_object_iterator *_iter TSRMLS_DC)
 {
        spl_recursive_it_iterator *iter   = (spl_recursive_it_iterator*)_iter;
@@ -161,7 +174,10 @@ static int spl_recursive_it_valid_ex(spl_recursive_it_object *object, zval *zthi
 {
        zend_object_iterator      *sub_iter;
        int                       level = object->level;
-       
+
+       if(!object->iterators) {
+               return FAILURE;
+       }
        while (level >=0) {
                sub_iter = object->iterators[level].iterator;
                if (sub_iter->funcs->valid(sub_iter TSRMLS_CC) == SUCCESS) {
@@ -212,6 +228,8 @@ static void spl_recursive_it_move_forward_ex(spl_recursive_it_object *object, zv
        zend_object_iterator      *sub_iter;
        int                       has_children;
 
+       SPL_FETCH_SUB_ITERATOR(iterator, object);
+
        while (!EG(exception)) {
 next_step:
                iterator = object->iterators[object->level].iterator;
@@ -375,9 +393,7 @@ static void spl_recursive_it_rewind_ex(spl_recursive_it_object *object, zval *zt
 {
        zend_object_iterator      *sub_iter;
        
-       if (!object->iterators) {
-               php_error_docref(NULL TSRMLS_CC, E_ERROR, "The %s instance wasn't initialized properly", Z_OBJCE_P(zthis)->name);
-       }
+       SPL_FETCH_SUB_ITERATOR(sub_iter, object);
 
        while (object->level) {
                sub_iter = object->iterators[object->level].iterator;
@@ -597,7 +613,7 @@ SPL_METHOD(RecursiveIteratorIterator, rewind)
 SPL_METHOD(RecursiveIteratorIterator, valid)
 {
        spl_recursive_it_object   *object = (spl_recursive_it_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
-       
+
        if (zend_parse_parameters_none() == FAILURE) {
                return;
        }
@@ -610,12 +626,14 @@ SPL_METHOD(RecursiveIteratorIterator, valid)
 SPL_METHOD(RecursiveIteratorIterator, key)
 {
        spl_recursive_it_object   *object = (spl_recursive_it_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
-       zend_object_iterator      *iterator = object->iterators[object->level].iterator;
-       
+       zend_object_iterator      *iterator;
+
        if (zend_parse_parameters_none() == FAILURE) {
                return;
        }
 
+       SPL_FETCH_SUB_ITERATOR(iterator, object);
+
        if (iterator->funcs->get_current_key) {
                iterator->funcs->get_current_key(iterator, return_value TSRMLS_CC);
        } else {
@@ -628,13 +646,15 @@ SPL_METHOD(RecursiveIteratorIterator, key)
 SPL_METHOD(RecursiveIteratorIterator, current)
 {
        spl_recursive_it_object   *object = (spl_recursive_it_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
-       zend_object_iterator      *iterator = object->iterators[object->level].iterator;
+       zend_object_iterator      *iterator;
        zval                      **data;
        
        if (zend_parse_parameters_none() == FAILURE) {
                return;
        }
 
+       SPL_FETCH_SUB_ITERATOR(iterator, object);
+
        iterator->funcs->get_current_data(iterator, &data TSRMLS_CC);
        if (data && *data) {
                RETURN_ZVAL(*data, 1, 0);
@@ -673,6 +693,7 @@ SPL_METHOD(RecursiveIteratorIterator, getSubIterator)
 {
        spl_recursive_it_object   *object = (spl_recursive_it_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
        long  level = object->level;
+       zval      *zobject;
        
        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &level) == FAILURE) {
                return;
@@ -680,6 +701,13 @@ SPL_METHOD(RecursiveIteratorIterator, getSubIterator)
        if (level < 0 || level > object->level) {
                RETURN_NULL();
        }
+
+       if(!object->iterators) {
+               zend_throw_exception_ex(spl_ce_LogicException, 0 TSRMLS_CC,
+                       "The object is in an invalid state as the parent constructor was not called");
+               return;
+       }
+
        RETURN_ZVAL(object->iterators[level].zobject, 1, 0);
 } /* }}} */
 
@@ -688,13 +716,15 @@ SPL_METHOD(RecursiveIteratorIterator, getSubIterator)
 SPL_METHOD(RecursiveIteratorIterator, getInnerIterator)
 {
        spl_recursive_it_object   *object = (spl_recursive_it_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
-       long  level = object->level;
+       zval      *zobject;
        
        if (zend_parse_parameters_none() == FAILURE) {
                return;
        }
-       
-       RETURN_ZVAL(object->iterators[level].zobject, 1, 0);
+
+       SPL_FETCH_SUB_ELEMENT(zobject, object, zobject);
+
+       RETURN_ZVAL(zobject, 1, 0);
 } /* }}} */
 
 /* {{{ proto RecursiveIterator RecursiveIteratorIterator::beginIteration()
@@ -722,13 +752,19 @@ SPL_METHOD(RecursiveIteratorIterator, endIteration)
 SPL_METHOD(RecursiveIteratorIterator, callHasChildren)
 {
        spl_recursive_it_object   *object = (spl_recursive_it_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
-       zend_class_entry *ce = object->iterators[object->level].ce;
+       zend_class_entry *ce;
        zval *retval, *zobject;
        
        if (zend_parse_parameters_none() == FAILURE) {
                return;
        }
 
+       if (!object->iterators) {
+               RETURN_NULL();
+       }
+
+       SPL_FETCH_SUB_ELEMENT(ce, object, ce);
+
        zobject = object->iterators[object->level].zobject;
        if (!zobject) {
                RETURN_FALSE;
@@ -747,13 +783,15 @@ SPL_METHOD(RecursiveIteratorIterator, callHasChildren)
 SPL_METHOD(RecursiveIteratorIterator, callGetChildren)
 {
        spl_recursive_it_object   *object = (spl_recursive_it_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
-       zend_class_entry *ce = object->iterators[object->level].ce;
+       zend_class_entry *ce;
        zval *retval, *zobject;
        
        if (zend_parse_parameters_none() == FAILURE) {
                return;
        }
 
+       SPL_FETCH_SUB_ELEMENT(ce, object, ce);
+
        zobject = object->iterators[object->level].zobject;
        if (!zobject) {
                return;
@@ -1072,6 +1110,13 @@ SPL_METHOD(RecursiveTreeIterator, getPrefix)
        if (zend_parse_parameters_none() == FAILURE) {
                return;
        }
+
+       if(!object->iterators) {
+               zend_throw_exception_ex(spl_ce_LogicException, 0 TSRMLS_CC,
+                       "The object is in an invalid state as the parent constructor was not called");
+               return;
+       } 
+    
        spl_recursive_tree_iterator_get_prefix(object, return_value TSRMLS_CC);
 } /* }}} */
 
@@ -1100,6 +1145,12 @@ SPL_METHOD(RecursiveTreeIterator, getEntry)
        if (zend_parse_parameters_none() == FAILURE) {
                return;
        }
+
+       if(!object->iterators) {
+               zend_throw_exception_ex(spl_ce_LogicException, 0 TSRMLS_CC,
+                       "The object is in an invalid state as the parent constructor was not called");
+               return;
+       }
        
        spl_recursive_tree_iterator_get_entry(object, return_value TSRMLS_CC);
 } /* }}} */
@@ -1113,6 +1164,12 @@ SPL_METHOD(RecursiveTreeIterator, getPostfix)
        if (zend_parse_parameters_none() == FAILURE) {
                return;
        }
+
+       if(!object->iterators) {
+               zend_throw_exception_ex(spl_ce_LogicException, 0 TSRMLS_CC,
+                       "The object is in an invalid state as the parent constructor was not called");
+               return;
+       }
        
        spl_recursive_tree_iterator_get_postfix(object, return_value TSRMLS_CC);
 } /* }}} */
@@ -1130,10 +1187,17 @@ SPL_METHOD(RecursiveTreeIterator, current)
                return;
        }
 
+       if(!object->iterators) {
+               zend_throw_exception_ex(spl_ce_LogicException, 0 TSRMLS_CC,
+                       "The object is in an invalid state as the parent constructor was not called");
+               return;
+       } 
+
        if (object->flags & RTIT_BYPASS_CURRENT) {
-               zend_object_iterator      *iterator = object->iterators[object->level].iterator;
+               zend_object_iterator      *iterator;
                zval                      **data;
 
+        SPL_FETCH_SUB_ITERATOR(iterator, object);
                iterator->funcs->get_current_data(iterator, &data TSRMLS_CC);
                if (data && *data) {
                        RETURN_ZVAL(*data, 1, 0);
@@ -1177,7 +1241,7 @@ SPL_METHOD(RecursiveTreeIterator, current)
 SPL_METHOD(RecursiveTreeIterator, key)
 {
        spl_recursive_it_object   *object = (spl_recursive_it_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
-       zend_object_iterator      *iterator = object->iterators[object->level].iterator;
+       zend_object_iterator      *iterator;
        zval                       prefix, key, postfix, key_copy;
        char                      *str, *ptr;
        size_t                     str_len;
@@ -1186,6 +1250,8 @@ SPL_METHOD(RecursiveTreeIterator, key)
                return;
        }
 
+       SPL_FETCH_SUB_ITERATOR(iterator, object);
+
        if (iterator->funcs->get_current_key) {
                iterator->funcs->get_current_key(iterator, &key TSRMLS_CC);
        } else {
@@ -1899,7 +1965,7 @@ SPL_METHOD(RecursiveCallbackFilterIterator, getChildren)
                return;
        }
 
-       intern = (spl_dual_it_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
+       SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
 
        zend_call_method_with_0_params(&intern->inner.zobject, intern->inner.ce, NULL, "getchildren", &retval);
        if (!EG(exception) && retval) {
index d42d9e585d365abb98eda510a96db0078562c2b0..71792eaa20df80727995a436c95021c1b38d66b2 100644 (file)
@@ -12,4 +12,8 @@ foreach($it as $k=>$v) { }
 
 ?>
 --EXPECTF--
-Fatal error: RecursiveIteratorIterator::rewind(): The RecursiveArrayIteratorIterator instance wasn't initialized properly in %s on line %d
+Fatal error: Uncaught exception 'LogicException' with message 'The object is in an invalid state as the parent constructor was not called' in %s:%d
+Stack trace:
+#0 %s/bug54281.php(8): RecursiveIteratorIterator->rewind()
+#1 {main}
+  thrown in %s/bug54281.php on line 8