Skip to content

Commit ab3f584

Browse files
committed
Merge branch 'PHP-8.1' into PHP-8.2
* PHP-8.1: Fix GH-11178: Segmentation fault in spl_array_it_get_current_data (PHP 8.1.18) Fix GH-11175 and GH-11177: Stream socket timeout undefined behaviour Fix GH-9068: Conditional jump or move depends on uninitialised value(s)
2 parents 81b2d2e + 81e50b4 commit ab3f584

File tree

5 files changed

+86
-14
lines changed

5 files changed

+86
-14
lines changed

NEWS

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ PHP NEWS
55
- Core:
66
. Fixed bug GH-11152 (Unable to alias namespaces containing reserved class
77
names). (ilutov)
8+
. Fixed bug GH-9068 (Conditional jump or move depends on uninitialised
9+
value(s)). (nielsdos)
810

911
- Opcache:
1012
. Fixed bug GH-11134 (Incorrect match default branch optimization). (ilutov)
@@ -13,10 +15,19 @@ PHP NEWS
1315
- PGSQL:
1416
. Fixed parameter parsing of pg_lo_export(). (kocsismate)
1517

18+
- SPL:
19+
. Fixed bug GH-11178 (Segmentation fault in spl_array_it_get_current_data
20+
(PHP 8.1.18)). (nielsdos)
21+
1622
- Standard:
1723
. Fixed bug GH-11138 (move_uploaded_file() emits open_basedir warning for
1824
source file). (ilutov)
1925

26+
- Streams:
27+
. Fixed bug GH-11175 (Stream Socket Timeout). (nielsdos)
28+
. Fixed bug GH-11177 (ASAN UndefinedBehaviorSanitizer when timeout = -1
29+
passed to stream_socket_accept/stream_socket_client). (nielsdos)
30+
2031
11 May 2023, PHP 8.2.6
2132

2233
- Core:

Zend/zend_string.c

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -370,11 +370,28 @@ ZEND_API void zend_interned_strings_switch_storage(bool request)
370370
# define I_REPLACE_SONAME_FNNAME_ZU(soname, fnname) _vgr00000ZU_ ## soname ## _ ## fnname
371371
#endif
372372

373-
ZEND_API bool ZEND_FASTCALL I_REPLACE_SONAME_FNNAME_ZU(NONE,zend_string_equal_val)(const zend_string *s1, const zend_string *s2)
373+
/* See GH-9068 */
374+
#if defined(__GNUC__) && (__GNUC__ >= 11 || defined(__clang__)) && __has_attribute(no_caller_saved_registers)
375+
# define NO_CALLER_SAVED_REGISTERS __attribute__((no_caller_saved_registers))
376+
# ifndef __clang__
377+
# pragma GCC push_options
378+
# pragma GCC target ("general-regs-only")
379+
# define POP_OPTIONS
380+
# endif
381+
#else
382+
# define NO_CALLER_SAVED_REGISTERS
383+
#endif
384+
385+
ZEND_API bool ZEND_FASTCALL NO_CALLER_SAVED_REGISTERS I_REPLACE_SONAME_FNNAME_ZU(NONE,zend_string_equal_val)(const zend_string *s1, const zend_string *s2)
374386
{
375387
return !memcmp(ZSTR_VAL(s1), ZSTR_VAL(s2), ZSTR_LEN(s1));
376388
}
377389

