Skip to content

Commit 94520fa

Browse files
committed
Fix GH-17900 and GH-8084
Calling the constructor twice has no real world benefit. Block it to fix these two issues. We also clean up the constructor code a bit: 1) `in_ctor` implies `object` exists 2) We no longer need to deal with reusing internal data. Closes GH-17900. Closes GH-8084.
1 parent 67a349d commit 94520fa

File tree

3 files changed

+29
-11
lines changed

3 files changed

+29
-11
lines changed

ext/mysqli/mysqli_nonapi.c

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,12 @@ void mysqli_common_connect(INTERNAL_FUNCTION_PARAMETERS, bool is_real_connect, b
7272
}
7373
#endif
7474

75-
if (getThis() && !ZEND_NUM_ARGS() && in_ctor) {
75+
if (UNEXPECTED(in_ctor && (Z_MYSQLI_P(object))->ptr)) {
76+
zend_throw_error(NULL, "Cannot call constructor twice");
77+
return;
78+
}
79+
80+
if (in_ctor && !ZEND_NUM_ARGS()) {
7681
php_mysqli_init(INTERNAL_FUNCTION_PARAM_PASSTHRU, in_ctor);
7782
return;
7883
}
@@ -85,16 +90,13 @@ void mysqli_common_connect(INTERNAL_FUNCTION_PARAMETERS, bool is_real_connect, b
8590
}
8691

8792
if (object) {
93+
#if ZEND_DEBUG
8894
ZEND_ASSERT(instanceof_function(Z_OBJCE_P(object), mysqli_link_class_entry));
89-
mysqli_resource = (Z_MYSQLI_P(object))->ptr;
90-
if (mysqli_resource && mysqli_resource->ptr) {
91-
mysql = (MY_MYSQL*) mysqli_resource->ptr;
92-
}
93-
}
94-
if (!mysql) {
95-
mysql = (MY_MYSQL *) ecalloc(1, sizeof(MY_MYSQL));
96-
self_alloced = 1;
95+
#endif
96+
ZEND_ASSERT(!Z_MYSQLI_P(object)->ptr);
9797
}
98+
mysql = (MY_MYSQL *) ecalloc(1, sizeof(MY_MYSQL));
99+
self_alloced = 1;
98100
flags |= CLIENT_MULTI_RESULTS; /* needed for mysql_multi_query() */
99101
} else {
100102
/* We have flags too */

ext/mysqli/tests/gh17900.phpt

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
--TEST--
2+
GH-17900 (Assertion failure ext/mysqli/mysqli_prop.c)
3+
--EXTENSIONS--
4+
mysqli
5+
--FILE--
6+
<?php
7+
mysqli_report(MYSQLI_REPORT_OFF);
8+
$mysqli = new mysqli();
9+
try {
10+
$mysqli->__construct('doesnotexist');
11+
} catch (Error $e) {
12+
echo $e->getMessage(), "\n";
13+
}
14+
?>
15+
--EXPECT--
16+
Cannot call constructor twice

ext/mysqli/tests/mysqli_incomplete_initialization.phpt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ $mysqli->close();
1212

1313
?>
1414
--EXPECTF--
15-
Fatal error: Uncaught Error: mysqli object is not fully initialized in %s:%d
15+
Fatal error: Uncaught Error: Cannot call constructor twice in %s:%d
1616
Stack trace:
17-
#0 %s(%d): mysqli->close()
17+
#0 %s(%d): mysqli->__construct('doesnotexist')
1818
#1 {main}
1919
thrown in %s on line %d

0 commit comments

Comments
 (0)