diff options
author | Emiel Bruijntjes <emiel.bruijntjes@copernica.com> | 2015-01-11 13:00:02 +0100 |
---|---|---|
committer | Emiel Bruijntjes <emiel.bruijntjes@copernica.com> | 2015-01-11 13:00:02 +0100 |
commit | 1c663ea116121469e37ad2cb9480387c16c0236b (patch) | |
tree | 06bf80d81f47d0c81b9cbdbccf7da9db61490022 | |
parent | 1efade1a7667e4e1a34265fb3cf310faf8c80bb6 (diff) |
fixed memory leak when executing php code using the Opcodes class, fixed possible double-free when path passed to File class was absolute, added extra constructors to the File class
-rw-r--r-- | include/file.h | 12 | ||||
-rw-r--r-- | include/value.h | 2 | ||||
-rw-r--r-- | zend/file.cpp | 22 | ||||
-rw-r--r-- | zend/opcodes.cpp | 9 |
4 files changed, 34 insertions, 11 deletions
diff --git a/include/file.h b/include/file.h index 093431e..6e24516 100644 --- a/include/file.h +++ b/include/file.h @@ -38,6 +38,18 @@ public: File(const char *name) : File(name, ::strlen(name)) {} /** + * Alternative constructor with a string object + * @param name the filename + */ + File(const std::string &name) : File(name.c_str(), name.size()) {} + + /** + * Alternative constructor with a Value object + * @param name the filename + */ + File(const Value &value) : File(value.stringValue()) {} + + /** * Destructor */ virtual ~File(); diff --git a/include/value.h b/include/value.h index 9447fc8..363779d 100644 --- a/include/value.h +++ b/include/value.h @@ -405,7 +405,7 @@ public: char *reserve(size_t size); /** - * Get access to the raw buffer for read operationrs. + * Get access to the raw buffer for read operations. * @return const char * */ const char *rawValue() const; diff --git a/zend/file.cpp b/zend/file.cpp index 3ba53c9..98c1441 100644 --- a/zend/file.cpp +++ b/zend/file.cpp @@ -33,6 +33,13 @@ File::File(const char *name, size_t size) // resolve the path _path = zend_resolve_path(name, size TSRMLS_CC); + + // the resolve-path function sometimes returns the original pointer, we + // do not want that because we may have to store the pathname in this object + if (_path != name) return; + + // make a full copy of the pathname + _path = estrndup(name, size); } /** @@ -78,7 +85,10 @@ Value File::execute() _opcodes = new Opcodes(zend_compile_file(&fileHandle, ZEND_INCLUDE TSRMLS_CC)); // close the file handle - zend_file_handle_dtor(&fileHandle TSRMLS_CC); + zend_destroy_file_handle(&fileHandle TSRMLS_CC); + + // add the entry to the list of included files + zend_hash_add_empty_element(&EG(included_files), _path, ::strlen(_path) + 1); // execute the opcodes return _opcodes->execute(); @@ -91,18 +101,12 @@ Value File::execute() Value File::once() { // skip if the opcodes are already known (then we know for sure that the - // file was already executed) - if (_opcodes) return nullptr; - - // also leap out if the filename was not even valid - if (!_path) return nullptr; + // file was already executed), also leap out if the filename was not even valid + if (_opcodes || !_path) return nullptr; // check if this file was already included if (zend_hash_exists(&EG(included_files), _path, ::strlen(_path) + 1)) return nullptr; - // add the entry to the list of included files - if (zend_hash_add_empty_element(&EG(included_files), _path, ::strlen(_path) + 1) == FAILURE) return nullptr; - // execute the file return execute(); } diff --git a/zend/opcodes.cpp b/zend/opcodes.cpp index 0603d9b..61d8a75 100644 --- a/zend/opcodes.cpp +++ b/zend/opcodes.cpp @@ -136,8 +136,15 @@ Value Opcodes::execute() const // we're ready if there is no return value if (!retval_ptr) return nullptr; + // wrap the return value + Value result(retval_ptr); + + // destruct the zval (this function will decrement the reference counter, + // and only destruct if there are no other references left) + zval_ptr_dtor(&retval_ptr); + // copy the pointer into a value object, and return that - return retval_ptr; + return result; } /** |