diff --git a/.github/actions/freebsd/action.yml b/.github/actions/freebsd/action.yml index 415790bab5a71..d375a51a6d173 100644 --- a/.github/actions/freebsd/action.yml +++ b/.github/actions/freebsd/action.yml @@ -27,7 +27,6 @@ runs: bzip2 \ t1lib \ gmp \ - tidyp \ libsodium \ libzip \ libxml2 \ diff --git a/NEWS b/NEWS index bef0ac90460a0..a3d278ac2e3b3 100644 --- a/NEWS +++ b/NEWS @@ -88,6 +88,7 @@ PHP NEWS (BogdanUngureanu) . Added Locale::isRightToLeft to check if a locale is written right to left. (David Carlier) + . Added null bytes presence in locale inputs for Locale class. (David Carlier) - MySQLi: . Fixed bugs GH-17900 and GH-8084 (calling mysqli::__construct twice). diff --git a/UPGRADING b/UPGRADING index 1b2779c8c1e7c..68f7d20a7f32f 100644 --- a/UPGRADING +++ b/UPGRADING @@ -212,6 +212,8 @@ PHP 8.5 UPGRADE NOTES . grapheme_extract() properly assigns $next value when skipping over invalid starting bytes. Previously there were cases where it would point to the start of the grapheme boundary instead of the end. + . Locale:: methods throw a ValueError when locale inputs contain null + bytes. - PCNTL: . pcntl_exec() now has a formal return type of false. @@ -474,6 +476,7 @@ PHP 8.5 UPGRADE NOTES - Standard: . Improved performance of array functions with callbacks (array_find, array_filter, array_map, usort, ...). + . Improved performance of urlencode() and rawurlencode(). - XMLReader: . Improved property access performance. diff --git a/UPGRADING.INTERNALS b/UPGRADING.INTERNALS index 56c7535158460..7c7f093e50cce 100644 --- a/UPGRADING.INTERNALS +++ b/UPGRADING.INTERNALS @@ -61,6 +61,10 @@ PHP 8.5 INTERNALS UPGRADE NOTES is still valid. This is useful when a GC cycle is collected and the database object can be destroyed prior to destroying the statement. +- ext/standard + . Added php_url_decode_ex() and php_raw_url_decode_ex() that unlike their + non-ex counterparts do not work in-place. + ======================== 4. OpCode changes ======================== diff --git a/Zend/zend_hash.c b/Zend/zend_hash.c index 8bddb0c208835..66cfb250d1fec 100644 --- a/Zend/zend_hash.c +++ b/Zend/zend_hash.c @@ -30,7 +30,6 @@ #if defined(__AVX2__) # include #elif defined( __SSE2__) -# include # include #endif diff --git a/Zend/zend_types.h b/Zend/zend_types.h index 7676a1d42a5f4..4a6d00b9d73ea 100644 --- a/Zend/zend_types.h +++ b/Zend/zend_types.h @@ -28,7 +28,6 @@ #include #ifdef __SSE2__ -# include # include #endif #if defined(__AVX2__) diff --git a/docs/release-process.md b/docs/release-process.md index 4c37d2b087390..5d603a22f078e 100644 --- a/docs/release-process.md +++ b/docs/release-process.md @@ -6,6 +6,7 @@ repository available according to the release schedule. The release schedule for each version is published on the [PHP wiki](https://wiki.php.net): +- [PHP 8.4](https://wiki.php.net/todo/php84) - [PHP 8.3](https://wiki.php.net/todo/php83) - [PHP 8.2](https://wiki.php.net/todo/php82) - [PHP 8.1](https://wiki.php.net/todo/php81) @@ -73,7 +74,7 @@ releases. > When you are unsure about anything, ask a previous RM before proceeding. > Ideally, make sure a previous RM is available to answer questions during > the first few releases of your version. For the steps related to the - > `web-php`, `web-qa`, and `web-php-distributions` repositories, try to have + > `web-php` and `web-php-distributions` repositories, try to have > someone from the webmaster team on hand. 5. Verify the tags to be extra sure everything was tagged properly. @@ -359,11 +360,10 @@ slightly different steps. We'll call attention where the steps differ. ## Announcing a non-stable release (alpha/beta/RC) -1. Switch to your local clone of the `web-qa` repository and update the +1. Switch to your local clone of the `web-php` repository and update the information in the `$QA_RELEASES` array in `include/release-qa.php`. Follow the documentation in the file for editing the QA release information. - See also [Announce 8.1.0RC3][] and [8.1.6RC1][] for examples. Add, commit, and push your changes, when finished. @@ -716,20 +716,7 @@ slightly different steps. We'll call attention where the steps differ. ```shell ./bin/news2html 'https://github.com/php/php-src/raw/php-X.Y.Z/NEWS' 'X.Y.Z' 'ChangeLog-X.php' ``` - -9. Review all the changes in `web-php`, commit, and push them. - - ```shell - git add -p - git add archive/entries/*.xml releases/*.php - git commit --gpg-sign=YOURKEYID -m "Announce PHP X.Y.Z" - git push upstream master - ``` - - See [Announce PHP 8.1.6][] for an example commit. - -10. Switch to your local clone of the `web-qa` repository and update the - information in the `$QA_RELEASES` array in `include/release-qa.php`. +8. Update the information in the `$QA_RELEASES` array in `include/release-qa.php`. The array probably contains information about the RC released two weeks ago in preparation for the current release. Since the current release is now GA, @@ -737,18 +724,20 @@ slightly different steps. We'll call attention where the steps differ. It is sufficient to set the `number` property for the release to `0` to stop displaying the RC build on the QA website. You may also remove the - sha256 hashes for the RC tarballs, but it's not necessary. For an example, - see [PHP 8.1.6 released][]. + sha256 hashes for the RC tarballs, but it's not necessary. - Add, commit, and push your changes, when finished. +9. Review all the changes in `web-php`, commit, and push them. ```shell git add -p - git commit --gpg-sign=YOURKEYID -m "PHP X.Y.Z released" + git add archive/entries/*.xml releases/*.php + git commit --gpg-sign=YOURKEYID -m "Announce PHP X.Y.Z" git push upstream master ``` -11. 🚨 **Before sending announcement emails, check to make sure the websites have + See [Announce PHP 8.1.6][] for an example commit. + +10. 🚨 **Before sending announcement emails, check to make sure the websites have synced.** * Make sure the tarballs are available from, e.g., @@ -760,8 +749,8 @@ slightly different steps. We'll call attention where the steps differ. e.g., https://www.php.net/ChangeLog-8.php * Is there a release page for the new version? e.g., `https://www.php.net/releases/X_Y_Z.php` - * Does the RC for this version still appear on the QA home page? - https://qa.php.net + * Does the RC for this version still appear on the Release Candidate Builds page? + https://www.php.net/release-candidates.php Keep in mind it may take up to an hour for the websites to sync. @@ -986,21 +975,22 @@ volunteers to begin the selection process for the next release managers. ## New release manager checklist -1. Request membership to the +1. Fill out [the form](https://www.php.net/git-php.php) + to get a PHP account (if you don't already have one). + +2. Request membership to the [release managers group](https://github.com/orgs/php/teams/release-managers) on GitHub. -2. Subscribe to the php-announce@lists.php.net mailing list by emailing +3. Subscribe to the php-announce@lists.php.net mailing list by emailing php-announce+subscribe@lists.php.net -3. Email systems@php.net to get setup for access to downloads.php.net, to be +4. Email systems@php.net to get setup for access to downloads.php.net, to be added to the release-managers@php.net distribution list, and to be added to the moderators for php-announce@lists.php.net so you are able to moderate your release announcements. Provide the following information in a single email: - - Preferred Unix username (will also become part of location to download RCs, - such as `https://downloads.php.net/~derick/`). - An SSH public key, preferably a new unique one for PHP systems and projects. - Read [Machine Access](https://wiki.php.net/systems#machine_access) to set @@ -1021,7 +1011,7 @@ volunteers to begin the selection process for the next release managers. > "[Send emails from a different address or alias][]." -4. Create a [GPG key][] for your @php.net address. +5. Create a [GPG key][] for your @php.net address. > 💡 **Tip** \ > If you're new to GPG, follow GitHub's instructions for @@ -1086,11 +1076,10 @@ volunteers to begin the selection process for the next release managers. git push ``` -5. Make sure you have the following repositories cloned locally: +6. Make sure you have the following repositories cloned locally: * https://github.com/php/php-src * https://github.com/php/web-php - * https://github.com/php/web-qa * https://github.com/php/web-php-distributions @@ -1105,13 +1094,10 @@ volunteers to begin the selection process for the next release managers. [Update NEWS for PHP 8.2.0RC6]: https://github.com/php/php-src/commit/4ccc414961a70200d638ca281a35f893226d74e2 [PHP 8.3 is now for PHP 8.3.21-dev]: https://github.com/php/php-src/commit/b57f425cfe20a11003253427424cc0517483550b [GitHub command line tool]: https://cli.github.com -[Announce 8.1.0RC3]: https://github.com/php/web-qa/commit/f264b711fd3827803b79bbb342959eae57ea502b -[8.1.6RC1]: https://github.com/php/web-qa/commit/e6d61ad7a9d8be0b1cd159af29f3b9cbdde33384 [merged upwards as usual]: https://wiki.php.net/vcs/gitworkflow [Update versions for PHP 8.1.7]: https://github.com/php/php-src/commit/d35e577a1bd0b35b9386cea97cddc73fd98eed6d [Update NEWS for PHP 8.1.7]: https://github.com/php/php-src/commit/b241f07f52ca9f87bf52be81817f475e6e727439 [Announce PHP 8.1.6]: https://github.com/php/web-php/commit/9f796a96c65f07e45845ec248933bfb0010b94a9 -[PHP 8.1.6 released]: https://github.com/php/web-qa/commit/bff725f8373cf6fd9d97ba62a8517b19721a4c2e [feature freeze]: https://en.wikipedia.org/wiki/Freeze_(software_engineering) [Prepare for PHP 8.2]: https://github.com/php/php-src/commit/1c33ddb5e5598c5385c4c965992c6e031fd00dd6 [Prepare for PHP 8.2 (bis)]: https://github.com/php/php-src/commit/a93e12f8a6dfc23e334339317c97aa35356db821 diff --git a/ext/dom/tests/DOMElement_toggleAttribute.phpt b/ext/dom/tests/DOMElement_toggleAttribute.phpt index ed29be899dac2..b9e9989e1fe09 100644 --- a/ext/dom/tests/DOMElement_toggleAttribute.phpt +++ b/ext/dom/tests/DOMElement_toggleAttribute.phpt @@ -87,7 +87,7 @@ echo "Checking toggled namespace:\n"; var_dump($dom->documentElement->getAttribute('xmlns:anotheron')); ?> ---EXPECT-- +--EXPECTF-- Invalid Character Error --- Selected attribute tests (HTML) --- bool(false) @@ -95,10 +95,10 @@ bool(false) bool(true) - + bool(true) - + bool(false) diff --git a/ext/dom/tests/gh10234.phpt b/ext/dom/tests/gh10234.phpt index 5edc8fc6c1ff1..11d39cd625a79 100644 --- a/ext/dom/tests/gh10234.phpt +++ b/ext/dom/tests/gh10234.phpt @@ -55,7 +55,7 @@ $document->documentElement->textContent = "quote 'test'"; var_dump($document->documentElement->textContent); var_dump($document->saveHTML()); ?> ---EXPECT-- +--EXPECTF-- -- Attribute tests -- string(38) " " @@ -67,10 +67,10 @@ string(13) "hello & world" string(50) " " string(9) "hi" -string(54) " +string(%d) "hi<\/b>")%r> " string(12) "quote "test"" -string(45) " +string(%d) " " string(12) "quote 'test'" string(45) " diff --git a/ext/fileinfo/fileinfo.c b/ext/fileinfo/fileinfo.c index c0cc8877bf991..143b8ba080fc5 100644 --- a/ext/fileinfo/fileinfo.c +++ b/ext/fileinfo/fileinfo.c @@ -36,17 +36,11 @@ #include "fopen_wrappers.h" /* needed for is_url */ #include "Zend/zend_exceptions.h" -/* {{{ macros and type definitions */ -typedef struct _php_fileinfo { - zend_long options; - struct magic_set *magic; -} php_fileinfo; - static zend_object_handlers finfo_object_handlers; zend_class_entry *finfo_class_entry; typedef struct _finfo_object { - php_fileinfo *ptr; + struct magic_set *magic; zend_object zo; } finfo_object; @@ -56,26 +50,12 @@ static inline finfo_object *php_finfo_fetch_object(zend_object *obj) { #define Z_FINFO_P(zv) php_finfo_fetch_object(Z_OBJ_P((zv))) -#define FILEINFO_FROM_OBJECT(finfo, object) \ -{ \ - finfo_object *obj = Z_FINFO_P(object); \ - finfo = obj->ptr; \ - if (!finfo) { \ - zend_throw_error(NULL, "Invalid finfo object"); \ - RETURN_THROWS(); \ - } \ -} - /* {{{ finfo_objects_free */ static void finfo_objects_free(zend_object *object) { finfo_object *intern = php_finfo_fetch_object(object); - if (intern->ptr) { - magic_close(intern->ptr->magic); - efree(intern->ptr); - } - + magic_close(intern->magic); zend_object_std_dtor(&intern->zo); } /* }}} */ @@ -135,10 +115,10 @@ ZEND_GET_MODULE(fileinfo) /* {{{ PHP_MINFO_FUNCTION */ PHP_MINFO_FUNCTION(fileinfo) { - char magic_ver[5]; + char magic_ver[15]; - (void)snprintf(magic_ver, 4, "%d", magic_version()); - magic_ver[4] = '\0'; + int raw_version = magic_version(); + (void)snprintf(magic_ver, sizeof(magic_ver), "%d.%d", raw_version / 100, raw_version % 100); php_info_print_table_start(); php_info_print_table_row(2, "fileinfo support", "enabled"); @@ -153,7 +133,6 @@ PHP_FUNCTION(finfo_open) zend_long options = MAGIC_NONE; char *file = NULL; size_t file_len = 0; - php_fileinfo *finfo; zval *object = getThis(); char resolved_path[MAXPATHLEN]; zend_error_handling zeh; @@ -163,15 +142,10 @@ PHP_FUNCTION(finfo_open) } if (object) { - finfo_object *finfo_obj = Z_FINFO_P(object); - zend_replace_error_handling(EH_THROW, NULL, &zeh); - if (finfo_obj->ptr) { - magic_close(finfo_obj->ptr->magic); - efree(finfo_obj->ptr); - finfo_obj->ptr = NULL; - } + magic_close(Z_FINFO_P(object)->magic); + Z_FINFO_P(object)->magic = NULL; } if (file_len == 0) { @@ -199,13 +173,9 @@ PHP_FUNCTION(finfo_open) file = resolved_path; } - finfo = emalloc(sizeof(php_fileinfo)); + struct magic_set *magic = magic_open(options); - finfo->options = options; - finfo->magic = magic_open(options); - - if (finfo->magic == NULL) { - efree(finfo); + if (magic == NULL) { php_error_docref(NULL, E_WARNING, "Invalid mode '" ZEND_LONG_FMT "'.", options); if (object) { zend_restore_error_handling(&zeh); @@ -216,10 +186,9 @@ PHP_FUNCTION(finfo_open) RETURN_FALSE; } - if (magic_load(finfo->magic, file) == -1) { + if (magic_load(magic, file) == -1) { php_error_docref(NULL, E_WARNING, "Failed to load magic database at \"%s\"", file); - magic_close(finfo->magic); - efree(finfo); + magic_close(magic); if (object) { zend_restore_error_handling(&zeh); if (!EG(exception)) { @@ -230,14 +199,13 @@ PHP_FUNCTION(finfo_open) } if (object) { - finfo_object *obj; zend_restore_error_handling(&zeh); - obj = Z_FINFO_P(object); - obj->ptr = finfo; + finfo_object *obj = Z_FINFO_P(object); + obj->magic = magic; } else { zend_object *zobj = finfo_objects_new(finfo_class_entry); finfo_object *obj = php_finfo_fetch_object(zobj); - obj->ptr = finfo; + obj->magic = magic; RETURN_OBJ(zobj); } } @@ -260,18 +228,20 @@ PHP_FUNCTION(finfo_close) PHP_FUNCTION(finfo_set_flags) { zend_long options; - php_fileinfo *finfo; zval *self; if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Ol", &self, finfo_class_entry, &options) == FAILURE) { RETURN_THROWS(); } - FILEINFO_FROM_OBJECT(finfo, self); + + if (!Z_FINFO_P(self)->magic) { + zend_throw_error(NULL, "Invalid finfo object"); + RETURN_THROWS(); + } /* We do not check the return value as it can only ever fail if options contains MAGIC_PRESERVE_ATIME * and the system neither has utime(3) nor utimes(2). Something incredibly unlikely. */ - magic_setflags(finfo->magic, options); - finfo->options = options; + magic_setflags(Z_FINFO_P(self)->magic, options); RETURN_TRUE; } @@ -331,13 +301,17 @@ PHP_FUNCTION(finfo_file) zend_string *path = NULL; zend_long options = 0; zval *zcontext = NULL; - php_fileinfo *finfo = NULL; if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "OP|lr!", &self, finfo_class_entry, &path, &options, &zcontext) == FAILURE) { RETURN_THROWS(); } - FILEINFO_FROM_OBJECT(finfo, self); - struct magic_set *magic = finfo->magic; + + if (!Z_FINFO_P(self)->magic) { + zend_throw_error(NULL, "Invalid finfo object"); + RETURN_THROWS(); + } + + struct magic_set *magic = Z_FINFO_P(self)->magic; if (UNEXPECTED(ZSTR_LEN(path) == 0)) { zend_argument_must_not_be_empty_error(2); @@ -349,6 +323,7 @@ PHP_FUNCTION(finfo_file) } /* Set options for the current file/buffer. */ + int old_options = magic_getflags(magic); if (options) { /* We do not check the return value as it can only ever fail if options contains MAGIC_PRESERVE_ATIME * and the system neither has utime(3) nor utimes(2). Something incredibly unlikely. */ @@ -356,9 +331,10 @@ PHP_FUNCTION(finfo_file) } const char *ret_val = php_fileinfo_from_path(magic, path, context); + /* Restore options */ if (options) { - magic_setflags(magic, finfo->options); + magic_setflags(magic, old_options); } if (UNEXPECTED(ret_val == NULL)) { @@ -375,16 +351,23 @@ PHP_FUNCTION(finfo_buffer) zend_string *buffer = NULL; zend_long options = 0; zval *dummy_context = NULL; - php_fileinfo *finfo = NULL; if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "OS|lr!", &self, finfo_class_entry, &buffer, &options, &dummy_context) == FAILURE) { RETURN_THROWS(); } - FILEINFO_FROM_OBJECT(finfo, self); - struct magic_set *magic = finfo->magic; + + if (!Z_FINFO_P(self)->magic) { + zend_throw_error(NULL, "Invalid finfo object"); + RETURN_THROWS(); + } + + struct magic_set *magic = Z_FINFO_P(self)->magic; /* Set options for the current file/buffer. */ + int old_options = magic_getflags(magic); if (options) { + /* We do not check the return value as it can only ever fail if options contains MAGIC_PRESERVE_ATIME + * and the system neither has utime(3) nor utimes(2). Something incredibly unlikely. */ magic_setflags(magic, options); } @@ -392,7 +375,7 @@ PHP_FUNCTION(finfo_buffer) /* Restore options */ if (options) { - magic_setflags(magic, finfo->options); + magic_setflags(magic, old_options); } if (UNEXPECTED(ret_val == NULL)) { diff --git a/ext/fileinfo/tests/bug79756.phpt b/ext/fileinfo/tests/bug79756.phpt index b4ea28baaa9b2..ad5478b62de8e 100644 --- a/ext/fileinfo/tests/bug79756.phpt +++ b/ext/fileinfo/tests/bug79756.phpt @@ -7,7 +7,6 @@ fileinfo $filename = __DIR__ . '/bug79756.xls'; $finfo = finfo_open(FILEINFO_MIME); $mime = finfo_file($finfo, $filename); -finfo_close($finfo); echo $mime; ?> --EXPECT-- diff --git a/ext/fileinfo/tests/cve-2014-1943-mb.phpt b/ext/fileinfo/tests/cve-2014-1943-mb.phpt index 9dd4a9ec18a5a..01cf70b811bea 100644 --- a/ext/fileinfo/tests/cve-2014-1943-mb.phpt +++ b/ext/fileinfo/tests/cve-2014-1943-mb.phpt @@ -15,13 +15,11 @@ $m = "0 byte x\n". file_put_contents($fd, $a); $fi = finfo_open(FILEINFO_NONE); var_dump(finfo_file($fi, $fd)); -finfo_close($fi); file_put_contents($fd, $b); file_put_contents($fm, $m); $fi = finfo_open(FILEINFO_NONE, $fm); var_dump(finfo_file($fi, $fd)); -finfo_close($fi); ?> Done --CLEAN-- diff --git a/ext/fileinfo/tests/cve-2014-1943.phpt b/ext/fileinfo/tests/cve-2014-1943.phpt index 35f66148ae79c..1aee196d16ffc 100644 --- a/ext/fileinfo/tests/cve-2014-1943.phpt +++ b/ext/fileinfo/tests/cve-2014-1943.phpt @@ -15,13 +15,11 @@ $m = "0 byte x\n". file_put_contents($fd, $a); $fi = finfo_open(FILEINFO_NONE); var_dump(finfo_file($fi, $fd)); -finfo_close($fi); file_put_contents($fd, $b); file_put_contents($fm, $m); $fi = finfo_open(FILEINFO_NONE, $fm); var_dump(finfo_file($fi, $fd)); -finfo_close($fi); ?> Done --CLEAN-- diff --git a/ext/fileinfo/tests/cve-2014-3538-mb.phpt b/ext/fileinfo/tests/cve-2014-3538-mb.phpt index e6c63e35ac852..3b158a26b7264 100644 --- a/ext/fileinfo/tests/cve-2014-3538-mb.phpt +++ b/ext/fileinfo/tests/cve-2014-3538-mb.phpt @@ -19,7 +19,6 @@ $fi = finfo_open(FILEINFO_NONE); $t = microtime(true); var_dump(finfo_file($fi, $fd)); $t = microtime(true) - $t; -finfo_close($fi); if ($t < 3) { echo "Ok\n"; } else { diff --git a/ext/fileinfo/tests/cve-2014-3538-nojit.phpt b/ext/fileinfo/tests/cve-2014-3538-nojit.phpt index 2010d538da951..e8c32b7d7582c 100644 --- a/ext/fileinfo/tests/cve-2014-3538-nojit.phpt +++ b/ext/fileinfo/tests/cve-2014-3538-nojit.phpt @@ -23,8 +23,7 @@ $fi = finfo_open(FILEINFO_NONE); $t = microtime(true); var_dump(finfo_file($fi, $fd)); $t = microtime(true) - $t; -finfo_close($fi); -if ($t < 1.5) { +if ($t < 2) { echo "Ok\n"; } else { printf("Failed, time=%.2f\n", $t); diff --git a/ext/fileinfo/tests/cve-2014-3538.phpt b/ext/fileinfo/tests/cve-2014-3538.phpt index f15e745fc05d3..798317003a26c 100644 --- a/ext/fileinfo/tests/cve-2014-3538.phpt +++ b/ext/fileinfo/tests/cve-2014-3538.phpt @@ -19,8 +19,7 @@ $fi = finfo_open(FILEINFO_NONE); $t = microtime(true); var_dump(finfo_file($fi, $fd)); $t = microtime(true) - $t; -finfo_close($fi); -if ($t < 1.5) { +if ($t < 2) { echo "Ok\n"; } else { printf("Failed, time=%.2f\n", $t); diff --git a/ext/fileinfo/tests/finfo_buffer_basic-mb.phpt b/ext/fileinfo/tests/finfo_buffer_basic-mb.phpt index 7426c909d9763..0ed6d48c803cb 100644 --- a/ext/fileinfo/tests/finfo_buffer_basic-mb.phpt +++ b/ext/fileinfo/tests/finfo_buffer_basic-mb.phpt @@ -27,7 +27,6 @@ foreach( $options as $option ) { foreach( $buffers as $string ) { var_dump( finfo_buffer( $finfo, $string, $option ) ); } - finfo_close( $finfo ); } ?> diff --git a/ext/fileinfo/tests/finfo_buffer_basic.phpt b/ext/fileinfo/tests/finfo_buffer_basic.phpt index e338583fab702..6a6e6a7a862cb 100644 --- a/ext/fileinfo/tests/finfo_buffer_basic.phpt +++ b/ext/fileinfo/tests/finfo_buffer_basic.phpt @@ -27,7 +27,6 @@ foreach( $options as $option ) { foreach( $buffers as $string ) { var_dump( finfo_buffer( $finfo, $string, $option ) ); } - finfo_close( $finfo ); } ?> diff --git a/ext/fileinfo/tests/finfo_set_flags_basic-mb.phpt b/ext/fileinfo/tests/finfo_set_flags_basic-mb.phpt index f366972b613e1..a4d723f86c9ca 100644 --- a/ext/fileinfo/tests/finfo_set_flags_basic-mb.phpt +++ b/ext/fileinfo/tests/finfo_set_flags_basic-mb.phpt @@ -12,8 +12,6 @@ echo "*** Testing finfo_set_flags() : basic functionality ***\n"; var_dump( finfo_set_flags( $finfo, FILEINFO_NONE ) ); var_dump( finfo_set_flags( $finfo, FILEINFO_SYMLINK ) ); -finfo_close( $finfo ); - // OO way $finfo = new finfo( FILEINFO_NONE, $magicFile ); var_dump( $finfo->set_flags( FILEINFO_MIME ) ); diff --git a/ext/fileinfo/tests/finfo_set_flags_basic.phpt b/ext/fileinfo/tests/finfo_set_flags_basic.phpt index 948031a0b8006..db71447ae2393 100644 --- a/ext/fileinfo/tests/finfo_set_flags_basic.phpt +++ b/ext/fileinfo/tests/finfo_set_flags_basic.phpt @@ -12,8 +12,6 @@ echo "*** Testing finfo_set_flags() : basic functionality ***\n"; var_dump( finfo_set_flags( $finfo, FILEINFO_NONE ) ); var_dump( finfo_set_flags( $finfo, FILEINFO_SYMLINK ) ); -finfo_close( $finfo ); - // OO way $finfo = new finfo( FILEINFO_NONE, $magicFile ); var_dump( $finfo->set_flags( FILEINFO_MIME ) ); diff --git a/ext/fileinfo/tests/finfo_uninitialized.phpt b/ext/fileinfo/tests/finfo_uninitialized.phpt new file mode 100644 index 0000000000000..533574c9c0dcd --- /dev/null +++ b/ext/fileinfo/tests/finfo_uninitialized.phpt @@ -0,0 +1,53 @@ +--TEST-- +Fileinfo uninitialized object +--EXTENSIONS-- +fileinfo +--FILE-- +newInstanceWithoutConstructor(); + +try { + var_dump(finfo_set_flags($finfo, FILEINFO_NONE)); +} catch (Error $e) { + echo $e::class, ": ", $e->getMessage(), PHP_EOL; +} + +try { + var_dump($finfo->set_flags(FILEINFO_NONE)); +} catch (Error $e) { + echo $e::class, ": ", $e->getMessage(), PHP_EOL; +} + +try { + var_dump(finfo_file($finfo, __FILE__)); +} catch (Error $e) { + echo $e::class, ": ", $e->getMessage(), PHP_EOL; +} + +try { + var_dump($finfo->file(__FILE__)); +} catch (Error $e) { + echo $e::class, ": ", $e->getMessage(), PHP_EOL; +} + +try { + var_dump(finfo_buffer($finfo, file_get_contents(__FILE__))); +} catch (Error $e) { + echo $e::class, ": ", $e->getMessage(), PHP_EOL; +} + +try { + var_dump($finfo->file(file_get_contents(__FILE__))); +} catch (Error $e) { + echo $e::class, ": ", $e->getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +Error: Invalid finfo object +Error: Invalid finfo object +Error: Invalid finfo object +Error: Invalid finfo object +Error: Invalid finfo object +Error: Invalid finfo object diff --git a/ext/fileinfo/tests/finfo_upstream.phpt b/ext/fileinfo/tests/finfo_upstream.phpt index ef5ec17b03706..2a28bd7f776c0 100644 --- a/ext/fileinfo/tests/finfo_upstream.phpt +++ b/ext/fileinfo/tests/finfo_upstream.phpt @@ -18,7 +18,6 @@ foreach($lst as $p) { if ($i !== $exp) { echo "'$p' failed\nexp: '$exp'\ngot: '$i'\n"; } - finfo_close($finfo); } echo "==DONE=="; diff --git a/ext/intl/locale/locale_methods.c b/ext/intl/locale/locale_methods.c index bba52a90994cc..684f84c7e323a 100644 --- a/ext/intl/locale/locale_methods.c +++ b/ext/intl/locale/locale_methods.c @@ -315,7 +315,7 @@ PHP_NAMED_FUNCTION(zif_locale_set_default) char *default_locale = NULL; ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_STR(locale_name) + Z_PARAM_PATH_STR(locale_name) ZEND_PARSE_PARAMETERS_END(); if (ZSTR_LEN(locale_name) == 0) { @@ -481,7 +481,7 @@ static void get_icu_value_src_php( char* tag_name, INTERNAL_FUNCTION_PARAMETERS) intl_error_reset( NULL ); ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_STRING(loc_name, loc_name_len) + Z_PARAM_PATH(loc_name, loc_name_len) ZEND_PARSE_PARAMETERS_END(); if(loc_name_len == 0) { @@ -568,9 +568,9 @@ static void get_icu_disp_value_src_php( char* tag_name, INTERNAL_FUNCTION_PARAME intl_error_reset( NULL ); ZEND_PARSE_PARAMETERS_START(1, 2) - Z_PARAM_STRING(loc_name, loc_name_len) + Z_PARAM_PATH(loc_name, loc_name_len) Z_PARAM_OPTIONAL - Z_PARAM_STRING_OR_NULL(disp_loc_name, disp_loc_name_len) + Z_PARAM_PATH_OR_NULL(disp_loc_name, disp_loc_name_len) ZEND_PARSE_PARAMETERS_END(); if(loc_name_len > ULOC_FULLNAME_CAPACITY) { @@ -735,7 +735,7 @@ PHP_FUNCTION( locale_get_keywords ) intl_error_reset( NULL ); ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_STRING(loc_name, loc_name_len) + Z_PARAM_PATH(loc_name, loc_name_len) ZEND_PARSE_PARAMETERS_END(); INTL_CHECK_LOCALE_LEN(strlen(loc_name)); @@ -1126,7 +1126,7 @@ PHP_FUNCTION(locale_parse) intl_error_reset( NULL ); ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_STRING(loc_name, loc_name_len) + Z_PARAM_PATH(loc_name, loc_name_len) ZEND_PARSE_PARAMETERS_END(); INTL_CHECK_LOCALE_LEN(strlen(loc_name)); @@ -1166,7 +1166,7 @@ PHP_FUNCTION(locale_get_all_variants) intl_error_reset( NULL ); ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_STRING(loc_name, loc_name_len) + Z_PARAM_PATH(loc_name, loc_name_len) ZEND_PARSE_PARAMETERS_END(); if(loc_name_len == 0) { @@ -1260,8 +1260,8 @@ PHP_FUNCTION(locale_filter_matches) intl_error_reset( NULL ); ZEND_PARSE_PARAMETERS_START(2, 3) - Z_PARAM_STRING(lang_tag, lang_tag_len) - Z_PARAM_STRING(loc_range, loc_range_len) + Z_PARAM_PATH(lang_tag, lang_tag_len) + Z_PARAM_PATH(loc_range, loc_range_len) Z_PARAM_OPTIONAL Z_PARAM_BOOL(boolCanonical) ZEND_PARSE_PARAMETERS_END(); @@ -1434,6 +1434,10 @@ static zend_string* lookup_loc_range(const char* loc_range, HashTable* hash_arr, zend_argument_type_error(2, "must only contain string values"); LOOKUP_CLEAN_RETURN(NULL); } + if (zend_str_has_nul_byte(Z_STR_P(ele_value))) { + zend_argument_value_error(2, "must not contain any null bytes"); + LOOKUP_CLEAN_RETURN(NULL); + } cur_arr[cur_arr_len*2] = estrndup(Z_STRVAL_P(ele_value), Z_STRLEN_P(ele_value)); result = strToMatch(Z_STRVAL_P(ele_value), cur_arr[cur_arr_len*2]); if(result == 0) { @@ -1535,10 +1539,10 @@ PHP_FUNCTION(locale_lookup) ZEND_PARSE_PARAMETERS_START(2, 4) Z_PARAM_ARRAY(arr) - Z_PARAM_STRING(loc_range, loc_range_len) + Z_PARAM_PATH(loc_range, loc_range_len) Z_PARAM_OPTIONAL Z_PARAM_BOOL(boolCanonical) - Z_PARAM_STR_OR_NULL(fallback_loc_str) + Z_PARAM_PATH_STR_OR_NULL(fallback_loc_str) ZEND_PARSE_PARAMETERS_END(); if(loc_range_len == 0) { @@ -1626,7 +1630,7 @@ PHP_FUNCTION(locale_is_right_to_left) size_t locale_len; ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_STRING(locale, locale_len) + Z_PARAM_PATH(locale, locale_len) ZEND_PARSE_PARAMETERS_END(); if (!locale_len) { diff --git a/ext/intl/tests/locale_filter_matches_icu70.phpt b/ext/intl/tests/locale_filter_matches_icu70.phpt index ce30b0565472f..0e0b16af17606 100644 --- a/ext/intl/tests/locale_filter_matches_icu70.phpt +++ b/ext/intl/tests/locale_filter_matches_icu70.phpt @@ -69,6 +69,18 @@ function ut_main() } } + try { + ut_loc_locale_filter_matches("de\0-DE", "de-DE", false); + } catch (\ValueError $e) { + echo $e->getMessage(). PHP_EOL; + } + + try { + ut_loc_locale_filter_matches("de-DE", "d\0e-DE", false); + } catch (\ValueError $e) { + echo $e->getMessage(). PHP_EOL; + } + $res_str .= "\n"; return $res_str; @@ -79,6 +91,10 @@ ut_run(); ?> --EXPECT-- +Locale::filterMatches(): Argument #1 ($languageTag) must not contain any null bytes +Locale::filterMatches(): Argument #2 ($locale) must not contain any null bytes +locale_filter_matches(): Argument #1 ($languageTag) must not contain any null bytes +locale_filter_matches(): Argument #2 ($locale) must not contain any null bytes -------------- loc_range:de-de matches lang_tag de-DEVA ? NO loc_range:de_DE canonically matches lang_tag de_Deva ? NO diff --git a/ext/intl/tests/locale_get_all_variants.phpt b/ext/intl/tests/locale_get_all_variants.phpt index 5b876d87eda95..12bf82cacac09 100644 --- a/ext/intl/tests/locale_get_all_variants.phpt +++ b/ext/intl/tests/locale_get_all_variants.phpt @@ -39,6 +39,12 @@ function ut_main() $res_str .= "\n"; } + try { + ut_loc_locale_get_all_variants("i-\0tay"); + } catch (\ValueError $e) { + echo $e->getMessage(). PHP_EOL; + } + $res_str .= "\n"; return $res_str; @@ -49,6 +55,8 @@ ut_run(); ?> --EXPECT-- +Locale::getAllVariants(): Argument #1 ($locale) must not contain any null bytes +locale_get_all_variants(): Argument #1 ($locale) must not contain any null bytes sl_IT_nedis_KIRTI : variants 'NEDIS','KIRTI', sl_IT_nedis-a-kirti-x-xyz : variants 'NEDIS', sl_IT_rozaj : variants 'ROZAJ', diff --git a/ext/intl/tests/locale_get_display_language4.phpt b/ext/intl/tests/locale_get_display_language4.phpt new file mode 100644 index 0000000000000..1273c4a99968d --- /dev/null +++ b/ext/intl/tests/locale_get_display_language4.phpt @@ -0,0 +1,29 @@ +--TEST-- +locale_get_display_language() throwing null bytes exceptions. +--EXTENSIONS-- +intl +--FILE-- +getMessage(). PHP_EOL; + } + + try { + ut_loc_get_display_language("a-DE", "locale=a\0-DE"); + } catch (\ValueError $e) { + echo $e->getMessage(). PHP_EOL; + } +} +include_once 'ut_common.inc'; +ut_run(); +?> +--EXPECT-- +Locale::getDisplayLanguage(): Argument #1 ($locale) must not contain any null bytes +Locale::getDisplayLanguage(): Argument #2 ($displayLocale) must not contain any null bytes +locale_get_display_language(): Argument #1 ($locale) must not contain any null bytes +locale_get_display_language(): Argument #2 ($displayLocale) must not contain any null bytes diff --git a/ext/intl/tests/locale_get_display_script4.phpt b/ext/intl/tests/locale_get_display_script4.phpt index 77c630393c88a..5330529330269 100644 --- a/ext/intl/tests/locale_get_display_script4.phpt +++ b/ext/intl/tests/locale_get_display_script4.phpt @@ -83,6 +83,18 @@ function ut_main() $res_str .= "-----------------\n"; } + try { + ut_loc_get_display_script("a-D\0E", "locale=a-DE"); + } catch (\ValueError $e) { + echo $e->getMessage(). PHP_EOL; + } + + try { + ut_loc_get_display_script("a-DE", "locale=a\0-DE"); + } catch (\ValueError $e) { + echo $e->getMessage(). PHP_EOL; + } + return $res_str; } @@ -92,6 +104,10 @@ ut_run(); ?> --EXPECT-- +Locale::getDisplayScript(): Argument #1 ($locale) must not contain any null bytes +Locale::getDisplayScript(): Argument #2 ($displayLocale) must not contain any null bytes +locale_get_display_script(): Argument #1 ($locale) must not contain any null bytes +locale_get_display_script(): Argument #2 ($displayLocale) must not contain any null bytes locale='uk-ua_CALIFORNIA@currency=;currency=GRN' disp_locale=en : display_script= disp_locale=fr : display_script= diff --git a/ext/intl/tests/locale_get_region.phpt b/ext/intl/tests/locale_get_region.phpt index f843397bdb6cf..0c3c1655deb3a 100644 --- a/ext/intl/tests/locale_get_region.phpt +++ b/ext/intl/tests/locale_get_region.phpt @@ -76,6 +76,12 @@ function ut_main() $res_str .= "\n"; } + try { + ut_loc_get_region("a-\0DE"); + } catch (\ValueError $e) { + echo $e->getMessage(). PHP_EOL; + } + return $res_str; } @@ -85,6 +91,8 @@ ut_run(); ?> --EXPECTF-- +Locale::getRegion(): Argument #1 ($locale) must not contain any null bytes +locale_get_region(): Argument #1 ($locale) must not contain any null bytes uk-ua_CALIFORNIA@currency=;currency=GRN: region='UA' root: region='' uk@currency=EURO: region='' diff --git a/ext/intl/tests/locale_get_script.phpt b/ext/intl/tests/locale_get_script.phpt index e00c83626d5bf..52e0a4155a971 100644 --- a/ext/intl/tests/locale_get_script.phpt +++ b/ext/intl/tests/locale_get_script.phpt @@ -74,6 +74,12 @@ function ut_main() $res_str .= "\n"; } + try { + ut_loc_get_script("de\0-419-DE"); + } catch (\ValueError $e) { + echo $e->getMessage(). PHP_EOL; + } + return $res_str; } @@ -83,6 +89,8 @@ ut_run(); ?> --EXPECT-- +Locale::getScript(): Argument #1 ($locale) must not contain any null bytes +locale_get_script(): Argument #1 ($locale) must not contain any null bytes uk-ua_CALIFORNIA@currency=;currency=GRN: script='' root: script='' uk@currency=EURO: script='' diff --git a/ext/intl/tests/locale_is_right_to_left.phpt b/ext/intl/tests/locale_is_right_to_left.phpt index c586582d42225..c9e4323ff7442 100644 --- a/ext/intl/tests/locale_is_right_to_left.phpt +++ b/ext/intl/tests/locale_is_right_to_left.phpt @@ -8,9 +8,15 @@ var_dump(Locale::isRightToLeft("en-US")); var_dump(Locale::isRightToLeft("\INVALID\\")); var_dump(Locale::isRightToLeft("")); var_dump(Locale::isRightToLeft("ar")); +try { + Locale::isRightToLeft("a\0r"); +} catch (\ValueError $e) { + echo $e->getMessage(); +} ?> --EXPECT-- bool(false) bool(false) bool(false) bool(true) +Locale::isRightToLeft(): Argument #1 ($locale) must not contain any null bytes diff --git a/ext/intl/tests/locale_lookup_variant3.phpt b/ext/intl/tests/locale_lookup_variant3.phpt index c1741a0ed9dd4..b13a54139f443 100644 --- a/ext/intl/tests/locale_lookup_variant3.phpt +++ b/ext/intl/tests/locale_lookup_variant3.phpt @@ -59,6 +59,24 @@ function ut_main() } + try { + ut_loc_locale_lookup(["de\0-DE"], "de-DE", false, "en-US"); + } catch (\ValueError $e) { + echo $e->getMessage(). PHP_EOL; + } + + try { + ut_loc_locale_lookup(["de-DE"], "de-D\0E", true, "en-US"); + } catch (\ValueError $e) { + echo $e->getMessage(). PHP_EOL; + } + + try { + ut_loc_locale_lookup(["de-DE"], "de-DE", true, "e\0n-US"); + } catch (\ValueError $e) { + echo $e->getMessage(). PHP_EOL; + } + $res_str .= "\n"; return $res_str; @@ -69,6 +87,12 @@ ut_run(); ?> --EXPECT-- +Locale::lookup(): Argument #2 ($locale) must not contain any null bytes +Locale::lookup(): Argument #2 ($locale) must not contain any null bytes +Locale::lookup(): Argument #4 ($defaultLocale) must not contain any null bytes +locale_lookup(): Argument #2 ($locale) must not contain any null bytes +locale_lookup(): Argument #2 ($locale) must not contain any null bytes +locale_lookup(): Argument #4 ($defaultLocale) must not contain any null bytes -------------- loc_range:de-de lang_tags: de-DEVA,de-DE-1996,de-DE,zh_Hans,de-CH-1996,sl_IT,sl_IT_nedis-a-kirti-x-xyz,sl_IT_rozaj,sl_IT_NEDIS_ROJAZ_1901,i-enochian,sgn-CH-de,art-lojban,i-lux,art-lojban,jbo,en_sl_IT,zh-Hant-CN-x-prv1-prv2 diff --git a/ext/intl/tests/locale_set_default.phpt b/ext/intl/tests/locale_set_default.phpt index 0f690aabc2965..6108f370274bb 100644 --- a/ext/intl/tests/locale_set_default.phpt +++ b/ext/intl/tests/locale_set_default.phpt @@ -86,6 +86,12 @@ function ut_main() $res_str .= "\n"; } + try { + ut_loc_set_default("a-\0DE"); + } catch (\ValueError $e) { + echo $e->getMessage(), PHP_EOL; + } + return $res_str; } @@ -95,6 +101,8 @@ ut_run(); ?> --EXPECT-- +Locale::setDefault(): Argument #1 ($locale) must not contain any null bytes +locale_set_default(): Argument #1 ($locale) must not contain any null bytes uk-ua_CALIFORNIA@currency=;currency=GRN: set locale 'uk-ua_CALIFORNIA@currency=;currency=GRN' root: set locale 'root' uk@currency=EURO: set locale 'uk@currency=EURO' diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c index 19e3e29bedff3..389833af3eb69 100644 --- a/ext/standard/basic_functions.c +++ b/ext/standard/basic_functions.c @@ -828,6 +828,7 @@ PHP_FUNCTION(putenv) #endif RETURN_TRUE; } else { + tsrm_env_unlock(); free(pe.putenv_string); zend_string_release(pe.key); #ifdef PHP_WIN32 diff --git a/ext/standard/url.c b/ext/standard/url.c index 3d704b0140ca9..da2ddea067314 100644 --- a/ext/standard/url.c +++ b/ext/standard/url.c @@ -411,21 +411,24 @@ PHP_FUNCTION(parse_url) } /* }}} */ +/* https://stackoverflow.com/questions/34365746/whats-the-fastest-way-to-convert-hex-to-integer-in-c */ +static unsigned int php_htoi_single(unsigned char x) +{ + ZEND_ASSERT((x >= 'a' && x <= 'f') || (x >= 'A' && x <= 'F') || (x >= '0' && x <= '9')); + return 9 * (x >> 6) + (x & 0xf); +} + /* {{{ php_htoi */ -static int php_htoi(char *s) +static int php_htoi(const char *s) { int value; - int c; + unsigned char c; c = ((unsigned char *)s)[0]; - if (isupper(c)) - c = tolower(c); - value = (c >= '0' && c <= '9' ? c - '0' : c - 'a' + 10) * 16; + value = php_htoi_single(c) * 16; c = ((unsigned char *)s)[1]; - if (isupper(c)) - c = tolower(c); - value += c >= '0' && c <= '9' ? c - '0' : c - 'a' + 10; + value += php_htoi_single(c); return (value); } @@ -572,28 +575,27 @@ PHP_FUNCTION(urldecode) Z_PARAM_STR(in_str) ZEND_PARSE_PARAMETERS_END(); - out_str = zend_string_init(ZSTR_VAL(in_str), ZSTR_LEN(in_str), 0); - ZSTR_LEN(out_str) = php_url_decode(ZSTR_VAL(out_str), ZSTR_LEN(out_str)); + out_str = zend_string_alloc(ZSTR_LEN(in_str), false); + ZSTR_LEN(out_str) = php_url_decode_ex(ZSTR_VAL(out_str), ZSTR_VAL(in_str), ZSTR_LEN(in_str)); RETURN_NEW_STR(out_str); } /* }}} */ -/* {{{ php_url_decode */ -PHPAPI size_t php_url_decode(char *str, size_t len) +PHPAPI size_t php_url_decode_ex(char *dest, const char *src, size_t src_len) { - char *dest = str; - char *data = str; + char *dest_start = dest; + const char *data = src; - while (len--) { + while (src_len--) { if (*data == '+') { *dest = ' '; } - else if (*data == '%' && len >= 2 && isxdigit((int) *(data + 1)) + else if (*data == '%' && src_len >= 2 && isxdigit((int) *(data + 1)) && isxdigit((int) *(data + 2))) { *dest = (char) php_htoi(data + 1); data += 2; - len -= 2; + src_len -= 2; } else { *dest = *data; } @@ -601,7 +603,13 @@ PHPAPI size_t php_url_decode(char *str, size_t len) dest++; } *dest = '\0'; - return dest - str; + return dest - dest_start; +} + +/* {{{ php_url_decode */ +PHPAPI size_t php_url_decode(char *str, size_t len) +{ + return php_url_decode_ex(str, str, len); } /* }}} */ @@ -634,25 +642,24 @@ PHP_FUNCTION(rawurldecode) Z_PARAM_STR(in_str) ZEND_PARSE_PARAMETERS_END(); - out_str = zend_string_init(ZSTR_VAL(in_str), ZSTR_LEN(in_str), 0); - ZSTR_LEN(out_str) = php_raw_url_decode(ZSTR_VAL(out_str), ZSTR_LEN(out_str)); + out_str = zend_string_alloc(ZSTR_LEN(in_str), false); + ZSTR_LEN(out_str) = php_raw_url_decode_ex(ZSTR_VAL(out_str), ZSTR_VAL(in_str), ZSTR_LEN(in_str)); RETURN_NEW_STR(out_str); } /* }}} */ -/* {{{ php_raw_url_decode */ -PHPAPI size_t php_raw_url_decode(char *str, size_t len) +PHPAPI size_t php_raw_url_decode_ex(char *dest, const char *src, size_t src_len) { - char *dest = str; - char *data = str; + char *dest_start = dest; + const char *data = src; - while (len--) { - if (*data == '%' && len >= 2 && isxdigit((int) *(data + 1)) + while (src_len--) { + if (*data == '%' && src_len >= 2 && isxdigit((int) *(data + 1)) && isxdigit((int) *(data + 2))) { *dest = (char) php_htoi(data + 1); data += 2; - len -= 2; + src_len -= 2; } else { *dest = *data; } @@ -660,7 +667,13 @@ PHPAPI size_t php_raw_url_decode(char *str, size_t len) dest++; } *dest = '\0'; - return dest - str; + return dest - dest_start; +} + +/* {{{ php_raw_url_decode */ +PHPAPI size_t php_raw_url_decode(char *str, size_t len) +{ + return php_raw_url_decode_ex(str, str, len); } /* }}} */ diff --git a/ext/standard/url.h b/ext/standard/url.h index 4126ee6c6db40..5c531c0086a20 100644 --- a/ext/standard/url.h +++ b/ext/standard/url.h @@ -33,7 +33,9 @@ PHPAPI php_url *php_url_parse(char const *str); PHPAPI php_url *php_url_parse_ex(char const *str, size_t length); PHPAPI php_url *php_url_parse_ex2(char const *str, size_t length, bool *has_port); PHPAPI size_t php_url_decode(char *str, size_t len); /* return value: length of decoded string */ +PHPAPI size_t php_url_decode_ex(char *dest, const char *src, size_t src_len); PHPAPI size_t php_raw_url_decode(char *str, size_t len); /* return value: length of decoded string */ +PHPAPI size_t php_raw_url_decode_ex(char *dest, const char *src, size_t src_len); PHPAPI zend_string *php_url_encode(char const *s, size_t len); PHPAPI zend_string *php_raw_url_encode(char const *s, size_t len); diff --git a/ext/xml/compat.c b/ext/xml/compat.c index d338c7d17b9c4..cafb19c2c1edd 100644 --- a/ext/xml/compat.c +++ b/ext/xml/compat.c @@ -689,20 +689,8 @@ XML_GetCurrentColumnNumber(XML_Parser parser) PHP_XML_API long XML_GetCurrentByteIndex(XML_Parser parser) { - /* We have to temporarily disable the encoder to satisfy the note from the manual: - * "This function returns byte index according to UTF-8 encoded text disregarding if input is in another encoding." - * Although that should probably be corrected at one point? (TODO) */ - xmlCharEncodingHandlerPtr encoder = NULL; - xmlParserInputPtr input = parser->parser->input; - if (input->buf) { - encoder = input->buf->encoder; - input->buf->encoder = NULL; - } - long result = xmlByteConsumed(parser->parser); - if (encoder) { - input->buf->encoder = encoder; - } - return result; + return parser->parser->input->consumed + + (parser->parser->input->cur - parser->parser->input->base); } PHP_XML_API int