Fix GH-8068: mysqli_fetch_object creates inaccessible properties

When fetching into objects, we need to create object style hash tables,
i.e. where numeric column names are stored as string keys instead of
integer keys.  Instead of the slightly more efficient alternative to
create the desired hash table in the first place, we go for the more
readable implementation and convert the array style hash table using
`zend_symtable_to_proptable()`.

Co-authored-by: Kamil Tekiela <tekiela246@gmail.com>

Closes GH-8189.
This commit is contained in:
Christoph M. Becker 2022-03-10 19:21:06 +01:00
parent 2b7431cf5b
commit ef29ddcc27
No known key found for this signature in database
GPG key ID: D66C9593118BCCB6
3 changed files with 34 additions and 3 deletions

4
NEWS
View file

@ -11,6 +11,10 @@ PHP NEWS
- Intl:
. Fixed bug GH-8142 (Compilation error on cygwin). (David Carlier)
- MySQLi:
. Fixed bug GH-8068 (mysqli_fetch_object creates inaccessible properties).
(cmb)
- Pcntl:
. Fixed bug GH-8142 (Compilation error on cygwin). (David Carlier)

View file

@ -1198,11 +1198,13 @@ void php_mysqli_fetch_into_hash(INTERNAL_FUNCTION_PARAMETERS, int override_flags
ZVAL_COPY_VALUE(&dataset, return_value);
object_init_ex(return_value, ce);
if (!ce->default_properties_count && !ce->__set) {
Z_OBJ_P(return_value)->properties = Z_ARR(dataset);
} else {
zend_merge_properties(return_value, Z_ARRVAL(dataset));
HashTable *prop_table = zend_symtable_to_proptable(Z_ARR(dataset));
zval_ptr_dtor(&dataset);
if (!ce->default_properties_count && !ce->__set) {
Z_OBJ_P(return_value)->properties = prop_table;
} else {
zend_merge_properties(return_value, prop_table);
zend_array_release(prop_table);
}
if (ce->constructor) {

View file

@ -0,0 +1,25 @@
--TEST--
GH-8068 (mysqli_fetch_object creates inaccessible properties)
--SKIPIF--
<?php
require_once 'skipif.inc';
require_once 'skipifconnectfailure.inc';
?>
--FILE--
<?php
require_once "connect.inc";
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$mysqli = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
$res = $mysqli->query('SELECT 42');
$obj = $res->fetch_object();
var_dump(
$obj,
$obj->{42}
);
?>
--EXPECT--
object(stdClass)#4 (1) {
["42"]=>
string(2) "42"
}
string(2) "42"