390+
#ifdef POP_OPTIONS
391+
# pragma GCC pop_options
392+
# undef POP_OPTIONS
393+
#endif
394+
378395
#if defined(__GNUC__) && defined(__i386__)
379396
ZEND_API bool ZEND_FASTCALL zend_string_equal_val(const zend_string *s1, const zend_string *s2)
380397
{

ext/spl/spl_array.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -989,7 +989,8 @@ static zval *spl_array_it_get_current_data(zend_object_iterator *iter) /* {{{ */
989989
zend_hash_get_current_key_ex(aht, &key, NULL, spl_array_get_pos_ptr(aht, object));
990990
zend_class_entry *ce = Z_OBJCE(object->array);
991991
zend_property_info *prop_info = zend_get_property_info(ce, key, true);
992-
if (ZEND_TYPE_IS_SET(prop_info->type)) {
992+
ZEND_ASSERT(prop_info != ZEND_WRONG_PROPERTY_INFO);
993+
if (EXPECTED(prop_info != NULL) && ZEND_TYPE_IS_SET(prop_info->type)) {
993994
if (prop_info->flags & ZEND_ACC_READONLY) {
994995
zend_throw_error(NULL,
995996
"Cannot acquire reference to readonly property %s::$%s",

ext/spl/tests/gh11178.phpt

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
--TEST--
2+
GH-11178 (Segmentation fault in spl_array_it_get_current_data (PHP 8.1.18))
3+
--FILE--
4+
<?php
5+
#[AllowDynamicProperties]
6+
class A implements IteratorAggregate {
7+
function __construct() {
8+
$this->{'x'} = 1;
9+
}
10+
11+
function getIterator(): Traversable {
12+
return new ArrayIterator($this);
13+
}
14+
}
15+
16+
$obj = new A;
17+
18+
foreach ($obj as $k => &$v) {
19+
$v = 3;
20+
}
21+
22+
var_dump($obj);
23+
?>
24+
--EXPECT--
25+
object(A)#1 (1) {
26+
["x"]=>
27+
&int(3)
28+
}

ext/standard/streamsfuncs.c

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,13 @@
3333
#ifndef PHP_WIN32
3434
#define php_select(m, r, w, e, t) select(m, r, w, e, t)
3535
typedef unsigned long long php_timeout_ull;
36+
#define PHP_TIMEOUT_ULL_MAX ULLONG_MAX
3637
#else
3738
#include "win32/select.h"
3839
#include "win32/sockets.h"
3940
#include "win32/console.h"
4041
typedef unsigned __int64 php_timeout_ull;
42+
#define PHP_TIMEOUT_ULL_MAX UINT64_MAX
4143
#endif
4244

4345
#define GET_CTX_OPT(stream, wrapper, name, val) (PHP_STREAM_CONTEXT(stream) && NULL != (val = php_stream_context_get_option(PHP_STREAM_CONTEXT(stream), wrapper, name)))
@@ -134,14 +136,21 @@ PHP_FUNCTION(stream_socket_client)
134136
}
135137

136138
/* prepare the timeout value for use */
137-
conv = (php_timeout_ull) (timeout * 1000000.0);
139+
struct timeval *tv_pointer;
140+
if (timeout < 0.0 || timeout >= (double) PHP_TIMEOUT_ULL_MAX / 1000000.0) {
141+
tv_pointer = NULL;
142+
} else {
143+
conv = (php_timeout_ull) (timeout * 1000000.0);
138144
#ifdef PHP_WIN32
139-
tv.tv_sec = (long)(conv / 1000000);
140-
tv.tv_usec =(long)(conv % 1000000);
145+
tv.tv_sec = (long)(conv / 1000000);
146+
tv.tv_usec = (long)(conv % 1000000);
141147
#else
142-
tv.tv_sec = conv / 1000000;
143-
tv.tv_usec = conv % 1000000;
148+
tv.tv_sec = conv / 1000000;
149+
tv.tv_usec = conv % 1000000;
144150
#endif
151+
tv_pointer = &tv;
152+
}
153+
145154
if (zerrno) {
146155
ZEND_TRY_ASSIGN_REF_LONG(zerrno, 0);
147156
}
@@ -152,7 +161,7 @@ PHP_FUNCTION(stream_socket_client)
152161
stream = php_stream_xport_create(ZSTR_VAL(host), ZSTR_LEN(host), REPORT_ERRORS,
153162
STREAM_XPORT_CLIENT | (flags & PHP_STREAM_CLIENT_CONNECT ? STREAM_XPORT_CONNECT : 0) |
154163
(flags & PHP_STREAM_CLIENT_ASYNC_CONNECT ? STREAM_XPORT_CONNECT_ASYNC : 0),
155-
hashkey, &tv, context, &errstr, &err);
164+
hashkey, tv_pointer, context, &errstr, &err);
156165

157166

158167
if (stream == NULL) {
@@ -275,19 +284,25 @@ PHP_FUNCTION(stream_socket_accept)
275284
php_stream_from_zval(stream, zstream);
276285

277286
/* prepare the timeout value for use */
278-
conv = (php_timeout_ull) (timeout * 1000000.0);
287+
struct timeval *tv_pointer;
288+
if (timeout < 0.0 || timeout >= (double) PHP_TIMEOUT_ULL_MAX / 1000000.0) {
289+
tv_pointer = NULL;
290+
} else {
291+
conv = (php_timeout_ull) (timeout * 1000000.0);
279292
#ifdef PHP_WIN32
280-
tv.tv_sec = (long)(conv / 1000000);
281-
tv.tv_usec = (long)(conv % 1000000);
293+
tv.tv_sec = (long)(conv / 1000000);
294+
tv.tv_usec = (long)(conv % 1000000);
282295
#else
283-
tv.tv_sec = conv / 1000000;
284-
tv.tv_usec = conv % 1000000;
296+
tv.tv_sec = conv / 1000000;
297+
tv.tv_usec = conv % 1000000;
285298
#endif
299+
tv_pointer = &tv;
300+
}
286301

287302
if (0 == php_stream_xport_accept(stream, &clistream,
288303
zpeername ? &peername : NULL,
289304
NULL, NULL,
290-
&tv, &errstr
305+
tv_pointer, &errstr
291306
) && clistream) {
292307

293308
if (peername) {

0 commit comments

Comments
 (0)