diff --git a/.github/actions/notify-slack/action.yml b/.github/actions/notify-slack/action.yml deleted file mode 100644 index 1ff425b51c6ac..0000000000000 --- a/.github/actions/notify-slack/action.yml +++ /dev/null @@ -1,10 +0,0 @@ -name: Notify Slack -inputs: - token: - required: true -runs: - using: composite - steps: - - shell: bash - run: >- - curl -X POST -H 'Content-type: application/json' --data '{"attachments": [{"text": "Job in *nightly* failed", "footer": "", "color": "danger", "mrkdwn_in": ["text"]}]}' ${{ inputs.token }} diff --git a/.github/workflows/nightly-results.yml b/.github/workflows/nightly-results.yml new file mode 100644 index 0000000000000..c1c4da72ca56a --- /dev/null +++ b/.github/workflows/nightly-results.yml @@ -0,0 +1,16 @@ +name: Nightly results +on: + workflow_run: + workflows: + - Nightly + types: + - completed +jobs: + on-failure: + runs-on: ubuntu-latest + if: ${{ github.repository == 'php/php-src' && github.event.workflow_run.conclusion == 'failure' }} + steps: + - run: | + export DEBIAN_FRONTEND=noninteractive + sudo apt-get install -y curl + curl -X POST -H 'Content-type: application/json' --data '{"attachments": [{"text": "Job in *nightly* failed", "footer": "<${{ github.event.workflow_run.jobs_url }}|View Run>", "color": "danger", "mrkdwn_in": ["text"]}]}' ${{ secrets.ACTION_MONITORING_SLACK }} diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index ded06c46b2ecf..adf07313a4c59 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -138,12 +138,6 @@ jobs: -d opcache.enable_cli=1 - name: Extra tests uses: ./.github/actions/extra-tests - - name: Notify Slack - if: failure() - uses: ./.github/actions/notify-slack - with: - token: ${{ secrets.ACTION_MONITORING_SLACK }} - LINUX_X64: services: mysql: @@ -272,11 +266,6 @@ jobs: uses: ./.github/actions/extra-tests - name: Verify generated files are up to date uses: ./.github/actions/verify-generated-files - - name: Notify Slack - if: failure() - uses: ./.github/actions/notify-slack - with: - token: ${{ secrets.ACTION_MONITORING_SLACK }} LINUX_X32: strategy: fail-fast: false @@ -358,11 +347,6 @@ jobs: -d opcache.enable_cli=1 - name: Extra tests uses: ./.github/actions/extra-tests - - name: Notify Slack - if: failure() - uses: ./.github/actions/notify-slack - with: - token: ${{ secrets.ACTION_MONITORING_SLACK }} MACOS: strategy: fail-fast: false @@ -418,11 +402,6 @@ jobs: uses: ./.github/actions/extra-tests - name: Verify generated files are up to date uses: ./.github/actions/verify-generated-files - - name: Notify Slack - if: failure() - uses: ./.github/actions/notify-slack - with: - token: ${{ secrets.ACTION_MONITORING_SLACK }} COVERAGE_DEBUG_NTS: if: inputs.branch == 'master' services: @@ -483,11 +462,6 @@ jobs: fail_ci_if_error: true token: ${{ secrets.CODECOV_TOKEN }} verbose: true - - name: Notify Slack - if: failure() - uses: ./.github/actions/notify-slack - with: - token: ${{ secrets.ACTION_MONITORING_SLACK }} COMMUNITY: strategy: fail-fast: false @@ -674,11 +648,6 @@ jobs: if [ $EXIT_CODE -gt 128 ]; then exit 1 fi - - name: Notify Slack - if: failure() - uses: ./.github/actions/notify-slack - with: - token: ${{ secrets.ACTION_MONITORING_SLACK }} OPCACHE_VARIATION: services: mysql: @@ -760,11 +729,6 @@ jobs: -d opcache.file_cache_only=1 - name: Verify generated files are up to date uses: ./.github/actions/verify-generated-files - - name: Notify Slack - if: failure() - uses: ./.github/actions/notify-slack - with: - token: ${{ secrets.ACTION_MONITORING_SLACK }} MSAN: name: MSAN runs-on: ubuntu-${{ inputs.ubuntu_version }} @@ -851,11 +815,6 @@ jobs: -d opcache.enable_cli=1 - name: Verify generated files are up to date uses: ./.github/actions/verify-generated-files - - name: Notify Slack - if: failure() - uses: ./.github/actions/notify-slack - with: - token: ${{ secrets.ACTION_MONITORING_SLACK }} LIBMYSQLCLIENT: name: LIBMYSQLCLIENT runs-on: ubuntu-${{ inputs.ubuntu_version }} @@ -898,11 +857,6 @@ jobs: withMysqli: ${{ inputs.libmysqlclient_with_mysqli }} - name: Verify generated files are up to date uses: ./.github/actions/verify-generated-files - - name: Notify Slack - if: failure() - uses: ./.github/actions/notify-slack - with: - token: ${{ secrets.ACTION_MONITORING_SLACK }} PECL: if: inputs.branch == 'master' runs-on: ubuntu-22.04 @@ -1010,11 +964,6 @@ jobs: /opt/php/bin/phpize ./configure --prefix=/opt/php --with-php-config=/opt/php/bin/php-config make -j$(/usr/bin/nproc) - - name: Notify Slack - if: failure() - uses: ./.github/actions/notify-slack - with: - token: ${{ secrets.ACTION_MONITORING_SLACK }} WINDOWS: strategy: fail-fast: false diff --git a/.github/workflows/root.yml b/.github/workflows/root.yml index 2983a8e3c9081..000f51f13cc16 100644 --- a/.github/workflows/root.yml +++ b/.github/workflows/root.yml @@ -31,11 +31,6 @@ jobs: - name: Generate Matrix id: set-matrix run: php .github/nightly_matrix.php "${{ github.event_name }}" "${{ github.run_attempt }}" "${{ github.head_ref || github.ref_name }}" - - name: Notify Slack - if: failure() - uses: ./.github/actions/notify-slack - with: - token: ${{ secrets.ACTION_MONITORING_SLACK }} NIGHTLY: needs: GENERATE_MATRIX name: ${{ matrix.branch.ref }} diff --git a/UPGRADING.INTERNALS b/UPGRADING.INTERNALS index d269bd107885e..42e52480bbb9c 100644 --- a/UPGRADING.INTERNALS +++ b/UPGRADING.INTERNALS @@ -32,6 +32,8 @@ PHP 8.6 INTERNALS UPGRADE NOTES . ZEND_LTOA() (and ZEND_LTOA_BUF_LEN) has been removed, as it was unsafe. Directly use ZEND_LONG_FMT with a function from the printf family. + . The zval_dtor() alias of zval_ptr_dtor_nogc() has been removed. + Call zval_ptr_dtor_nogc() directly instead. ======================== 2. Build system changes diff --git a/Zend/zend_variables.h b/Zend/zend_variables.h index 1cb745ca1b1dc..d90ad9951782a 100644 --- a/Zend/zend_variables.h +++ b/Zend/zend_variables.h @@ -81,9 +81,6 @@ ZEND_API void zval_ptr_dtor(zval *zval_ptr); ZEND_API void zval_ptr_safe_dtor(zval *zval_ptr); ZEND_API void zval_internal_ptr_dtor(zval *zvalue); -/* Kept for compatibility */ -#define zval_dtor(zvalue) zval_ptr_dtor_nogc(zvalue) - ZEND_API void zval_add_ref(zval *p); END_EXTERN_C() diff --git a/ext/pdo/pdo_stmt.c b/ext/pdo/pdo_stmt.c index e2723c703f0ac..e87af66c75868 100644 --- a/ext/pdo/pdo_stmt.c +++ b/ext/pdo/pdo_stmt.c @@ -1052,7 +1052,7 @@ PHP_METHOD(PDOStatement, fetch) array_init_size(return_value, 1); bool success = pdo_do_key_pair_fetch(stmt, ori, off, Z_ARRVAL_P(return_value)); if (!success) { - zval_dtor(return_value); + zval_ptr_dtor_nogc(return_value); PDO_HANDLE_STMT_ERR(); RETURN_FALSE; } diff --git a/ext/pgsql/pgsql.c b/ext/pgsql/pgsql.c index 3f511d21456bd..89c99cd84132a 100644 --- a/ext/pgsql/pgsql.c +++ b/ext/pgsql/pgsql.c @@ -1223,26 +1223,55 @@ PHP_FUNCTION(pg_query) } } -static void _php_pgsql_free_params(char **params, int num_params) +/* The char pointer MUST refer to the char* of a zend_string struct */ +static void php_pgsql_zend_string_release_from_char_pointer(char *ptr) { + zend_string_release((zend_string*) (ptr - XtOffsetOf(zend_string, val))); +} + +static void _php_pgsql_free_params(char **params, uint32_t num_params) { - int i; - for (i = 0; i < num_params; i++) { + for (uint32_t i = 0; i < num_params; i++) { if (params[i]) { - efree(params[i]); + php_pgsql_zend_string_release_from_char_pointer(params[i]); } } efree(params); } +static char **php_pgsql_make_arguments(const HashTable *param_arr, int *num_params) +{ + /* This conversion is safe because of the limit of number of elements in a table. */ + *num_params = (int) zend_hash_num_elements(param_arr); + char **params = safe_emalloc(sizeof(char *), *num_params, 0); + uint32_t i = 0; + + ZEND_HASH_FOREACH_VAL(param_arr, zval *tmp) { + ZVAL_DEREF(tmp); + if (Z_TYPE_P(tmp) == IS_NULL) { + params[i] = NULL; + } else { + zend_string *param_str = zval_try_get_string(tmp); + if (!param_str) { + _php_pgsql_free_params(params, i); + return NULL; + } + params[i] = ZSTR_VAL(param_str); + } + i++; + } ZEND_HASH_FOREACH_END(); + + return params; +} + /* Execute a query */ PHP_FUNCTION(pg_query_params) { zval *pgsql_link = NULL; - zval *pv_param_arr, *tmp; + zval *pv_param_arr; char *query; size_t query_len; bool leftover = false; - int num_params = 0; + int num_params; char **params = NULL; pgsql_link_handle *link; PGconn *pgsql; @@ -1286,26 +1315,9 @@ PHP_FUNCTION(pg_query_params) php_error_docref(NULL, E_NOTICE, "Found results on this connection. Use pg_get_result() to get these results first"); } - num_params = zend_hash_num_elements(Z_ARRVAL_P(pv_param_arr)); - if (num_params > 0) { - int i = 0; - params = (char **)safe_emalloc(sizeof(char *), num_params, 0); - - ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(pv_param_arr), tmp) { - ZVAL_DEREF(tmp); - if (Z_TYPE_P(tmp) == IS_NULL) { - params[i] = NULL; - } else { - zend_string *param_str = zval_try_get_string(tmp); - if (!param_str) { - _php_pgsql_free_params(params, i); - RETURN_THROWS(); - } - params[i] = estrndup(ZSTR_VAL(param_str), ZSTR_LEN(param_str)); - zend_string_release(param_str); - } - i++; - } ZEND_HASH_FOREACH_END(); + params = php_pgsql_make_arguments(Z_ARRVAL_P(pv_param_arr), &num_params); + if (UNEXPECTED(!params)) { + RETURN_THROWS(); } pgsql_result = PQexecParams(pgsql, query, num_params, @@ -1440,11 +1452,11 @@ PHP_FUNCTION(pg_prepare) PHP_FUNCTION(pg_execute) { zval *pgsql_link = NULL; - zval *pv_param_arr, *tmp; + zval *pv_param_arr; char *stmtname; size_t stmtname_len; bool leftover = false; - int num_params = 0; + int num_params; char **params = NULL; PGconn *pgsql; pgsql_link_handle *link; @@ -1488,25 +1500,9 @@ PHP_FUNCTION(pg_execute) php_error_docref(NULL, E_NOTICE, "Found results on this connection. Use pg_get_result() to get these results first"); } - num_params = zend_hash_num_elements(Z_ARRVAL_P(pv_param_arr)); - if (num_params > 0) { - int i = 0; - params = (char **)safe_emalloc(sizeof(char *), num_params, 0); - - ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(pv_param_arr), tmp) { - ZVAL_DEREF(tmp); - if (Z_TYPE_P(tmp) == IS_NULL) { - params[i] = NULL; - } else { - zend_string *tmp_str; - zend_string *str = zval_get_tmp_string(tmp, &tmp_str); - - params[i] = estrndup(ZSTR_VAL(str), ZSTR_LEN(str)); - zend_tmp_string_release(tmp_str); - } - - i++; - } ZEND_HASH_FOREACH_END(); + params = php_pgsql_make_arguments(Z_ARRVAL_P(pv_param_arr), &num_params); + if (UNEXPECTED(!params)) { + RETURN_THROWS(); } pgsql_result = PQexecPrepared(pgsql, stmtname, num_params, @@ -3409,26 +3405,27 @@ PHP_FUNCTION(pg_copy_to) static zend_result pgsql_copy_from_query(PGconn *pgsql, PGresult *pgsql_result, zval *value) { - zend_string *tmp = zval_try_get_string(value); + zend_string *tmp_tmp; + zend_string *tmp = zval_try_get_tmp_string(value, &tmp_tmp); if (UNEXPECTED(!tmp)) { return FAILURE; } - zend_string *zquery = zend_string_alloc(ZSTR_LEN(tmp) + 2, false); - memcpy(ZSTR_VAL(zquery), ZSTR_VAL(tmp), ZSTR_LEN(tmp) + 1); - ZSTR_LEN(zquery) = ZSTR_LEN(tmp); - if (ZSTR_LEN(tmp) > 0 && ZSTR_VAL(zquery)[ZSTR_LEN(tmp) - 1] != '\n') { - ZSTR_VAL(zquery)[ZSTR_LEN(tmp)] = '\n'; - ZSTR_VAL(zquery)[ZSTR_LEN(tmp) + 1] = '\0'; - ZSTR_LEN(zquery) ++; - } - if (PQputCopyData(pgsql, ZSTR_VAL(zquery), ZSTR_LEN(zquery)) != 1) { - zend_string_release_ex(zquery, false); - zend_string_release(tmp); - return FAILURE; + + int result; + if (ZSTR_LEN(tmp) > 0 && ZSTR_VAL(tmp)[ZSTR_LEN(tmp) - 1] != '\n') { + char *zquery = emalloc(ZSTR_LEN(tmp) + 2); + memcpy(zquery, ZSTR_VAL(tmp), ZSTR_LEN(tmp) + 1); + zquery[ZSTR_LEN(tmp)] = '\n'; + zquery[ZSTR_LEN(tmp) + 1] = '\0'; + result = PQputCopyData(pgsql, zquery, ZSTR_LEN(tmp) + 1); + efree(zquery); + } else { + result = PQputCopyData(pgsql, ZSTR_VAL(tmp), ZSTR_LEN(tmp)); } - zend_string_release_ex(zquery, false); - zend_string_release(tmp); - return SUCCESS; + + zend_tmp_string_release(tmp_tmp); + + return result != 1 ? FAILURE : SUCCESS; } /* {{{ Copy table from array */ @@ -4033,9 +4030,9 @@ PHP_FUNCTION(pg_send_query) /* {{{ Send asynchronous parameterized query */ PHP_FUNCTION(pg_send_query_params) { - zval *pgsql_link, *pv_param_arr, *tmp; + zval *pgsql_link, *pv_param_arr; pgsql_link_handle *link; - int num_params = 0; + int num_params; char **params = NULL; char *query; size_t query_len; @@ -4065,25 +4062,9 @@ PHP_FUNCTION(pg_send_query_params) "There are results on this connection. Call pg_get_result() until it returns FALSE"); } - num_params = zend_hash_num_elements(Z_ARRVAL_P(pv_param_arr)); - if (num_params > 0) { - int i = 0; - params = (char **)safe_emalloc(sizeof(char *), num_params, 0); - - ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(pv_param_arr), tmp) { - ZVAL_DEREF(tmp); - if (Z_TYPE_P(tmp) == IS_NULL) { - params[i] = NULL; - } else { - zend_string *tmp_str; - zend_string *str = zval_get_tmp_string(tmp, &tmp_str); - - params[i] = estrndup(ZSTR_VAL(str), ZSTR_LEN(str)); - zend_tmp_string_release(tmp_str); - } - - i++; - } ZEND_HASH_FOREACH_END(); + params = php_pgsql_make_arguments(Z_ARRVAL_P(pv_param_arr), &num_params); + if (UNEXPECTED(!params)) { + RETURN_THROWS(); } if (PQsendQueryParams(pgsql, query, num_params, NULL, (const char * const *)params, NULL, NULL, 0)) { @@ -4205,8 +4186,8 @@ PHP_FUNCTION(pg_send_execute) { zval *pgsql_link; pgsql_link_handle *link; - zval *pv_param_arr, *tmp; - int num_params = 0; + zval *pv_param_arr; + int num_params; char **params = NULL; char *stmtname; size_t stmtname_len; @@ -4236,27 +4217,9 @@ PHP_FUNCTION(pg_send_execute) "There are results on this connection. Call pg_get_result() until it returns FALSE"); } - num_params = zend_hash_num_elements(Z_ARRVAL_P(pv_param_arr)); - if (num_params > 0) { - int i = 0; - params = (char **)safe_emalloc(sizeof(char *), num_params, 0); - - ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(pv_param_arr), tmp) { - ZVAL_DEREF(tmp); - if (Z_TYPE_P(tmp) == IS_NULL) { - params[i] = NULL; - } else { - zend_string *tmp_str = zval_try_get_string(tmp); - if (UNEXPECTED(!tmp_str)) { - _php_pgsql_free_params(params, i); - return; - } - params[i] = estrndup(ZSTR_VAL(tmp_str), ZSTR_LEN(tmp_str)); - zend_string_release(tmp_str); - } - - i++; - } ZEND_HASH_FOREACH_END(); + params = php_pgsql_make_arguments(Z_ARRVAL_P(pv_param_arr), &num_params); + if (UNEXPECTED(!params)) { + RETURN_THROWS(); } if (PQsendQueryPrepared(pgsql, stmtname, num_params, (const char * const *)params, NULL, NULL, 0)) { diff --git a/ext/phar/dirstream.c b/ext/phar/dirstream.c index 81fa62c854dfd..f37599e7db117 100644 --- a/ext/phar/dirstream.c +++ b/ext/phar/dirstream.c @@ -188,8 +188,6 @@ static php_stream *phar_make_dirstream(const char *dir, size_t dirlen, const Has entry = safe_emalloc(keylen, 1, 1); memcpy(entry, ZSTR_VAL(str_key), keylen); entry[keylen] = '\0'; - - goto PHAR_ADD_ENTRY; } else { if (0 != memcmp(ZSTR_VAL(str_key), dir, dirlen)) { /* entry in directory not found */ @@ -199,28 +197,28 @@ static php_stream *phar_make_dirstream(const char *dir, size_t dirlen, const Has continue; } } - } - const char *save = ZSTR_VAL(str_key); - save += dirlen + 1; /* seek to just past the path separator */ + const char *save = ZSTR_VAL(str_key); + save += dirlen + 1; /* seek to just past the path separator */ - const char *has_slash = memchr(save, '/', keylen - dirlen - 1); - if (has_slash) { - /* is subdirectory */ - save -= dirlen + 1; - entry = safe_emalloc(has_slash - save + dirlen, 1, 1); - memcpy(entry, save + dirlen + 1, has_slash - save - dirlen - 1); - keylen = has_slash - save - dirlen - 1; - entry[keylen] = '\0'; - } else { - /* is file */ - save -= dirlen + 1; - entry = safe_emalloc(keylen - dirlen, 1, 1); - memcpy(entry, save + dirlen + 1, keylen - dirlen - 1); - entry[keylen - dirlen - 1] = '\0'; - keylen = keylen - dirlen - 1; + const char *has_slash = memchr(save, '/', keylen - dirlen - 1); + if (has_slash) { + /* is subdirectory */ + save -= dirlen + 1; + entry = safe_emalloc(has_slash - save + dirlen, 1, 1); + memcpy(entry, save + dirlen + 1, has_slash - save - dirlen - 1); + keylen = has_slash - save - dirlen - 1; + entry[keylen] = '\0'; + } else { + /* is file */ + save -= dirlen + 1; + entry = safe_emalloc(keylen - dirlen, 1, 1); + memcpy(entry, save + dirlen + 1, keylen - dirlen - 1); + entry[keylen - dirlen - 1] = '\0'; + keylen = keylen - dirlen - 1; + } } -PHAR_ADD_ENTRY: + if (keylen) { /** * Add an empty element to avoid duplicates @@ -450,7 +448,6 @@ int phar_wrapper_mkdir(php_stream_wrapper *wrapper, const char *url_from, int mo if (NULL == zend_hash_add_mem(&phar->manifest, entry.filename, &entry, sizeof(phar_entry_info))) { php_stream_wrapper_log_error(wrapper, options, "phar error: cannot create directory \"%s\" in phar \"%s\", adding to manifest failed", ZSTR_VAL(entry.filename), phar->fname); - efree(error); zend_string_efree(entry.filename); return 0; } diff --git a/ext/phar/phar_object.c b/ext/phar/phar_object.c index 9c09417e077b4..fba332aa21a0b 100644 --- a/ext/phar/phar_object.c +++ b/ext/phar/phar_object.c @@ -4315,10 +4315,7 @@ PHP_METHOD(Phar, extractTo) } if (ZSTR_LEN(path_to) >= MAXPATHLEN) { - char *tmp = estrndup(ZSTR_VAL(path_to), 50); - /* truncate for error message */ - zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0, "Cannot extract to \"%s...\", destination directory is too long for filesystem", tmp); - efree(tmp); + zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0, "Cannot extract to \"%.50s...\", destination directory is too long for filesystem", ZSTR_VAL(path_to)); RETURN_THROWS(); } diff --git a/ext/phar/tests/openssl_sign_invalid_polyfill_return_value.phpt b/ext/phar/tests/openssl_sign_invalid_polyfill_return_value.phpt new file mode 100644 index 0000000000000..37c14188edf98 --- /dev/null +++ b/ext/phar/tests/openssl_sign_invalid_polyfill_return_value.phpt @@ -0,0 +1,34 @@ +--TEST-- +openssl_sign() polyfill with wrong return value +--EXTENSIONS-- +phar +--SKIPIF-- + +--INI-- +phar.require_hash=0 +--FILE-- +setSignatureAlgorithm(Phar::OPENSSL, "randomcrap"); +try { + $phar->addEmptyDir('blah'); +} catch (PharException $e) { + echo $e->getMessage(); +} + +?> +--CLEAN-- + +--EXPECTF-- +phar error: unable to write signature to tar-based phar: unable to write phar "%s" with requested openssl signature diff --git a/ext/phar/util.c b/ext/phar/util.c index 884e96fb979a6..60607006f6712 100644 --- a/ext/phar/util.c +++ b/ext/phar/util.c @@ -1464,8 +1464,10 @@ static zend_result phar_call_openssl_signverify(bool is_sign, php_stream *fp, ze *signature_len = Z_STRLEN(zp[1]); zval_ptr_dtor(&zp[1]); return SUCCESS; - case IS_FALSE: default: + zval_ptr_dtor(&retval); + ZEND_FALLTHROUGH; + case IS_FALSE: zval_ptr_dtor(&zp[1]); return FAILURE; } diff --git a/ext/phar/zip.c b/ext/phar/zip.c index dff893c221b94..5abbc49d3c2ce 100644 --- a/ext/phar/zip.c +++ b/ext/phar/zip.c @@ -234,7 +234,7 @@ zend_result phar_parse_zipfile(php_stream *fp, char *fname, size_t fname_len, ch uint16_t i; phar_archive_data *mydata = NULL; phar_entry_info entry = {0}; - char *p = buf, *ext, *actual_alias = NULL; + char *ext, *actual_alias = NULL; char *metadata = NULL; size = php_stream_tell(fp); @@ -261,58 +261,55 @@ zend_result phar_parse_zipfile(php_stream *fp, char *fname, size_t fname_len, ch return FAILURE; } - if ((p = phar_find_eocd(buf, size)) != NULL) { - memcpy((void *)&locator, (void *) p, sizeof(locator)); - if (PHAR_GET_16(locator.centraldisk) != 0 || PHAR_GET_16(locator.disknumber) != 0) { - /* split archives not handled */ - php_stream_close(fp); - if (error) { - spprintf(error, 4096, "phar error: split archives spanning multiple zips cannot be processed in zip-based phar \"%s\"", fname); - } - return FAILURE; + char *p = phar_find_eocd(buf, size); + if (!p) { + php_stream_close(fp); + if (error) { + spprintf(error, 4096, "phar error: end of central directory not found in zip-based phar \"%s\"", fname); } + return FAILURE; + } - if (PHAR_GET_16(locator.counthere) != PHAR_GET_16(locator.count)) { - if (error) { - spprintf(error, 4096, "phar error: corrupt zip archive, conflicting file count in end of central directory record in zip-based phar \"%s\"", fname); - } - php_stream_close(fp); - return FAILURE; + memcpy((void *)&locator, (void *) p, sizeof(locator)); + if (PHAR_GET_16(locator.centraldisk) != 0 || PHAR_GET_16(locator.disknumber) != 0) { + /* split archives not handled */ + php_stream_close(fp); + if (error) { + spprintf(error, 4096, "phar error: split archives spanning multiple zips cannot be processed in zip-based phar \"%s\"", fname); } + return FAILURE; + } - mydata = pecalloc(1, sizeof(phar_archive_data), PHAR_G(persist)); - mydata->is_persistent = PHAR_G(persist); + if (PHAR_GET_16(locator.counthere) != PHAR_GET_16(locator.count)) { + if (error) { + spprintf(error, 4096, "phar error: corrupt zip archive, conflicting file count in end of central directory record in zip-based phar \"%s\"", fname); + } + php_stream_close(fp); + return FAILURE; + } - /* read in archive comment, if any */ - if (PHAR_GET_16(locator.comment_len)) { + mydata = pecalloc(1, sizeof(phar_archive_data), PHAR_G(persist)); + mydata->is_persistent = PHAR_G(persist); - metadata = p + sizeof(locator); + /* read in archive comment, if any */ + if (PHAR_GET_16(locator.comment_len)) { - if (PHAR_GET_16(locator.comment_len) != size - (metadata - buf)) { - if (error) { - spprintf(error, 4096, "phar error: corrupt zip archive, zip file comment truncated in zip-based phar \"%s\"", fname); - } - php_stream_close(fp); - pefree(mydata, mydata->is_persistent); - return FAILURE; - } + metadata = p + sizeof(locator); - phar_parse_metadata_lazy(metadata, &mydata->metadata_tracker, PHAR_GET_16(locator.comment_len), mydata->is_persistent); - } else { - ZVAL_UNDEF(&mydata->metadata_tracker.val); + if (PHAR_GET_16(locator.comment_len) != size - (metadata - buf)) { + if (error) { + spprintf(error, 4096, "phar error: corrupt zip archive, zip file comment truncated in zip-based phar \"%s\"", fname); + } + php_stream_close(fp); + pefree(mydata, mydata->is_persistent); + return FAILURE; } - goto foundit; - } - - php_stream_close(fp); - - if (error) { - spprintf(error, 4096, "phar error: end of central directory not found in zip-based phar \"%s\"", fname); + phar_parse_metadata_lazy(metadata, &mydata->metadata_tracker, PHAR_GET_16(locator.comment_len), mydata->is_persistent); + } else { + ZVAL_UNDEF(&mydata->metadata_tracker.val); } - return FAILURE; -foundit: mydata->fname = pestrndup(fname, fname_len, mydata->is_persistent); #ifdef PHP_WIN32 phar_unixify_path_separators(mydata->fname, fname_len); @@ -1395,8 +1392,8 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(1, 4) void phar_zip_flush(phar_archive_data *phar, z zend_hash_apply_with_argument(&phar->manifest, phar_zip_changed_apply, (void *) &pass); phar_metadata_tracker_try_ensure_has_serialized_data(&phar->metadata_tracker, phar->is_persistent); - if (pass_error) { -has_pass_error: + if (pass_error + || FAILURE == phar_zip_applysignature(phar, &pass)) { spprintf(error, 4096, "phar zip flush of \"%s\" failed: %s", phar->fname, pass_error); efree(pass_error); nopasserror: @@ -1409,11 +1406,6 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(1, 4) void phar_zip_flush(phar_archive_data *phar, z return; } - if (FAILURE == phar_zip_applysignature(phar, &pass)) { - ZEND_ASSERT(pass_error != NULL); - goto has_pass_error; - } - /* save zip */ cdir_size = php_stream_tell(pass.centralfp); cdir_offset = php_stream_tell(pass.filefp);