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
6 changes: 6 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ PHP NEWS
. IntlDateFormatter::setTimeZone()/datefmt_set_timezone() throws an exception
with uninitialised classes or clone failure. (David Carlier)

- MySQLi:
. Fixed bugs GH-17900 and GH-8084 (calling mysqli::__construct twice).
(nielsdos)

- MySQLnd:
. Added mysqlnd.collect_memory_statistics to ini quick reference.
(hauk92)
Expand Down Expand Up @@ -141,6 +145,8 @@ PHP NEWS
. socket_getsockname/socket_create/socket_bind handled AF_PACKET family socket.
(David Carlier)
. Added IP_BINDANY for a socket to bind to any address. (David Carlier)
. Added support for ethernet frames data for socket_sendto/socket_recvfrom
for SOCK_RAW sockets. (David Carlier)

- Sodium:
. Fix overall theorical overflows on zend_string buffer allocations.
Expand Down
4 changes: 4 additions & 0 deletions UPGRADING
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ PHP 8.5 UPGRADE NOTES
. ldap_get_option() and ldap_set_option() now throw a ValueError when
passing an invalid option.

- MySQLi:
. Calling the mysqli constructor on an already-constructed object
is now no longer possible and throws an Error.

- PCNTL:
. pcntl_exec() now throws ValueErrors when entries of the $args parameter
contain null bytes.
Expand Down
35 changes: 35 additions & 0 deletions Zend/tests/attributes/deprecated/functions/gh17866.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
--TEST--
GH-17866 (zend_mm_heap corrupted error after upgrading from 8.4.3 to 8.4.4)
--FILE--
<?php

class Foo {
#[Deprecated("xyzzy")]
public function __invoke() {
echo "In __invoke\n";
}
}

$foo = new Foo;
$closure = Closure::fromCallable($foo);
$test = $closure->__invoke(...);

$rc = new ReflectionMethod($test, '__invoke');
var_dump($rc->getAttributes());
var_dump($rc->isDeprecated());

$test();

?>
--EXPECTF--
array(1) {
[0]=>
object(ReflectionAttribute)#%d (1) {
["name"]=>
string(10) "Deprecated"
}
}
bool(true)

Deprecated: Method Foo::__invoke() is deprecated, xyzzy in %s on line %d
In __invoke
14 changes: 14 additions & 0 deletions Zend/tests/property_hooks/abstract_prop_final.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
--TEST--
GH-17916: Abstract property cannot be marked as final
--FILE--
<?php

abstract class Foo {
final abstract public string $bar {
get;
}
}

?>
--EXPECTF--
Fatal error: Cannot use the final modifier on an abstract property in %s on line %d
2 changes: 1 addition & 1 deletion Zend/zend_closures.c
Original file line number Diff line number Diff line change
Expand Up @@ -469,7 +469,7 @@ ZEND_API zend_function *zend_get_closure_invoke_method(zend_object *object) /* {
zend_closure *closure = (zend_closure *)object;
zend_function *invoke = (zend_function*)emalloc(sizeof(zend_function));
const uint32_t keep_flags =
ZEND_ACC_RETURN_REFERENCE | ZEND_ACC_VARIADIC | ZEND_ACC_HAS_RETURN_TYPE;
ZEND_ACC_RETURN_REFERENCE | ZEND_ACC_VARIADIC | ZEND_ACC_HAS_RETURN_TYPE | ZEND_ACC_DEPRECATED;

invoke->common = closure->func.common;
/* We return ZEND_INTERNAL_FUNCTION, but arg_info representation is the
Expand Down
15 changes: 11 additions & 4 deletions Zend/zend_compile.c
Original file line number Diff line number Diff line change
Expand Up @@ -1031,10 +1031,17 @@ uint32_t zend_add_member_modifier(uint32_t flags, uint32_t new_flag, zend_modifi
"Multiple access type modifiers are not allowed", 0);
return 0;
}
if (target == ZEND_MODIFIER_TARGET_METHOD && (new_flags & ZEND_ACC_ABSTRACT) && (new_flags & ZEND_ACC_FINAL)) {
zend_throw_exception(zend_ce_compile_error,
"Cannot use the final modifier on an abstract method", 0);
return 0;
if ((new_flags & ZEND_ACC_ABSTRACT) && (new_flags & ZEND_ACC_FINAL)) {
if (target == ZEND_MODIFIER_TARGET_METHOD) {
zend_throw_exception(zend_ce_compile_error,
"Cannot use the final modifier on an abstract method", 0);
return 0;
}
if (target == ZEND_MODIFIER_TARGET_PROPERTY) {
zend_throw_exception(zend_ce_compile_error,
"Cannot use the final modifier on an abstract property", 0);
return 0;
}
}
if (target == ZEND_MODIFIER_TARGET_PROPERTY || target == ZEND_MODIFIER_TARGET_CPP) {
if ((flags & ZEND_ACC_PPP_SET_MASK) && (new_flag & ZEND_ACC_PPP_SET_MASK)) {
Expand Down
8 changes: 2 additions & 6 deletions Zend/zend_object_handlers.c
Original file line number Diff line number Diff line change
Expand Up @@ -1618,12 +1618,8 @@ ZEND_API zend_function *zend_get_call_trampoline_func(const zend_class_entry *ce
| ZEND_ACC_PUBLIC
| ZEND_ACC_VARIADIC
| (fbc->common.fn_flags & (ZEND_ACC_RETURN_REFERENCE|ZEND_ACC_ABSTRACT|ZEND_ACC_DEPRECATED));
if (fbc->common.attributes) {
func->attributes = fbc->common.attributes;
GC_TRY_ADDREF(func->attributes);
} else {
func->attributes = NULL;
}
/* Attributes outlive the trampoline because they are created by the compiler. */
func->attributes = fbc->common.attributes;
if (is_static) {
func->fn_flags |= ZEND_ACC_STATIC;
}
Expand Down
3 changes: 0 additions & 3 deletions Zend/zend_object_handlers.h
Original file line number Diff line number Diff line change
Expand Up @@ -341,9 +341,6 @@ ZEND_API bool ZEND_FASTCALL zend_asymmetric_property_has_set_access(const zend_p
} while (0)

