Skip to content

Commit 001e278

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

File tree

4 files changed

+75
-14
lines changed

4 files changed

+75
-14
lines changed

Zend/zend_string.c

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

383-
ZEND_API bool ZEND_FASTCALL I_REPLACE_SONAME_FNNAME_ZU(NONE,zend_string_equal_val)(const zend_string *s1, const zend_string *s2)
383+
/* See GH-9068 */
384+
#if defined(__GNUC__) && (__GNUC__ >= 11 || defined(__clang__)) && __has_attribute(no_caller_saved_registers)
385+
# define NO_CALLER_SAVED_REGISTERS __attribute__((no_caller_saved_registers))
386+
# ifndef __clang__
387+
# pragma GCC push_options
388+
# pragma GCC target ("general-regs-only")
389+
# define POP_OPTIONS
390+
# endif
391+
#else
392+
# define NO_CALLER_SAVED_REGISTERS
393+
#endif
394+
395+
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)
384396
{
385397
return !memcmp(ZSTR_VAL(s1), ZSTR_VAL(s2), ZSTR_LEN(s1));
386398
}
387399

400+
#ifdef POP_OPTIONS
401+
# pragma GCC pop_options
402+
# undef POP_OPTIONS
403+
#endif
404+
388405
#if defined(__GNUC__) && defined(__i386__)
389406
ZEND_API bool ZEND_FASTCALL zend_string_equal_val(const zend_string *s1, const zend_string *s2)
390407
{

ext/spl/spl_array.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1000,7 +1000,8 @@ static zval *spl_array_it_get_current_data(zend_object_iterator *iter) /* {{{ */
10001000
zend_hash_get_current_key_ex(aht, &key, NULL, spl_array_get_pos_ptr(aht, object));
10011001
zend_class_entry *ce = Z_OBJCE(object->array);
10021002
zend_property_info *prop_info = zend_get_property_info(ce, key, true);
1003-
if (ZEND_TYPE_IS_SET(prop_info->type)) {
1003+
ZEND_ASSERT(prop_info != ZEND_WRONG_PROPERTY_INFO);
1004+
if (EXPECTED(prop_info != NULL) && ZEND_TYPE_IS_SET(prop_info->type)) {
10041005
if (prop_info->flags & ZEND_ACC_READONLY) {
10051006
zend_throw_error(NULL,
10061007
"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)