Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 27 additions & 13 deletions docs/release-process.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ releases.
* php-8.4.0 (initial GA)
* php-8.4.9 (periodic bugfix or security release)

12. Ensure you are familiar with our procedure for [merging upwards][].

## Packaging a non-stable release (alpha/beta/RC)

Expand Down Expand Up @@ -321,7 +322,7 @@ slightly different steps. We'll call attention where the steps differ.
git add main/php_version.h Zend/zend.h configure.ac
git merge --continue
```

Be sure to set up a merge driver for the `NEWS` file as described in
the [Git FAQ page on the PHP wiki][gitfaq-mandatory].

Expand Down Expand Up @@ -543,25 +544,38 @@ slightly different steps. We'll call attention where the steps differ.

## Packaging a stable release

1. Check out the *patch-level version branch* for the release
(e.g., `PHP-8.1.7`).
1. Check out the *patch-level version branch* for the release.

```
git switch PHP-X.Y.Z
```

> 💬 **Hint** \
> You should have created this branch when packaging the non-stable release
> candidate for this version. If it is for a PHP-X.Y.0 version, then the branch
> was created as part of the final planned release candidate, PHP-X.Y.0RC4.

2. If a CVE commit needs to be merged to the release, have it committed to
the base branches and [merged upwards as usual][] (e.g. commit the CVE fix
to 7.2, merge to 7.3, 7.4, etc.). Then, you can cherry-pick it into the
patch-level version branch for this release.
2. If the upcoming release is a security release, you will have been informed
about it by the security release manager (SRM) by Tuesday noon (UTC).

Commit these changes and push the patch-level version branch. Ensure
that CI is still passing (see above).
> 💬 **Hint** \
> If you haven't set up a git remote for the security repo yet, do so:
> ```bash
> git remote add security git@github.com:php/php-src-security.git
> ```

> 💡 **Tip** \
> Don't forget to update `NEWS` manually in an extra commit to the
> patch-level version branch.
The SRM will provide you with a branch to merge in your
*patch-level version branch*.

```bash
git fetch security
git merge security/PHP-X.Y.Z-security
git push upstream PHP-X.Y.Z
```

> 💬 **Hint** \
> You do not need to merge this back into PHP-X.Y; the SRM will take care
> of it.

3. Run the `./scripts/dev/credits` script in the patch-level version branch,
and commit the changes in the credits files in `ext/standard`.
Expand Down Expand Up @@ -1182,7 +1196,7 @@ 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
[merged upwards as usual]: https://wiki.php.net/vcs/gitworkflow
[merging upwards]: 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
Expand Down
11 changes: 5 additions & 6 deletions ext/standard/ftp_fopen_wrapper.c
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,6 @@ static php_stream *php_ftp_fopen_connect(php_stream_wrapper *wrapper, const char
php_uri *resource = NULL;
int result, use_ssl, use_ssl_on_data = 0;
char tmp_line[512];
char *transport;
int transport_len;

const php_uri_parser *uri_parser = php_stream_context_get_uri_parser("ftp", context);
if (uri_parser == NULL) {
Expand All @@ -150,7 +148,8 @@ static php_stream *php_ftp_fopen_connect(php_stream_wrapper *wrapper, const char
if (resource->port == 0)
resource->port = 21;

transport_len = (int)spprintf(&transport, 0, "tcp://%s:" ZEND_LONG_FMT, ZSTR_VAL(resource->host), resource->port);
char *transport;
size_t transport_len = spprintf(&transport, 0, "tcp://%s:" ZEND_LONG_FMT, ZSTR_VAL(resource->host), resource->port);
stream = php_stream_xport_create(transport, transport_len, REPORT_ERRORS, STREAM_XPORT_CLIENT | STREAM_XPORT_CONNECT, NULL, NULL, context, NULL, NULL);
efree(transport);
if (stream == NULL) {
Expand Down Expand Up @@ -420,8 +419,6 @@ php_stream * php_stream_url_wrap_ftp(php_stream_wrapper *wrapper, const char *pa
zval *tmpzval;
bool allow_overwrite = false;
int8_t read_write = 0;
char *transport;
int transport_len;
zend_string *error_message = NULL;

tmp_line[0] = '\0';
Expand Down Expand Up @@ -554,7 +551,9 @@ php_stream * php_stream_url_wrap_ftp(php_stream_wrapper *wrapper, const char *pa
if (hoststart == NULL) {
hoststart = ZSTR_VAL(resource->host);
}
transport_len = (int)spprintf(&transport, 0, "tcp://%s:%d", hoststart, portno);

char *transport;
size_t transport_len = spprintf(&transport, 0, "tcp://%s:%d", hoststart, portno);
datastream = php_stream_xport_create(transport, transport_len, REPORT_ERRORS, STREAM_XPORT_CLIENT | STREAM_XPORT_CONNECT, NULL, NULL, context, &error_message, NULL);
efree(transport);
if (datastream == NULL) {
Expand Down
4 changes: 2 additions & 2 deletions ext/standard/http_fopen_wrapper.c
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ static zend_string *php_stream_http_response_headers_parse(php_stream_wrapper *w

/* Process folding headers if starting with a space or a tab. */
if (header_line && (*header_line == ' ' || *header_line == '\t')) {
char *http_folded_header_line = header_line;
const char *http_folded_header_line = header_line;
size_t http_folded_header_line_length = *header_line_length;
/* Remove the leading white spaces. */
while (*http_folded_header_line == ' ' || *http_folded_header_line == '\t') {
Expand All @@ -232,7 +232,7 @@ static zend_string *php_stream_http_response_headers_parse(php_stream_wrapper *w
char *last_header_value = memchr(last_header_line, ':', last_header_line_length);
if (last_header_value) {
/* Verify there is no space in header name */
char *last_header_name = last_header_line + 1;
const char *last_header_name = last_header_line + 1;
while (last_header_name < last_header_value) {
if (*last_header_name == ' ' || *last_header_name == '\t') {
header_info->error = true;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
--TEST--
unserialize_callback_func with partially deprecated callable string
--INI--
unserialize_callback_func=parent::my_unserialize
--FILE--
<?php

class TesterParent {
public static function my_unserialize($name) {
echo 'callback_called in ', __CLASS__ , PHP_EOL;
eval('class Foo {}');
}
}

class TesterChild extends TesterParent {
public static function my_unserialize($name) {
echo 'callback_called in ', __CLASS__ , PHP_EOL;
eval('class Foo {}');
}

public function unserialize(string $str) {
return unserialize($str);
}
}

$s = 'O:3:"FOO":0:{}';
try {
$o = unserialize($s);
var_dump($o);
} catch (Throwable $e) {
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
}

try {
$tester = new TesterChild();
$o = $tester->unserialize($s);
var_dump($o);
} catch (Throwable $e) {
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
}
echo "Done";

?>
--EXPECTF--
Error: Invalid callback parent::my_unserialize, cannot access "parent" when no class scope is active

Deprecated: Use of "parent" in callables is deprecated in %s on line %d
callback_called in TesterParent
object(Foo)#3 (0) {
}
Done
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
--TEST--
unserialize_callback_func with fully qualified name function
--INI--
unserialize_callback_func=\my_global_fn
--FILE--
<?php
function my_global_fn($name) {
echo "callback_called\n";
eval('class Foo {}');
}

$o = unserialize('O:3:"FOO":0:{}');

var_dump($o);

echo "Done";
?>
--EXPECT--
callback_called
object(Foo)#1 (0) {
}
Done
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
--TEST--
unserialize_callback_func with fully qualified named namespaced function
--INI--
unserialize_callback_func=\php\test\my_global_fn
--FILE--
<?php

namespace php\test {
function my_global_fn($name) {
echo "callback_called\n";
eval('class Foo {}');
}
}
namespace {
$o = unserialize('O:3:"FOO":0:{}');

var_dump($o);

echo "Done";
}
?>
--EXPECT--
callback_called
object(Foo)#1 (0) {
}
Done
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
--TEST--
unserialize_callback_func with function name containing null bytes
--FILE--
<?php

ini_set('unserialize_callback_func', "foo\0butno");

function foo(string $name) {
echo "callback_called\n";
eval('class Foo {}');
}

$s = 'O:3:"FOO":0:{}';
try {
$o = unserialize($s);
var_dump($o);
} catch (Throwable $e) {
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
}

echo "Done";
?>
--EXPECT--
Error: Invalid callback foo, function "foo" not found or invalid function name
Done
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
--TEST--
unserialize_callback_func with private non-static method
--INI--
unserialize_callback_func=Tester::my_unserialize
--FILE--
<?php

class Tester {
private function my_unserialize($name) {
echo "callback_called\n";
eval('class Foo {}');
}

public function unserialize(string $str) {
return unserialize($str);
}
}

$s = 'O:3:"FOO":0:{}';
try {
$o = unserialize($s);
var_dump($o);
} catch (Throwable $e) {
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
}

try {
$tester = new Tester();
$o = $tester->unserialize($s);
var_dump($o);
} catch (Throwable $e) {
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
}
echo "Done";

?>
--EXPECT--
Error: Invalid callback Tester::my_unserialize, non-static method Tester::my_unserialize() cannot be called statically
callback_called
object(Foo)#3 (0) {
}
Done
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
--TEST--
unserialize_callback_func with public non-static method
--INI--
unserialize_callback_func=Tester::my_unserialize
--FILE--
<?php

class Tester {
public function my_unserialize($name) {
echo "callback_called\n";
eval('class Foo {}');
}

public function unserialize(string $str) {
return unserialize($str);
}
}

$s = 'O:3:"FOO":0:{}';
try {
$o = unserialize($s);
var_dump($o);
} catch (Throwable $e) {
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
}

try {
$tester = new Tester();
$o = $tester->unserialize($s);
var_dump($o);
} catch (Throwable $e) {
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
}
echo "Done";

?>
--EXPECT--
Error: Invalid callback Tester::my_unserialize, non-static method Tester::my_unserialize() cannot be called statically
callback_called
object(Foo)#3 (0) {
}
Done
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
--TEST--
unserialize_callback_func with public static method
--INI--
unserialize_callback_func=Tester::my_unserialize
--FILE--
<?php

class Tester {
public static function my_unserialize($name) {
echo "callback_called\n";
eval('class Foo {}');
}
}

$o = unserialize('O:3:"FOO":0:{}');

var_dump($o);

echo "Done";

?>
--EXPECT--
callback_called
object(Foo)#1 (0) {
}
Done
Loading
Loading