#define zend_free_trampoline(func) do { \
if ((func)->common.attributes) { \
zend_array_release((func)->common.attributes); \
} \
if ((func) == &EG(trampoline)) { \
EG(trampoline).common.attributes = NULL; \
EG(trampoline).common.function_name = NULL; \
Expand Down
5 changes: 1 addition & 4 deletions ext/mysqli/mysqli_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -969,10 +969,6 @@ void php_mysqli_init(INTERNAL_FUNCTION_PARAMETERS, bool is_method)
MYSQLI_RESOURCE *mysqli_resource;
MY_MYSQL *mysql;

if (zend_parse_parameters_none() == FAILURE) {
RETURN_THROWS();
}

if (is_method && (Z_MYSQLI_P(getThis()))->ptr) {
return;
}
Expand Down Expand Up @@ -1004,6 +1000,7 @@ void php_mysqli_init(INTERNAL_FUNCTION_PARAMETERS, bool is_method)
/* {{{ Initialize mysqli and return a resource for use with mysql_real_connect */
PHP_FUNCTION(mysqli_init)
{
ZEND_PARSE_PARAMETERS_NONE();
php_mysqli_init(INTERNAL_FUNCTION_PARAM_PASSTHRU, false);
}
/* }}} */
Expand Down
15 changes: 14 additions & 1 deletion ext/mysqli/mysqli_nonapi.c
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,14 @@ void mysqli_common_connect(INTERNAL_FUNCTION_PARAMETERS, bool is_real_connect, b
}
#endif

if (getThis() && !ZEND_NUM_ARGS() && in_ctor) {
if (in_ctor && !ZEND_NUM_ARGS()) {
ZEND_PARSE_PARAMETERS_NONE();

if (UNEXPECTED(Z_MYSQLI_P(object)->ptr)) {
zend_throw_error(NULL, "Cannot call constructor twice");
return;
}

php_mysqli_init(INTERNAL_FUNCTION_PARAM_PASSTHRU, in_ctor);
return;
}
Expand All @@ -84,6 +91,11 @@ void mysqli_common_connect(INTERNAL_FUNCTION_PARAMETERS, bool is_real_connect, b
RETURN_THROWS();
}

if (UNEXPECTED(in_ctor && Z_MYSQLI_P(object)->ptr)) {
zend_throw_error(NULL, "Cannot call constructor twice");
return;
}

if (object) {
ZEND_ASSERT(instanceof_function(Z_OBJCE_P(object), mysqli_link_class_entry));
mysqli_resource = (Z_MYSQLI_P(object))->ptr;
Expand Down Expand Up @@ -325,6 +337,7 @@ PHP_METHOD(mysqli, __construct)
/* {{{ Initialize mysqli and return a resource for use with mysql_real_connect */
PHP_METHOD(mysqli, init)
{
ZEND_PARSE_PARAMETERS_NONE();
php_mysqli_init(INTERNAL_FUNCTION_PARAM_PASSTHRU, true);
}
/* }}} */
Expand Down
16 changes: 16 additions & 0 deletions ext/mysqli/tests/gh17900.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
--TEST--
GH-17900 (Assertion failure ext/mysqli/mysqli_prop.c)
--EXTENSIONS--
mysqli
--FILE--
<?php
mysqli_report(MYSQLI_REPORT_OFF);
$mysqli = new mysqli();
try {
$mysqli->__construct('doesnotexist');
} catch (Error $e) {
echo $e->getMessage(), "\n";
}
?>
--EXPECT--
Cannot call constructor twice
4 changes: 2 additions & 2 deletions ext/mysqli/tests/mysqli_incomplete_initialization.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ $mysqli->close();

?>
--EXPECTF--
Fatal error: Uncaught Error: mysqli object is not fully initialized in %s:%d
Fatal error: Uncaught Error: Cannot call constructor twice in %s:%d
Stack trace:
#0 %s(%d): mysqli->close()
#0 %s(%d): mysqli->__construct('doesnotexist')
#1 {main}
thrown in %s on line %d
2 changes: 1 addition & 1 deletion ext/opcache/jit/zend_jit_helpers.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ static zend_never_inline zend_op_array* ZEND_FASTCALL zend_jit_init_func_run_tim
{
void **run_time_cache;

if (op_array->type == ZEND_USER_FUNCTION && !RUN_TIME_CACHE(op_array)) {
if (!RUN_TIME_CACHE(op_array)) {
run_time_cache = zend_arena_alloc(&CG(arena), op_array->cache_size);
memset(run_time_cache, 0, op_array->cache_size);
ZEND_MAP_PTR_SET(op_array->run_time_cache, run_time_cache);
Expand Down
22 changes: 15 additions & 7 deletions ext/opcache/jit/zend_jit_ir.c
Original file line number Diff line number Diff line change
Expand Up @@ -8691,6 +8691,7 @@ static int zend_jit_push_call_frame(zend_jit_ctx *jit, const zend_op *opline, co
ir_STORE(jit_CALL(rx, This), IR_NULL);
} else {
ir_ref object_or_called_scope, call_info, call_info2, object, if_cond;
ir_ref if_cond_user = IR_UNUSED;

if (opline->op2_type == IS_CV) {
// JIT: GC_ADDREF(closure);
Expand Down Expand Up @@ -8728,15 +8729,22 @@ static int zend_jit_push_call_frame(zend_jit_ctx *jit, const zend_op *opline, co
// JIT: Z_PTR(call->This) = object_or_called_scope;
ir_STORE(jit_CALL(rx, This.value.ptr), object_or_called_scope);

// JIT: if (closure->func.op_array.run_time_cache__ptr)
if_cond = ir_IF(ir_LOAD_A(ir_ADD_OFFSET(func_ref, offsetof(zend_closure, func.op_array.run_time_cache__ptr))));
ir_IF_FALSE(if_cond);
if (!func) {
// JIT: if (closure->func.common.type & ZEND_USER_FUNCTION)
ir_ref type = ir_LOAD_U8(ir_ADD_OFFSET(func_ref, offsetof(zend_closure, func.type)));
if_cond_user = ir_IF(ir_AND_U8(type, ir_CONST_U8(ZEND_USER_FUNCTION)));
ir_IF_TRUE(if_cond_user);
}

// JIT: zend_jit_init_func_run_time_cache_helper(closure->func);
ir_CALL_1(IR_VOID, ir_CONST_FC_FUNC(zend_jit_init_func_run_time_cache_helper),
ir_ADD_OFFSET(func_ref, offsetof(zend_closure, func)));
if (!func || func->common.type == ZEND_USER_FUNCTION) {
// JIT: zend_jit_init_func_run_time_cache_helper(closure->func);
ir_CALL_1(IR_VOID, ir_CONST_FC_FUNC(zend_jit_init_func_run_time_cache_helper),
ir_ADD_OFFSET(func_ref, offsetof(zend_closure, func)));
}

ir_MERGE_WITH_EMPTY_TRUE(if_cond);
if (!func) {
ir_MERGE_WITH_EMPTY_FALSE(if_cond_user);
}
}

// JIT: ZEND_CALL_NUM_ARGS(call) = num_args;
Expand Down
2 changes: 1 addition & 1 deletion ext/sockets/config.m4
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ PHP_ARG_ENABLE([sockets],

if test "$PHP_SOCKETS" != "no"; then
AC_CHECK_FUNCS([hstrerror if_nametoindex if_indextoname sockatmark])
AC_CHECK_HEADERS([sys/sockio.h linux/filter.h linux/if_packet.h linux/if_ether.h])
AC_CHECK_HEADERS([sys/sockio.h linux/filter.h linux/if_packet.h linux/if_ether.h netinet/ether.h])
AC_DEFINE([HAVE_SOCKETS], [1],
[Define to 1 if the PHP extension 'sockets' is available.])

Expand Down
4 changes: 4 additions & 0 deletions ext/sockets/php_sockets.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,10 @@ typedef struct {

extern PHP_SOCKETS_API zend_class_entry *socket_ce;

#ifdef AF_PACKET
extern PHP_SOCKETS_API zend_class_entry *socket_ethinfo_ce;
#endif

static inline php_socket *socket_from_obj(zend_object *obj) {
return (php_socket *)((char *)(obj) - XtOffsetOf(php_socket, std));
}
Expand Down
Loading
Loading