Skip to content

Commit ddebe46

Browse files
committed
Merge branch 'PHP-8.2' into PHP-8.3
* PHP-8.2: ext/pdo: Fix various PDORow bugs
2 parents 7e938d2 + b4e272c commit ddebe46

File tree

4 files changed

+362
-141
lines changed

4 files changed

+362
-141
lines changed

NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ PHP NEWS
3030
. Fixed bug GH-11950 ([mysqlnd] Fixed not to set CR_MALFORMED_PACKET to error
3131
if CR_SERVER_GONE_ERROR is already set). (Saki Takamachi)
3232

33+
- PDO:
34+
. Fix various PDORow bugs. (Girgias)
35+
3336
- PGSQL:
3437
. Fixed bug GH-13354 (pg_execute/pg_send_query_params/pg_send_execute
3538
with null value passed by reference). (George Barbarosie)

ext/pdo/pdo_stmt.c

Lines changed: 97 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -2254,74 +2254,84 @@ zend_object_iterator *pdo_stmt_iter_get(zend_class_entry *ce, zval *object, int
22542254
/* }}} */
22552255

22562256
/* {{{ overloaded handlers for PDORow class (used by PDO_FETCH_LAZY) */
2257+
static zval *row_read_column_name(pdo_stmt_t *stmt, zend_string *name, zval *rv)
2258+
{
2259+
/* TODO: replace this with a hash of available column names to column numbers */
2260+
for (int colno = 0; colno < stmt->column_count; colno++) {
2261+
if (zend_string_equals(stmt->columns[colno].name, name)) {
2262+
fetch_value(stmt, rv, colno, NULL);
2263+
return rv;
2264+
}
2265+
}
2266+
return NULL;
2267+
}
2268+
2269+
static zval *row_read_column_number(pdo_stmt_t *stmt, zend_long column, zval *rv)
2270+
{
2271+
if (column >= 0 && column < stmt->column_count) {
2272+
fetch_value(stmt, rv, column, NULL);
2273+
return rv;
2274+
}
2275+
return NULL;
2276+
}
22572277

22582278
static zval *row_prop_read(zend_object *object, zend_string *name, int type, void **cache_slot, zval *rv)
22592279
{
22602280
pdo_row_t *row = (pdo_row_t *)object;
22612281
pdo_stmt_t *stmt = row->stmt;
2262-
int colno = -1;
22632282
zend_long lval;
2283+
zval *retval;
22642284
ZEND_ASSERT(stmt);
22652285

22662286
ZVAL_NULL(rv);
22672287
if (zend_string_equals_literal(name, "queryString")) {
22682288
return zend_std_read_property(&stmt->std, name, type, cache_slot, rv);
2269-
} else if (is_numeric_string(ZSTR_VAL(name), ZSTR_LEN(name), &lval, NULL, 0) == IS_LONG) {
2270-
if (lval >= 0 && lval < stmt->column_count) {
2271-
fetch_value(stmt, rv, lval, NULL);
2272-
}
2289+
} else if (is_numeric_str_function(name, &lval, /* dval */ NULL) == IS_LONG) {
2290+
retval = row_read_column_number(stmt, lval, rv);
22732291
} else {
2274-
/* TODO: replace this with a hash of available column names to column
2275-
* numbers */
2276-
for (colno = 0; colno < stmt->column_count; colno++) {
2277-
if (zend_string_equals(stmt->columns[colno].name, name)) {
2278-
fetch_value(stmt, rv, colno, NULL);
2279-
return rv;
2280-
}
2281-
}
2292+
retval = row_read_column_name(stmt, name, rv);
22822293
}
2283-
2284-
return rv;
2294+
if (UNEXPECTED(!retval)) {
2295+
// TODO throw an error on master
2296+
//if (type != BP_VAR_IS) {
2297+
// if (is_numeric) {
2298+
// zend_value_error("Invalid column index");
2299+
// } else {
2300+
// zend_throw_error(NULL, "No column named \"%s\" exists", ZSTR_VAL(name));
2301+
// }
2302+
//}
2303+
//return &EG(uninitialized_zval);
2304+
ZVAL_NULL(rv);
2305+
return rv;
2306+
}
2307+
return retval;
22852308
}
22862309

2287-
static zval *row_dim_read(zend_object *object, zval *member, int type, zval *rv)
2310+
static zval *row_dim_read(zend_object *object, zval *offset, int type, zval *rv)
22882311
{
2289-
pdo_row_t *row = (pdo_row_t *)object;
2290-
pdo_stmt_t *stmt = row->stmt;
2291-
int colno = -1;
2292-
zend_long lval;
2293-
ZEND_ASSERT(stmt);
2312+
if (UNEXPECTED(!offset)) {
2313+
zend_throw_error(NULL, "Cannot append to PDORow offset");
2314+
return NULL;
2315+
}
2316+
if (Z_TYPE_P(offset) == IS_LONG) {
2317+
pdo_row_t *row = (pdo_row_t *)object;
2318+
pdo_stmt_t *stmt = row->stmt;
2319+
ZEND_ASSERT(stmt);
22942320

2295-
ZVAL_NULL(rv);
2296-
if (Z_TYPE_P(member) == IS_LONG) {
2297-
if (Z_LVAL_P(member) >= 0 && Z_LVAL_P(member) < stmt->column_count) {
2298-
fetch_value(stmt, rv, Z_LVAL_P(member), NULL);
2299-
}
2300-
} else if (Z_TYPE_P(member) == IS_STRING
2301-
&& is_numeric_string(Z_STRVAL_P(member), Z_STRLEN_P(member), &lval, NULL, 0) == IS_LONG) {
2302-
if (lval >= 0 && lval < stmt->column_count) {
2303-
fetch_value(stmt, rv, lval, NULL);
2321+
ZVAL_NULL(rv);
2322+
if (Z_LVAL_P(offset) >= 0 && Z_LVAL_P(offset) < stmt->column_count) {
2323+
fetch_value(stmt, rv, Z_LVAL_P(offset), NULL);
23042324
}
2325+
return rv;
23052326
} else {
2306-
if (!try_convert_to_string(member)) {
2307-
return &EG(uninitialized_zval);
2308-
}
2309-
2310-
if (zend_string_equals_literal(Z_STR_P(member), "queryString")) {
2311-
return zend_std_read_property(&stmt->std, Z_STR_P(member), type, NULL, rv);
2312-
}
2313-
2314-
/* TODO: replace this with a hash of available column names to column
2315-
* numbers */
2316-
for (colno = 0; colno < stmt->column_count; colno++) {
2317-
if (zend_string_equals(stmt->columns[colno].name, Z_STR_P(member))) {
2318-
fetch_value(stmt, rv, colno, NULL);
2319-
return rv;
2320-
}
2327+
zend_string *member = zval_try_get_string(offset);
2328+
if (!member) {
2329+
return NULL;
23212330
}
2331+
zval *result = row_prop_read(object, member, type, NULL, rv);
2332+
zend_string_release_ex(member, false);
2333+
return result;
23222334
}
2323-
2324-
return rv;
23252335
}
23262336

23272337
static zval *row_prop_write(zend_object *object, zend_string *name, zval *value, void **cache_slot)
@@ -2332,75 +2342,67 @@ static zval *row_prop_write(zend_object *object, zend_string *name, zval *value,
23322342

23332343
static void row_dim_write(zend_object *object, zval *member, zval *value)
23342344
{
2335-
zend_throw_error(NULL, "Cannot write to PDORow offset");
2345+
if (!member) {
2346+
zend_throw_error(NULL, "Cannot append to PDORow offset");
2347+
} else {
2348+
zend_throw_error(NULL, "Cannot write to PDORow offset");
2349+
}
23362350
}
23372351

23382352
static int row_prop_exists(zend_object *object, zend_string *name, int check_empty, void **cache_slot)
23392353
{
23402354
pdo_row_t *row = (pdo_row_t *)object;
23412355
pdo_stmt_t *stmt = row->stmt;
2342-
int colno = -1;
23432356
zend_long lval;
2357+
zval tmp_val;
2358+
zval *retval = NULL;
23442359
ZEND_ASSERT(stmt);
23452360

2346-
if (is_numeric_string(ZSTR_VAL(name), ZSTR_LEN(name), &lval, NULL, 0) == IS_LONG) {
2347-
return lval >=0 && lval < stmt->column_count;
2361+
if (is_numeric_str_function(name, &lval, /* dval */ NULL) == IS_LONG) {
2362+
retval = row_read_column_number(stmt, lval, &tmp_val);
2363+
} else {
2364+
retval = row_read_column_name(stmt, name, &tmp_val);
23482365
}
23492366

2350-
/* TODO: replace this with a hash of available column names to column
2351-
* numbers */
2352-
for (colno = 0; colno < stmt->column_count; colno++) {
2353-
if (zend_string_equals(stmt->columns[colno].name, name)) {
2354-
int res;
2355-
zval val;
2356-
2357-
fetch_value(stmt, &val, colno, NULL);
2358-
res = check_empty ? i_zend_is_true(&val) : Z_TYPE(val) != IS_NULL;
2359-
zval_ptr_dtor_nogc(&val);
2360-
2361-
return res;
2362-
}
2367+
if (!retval) {
2368+
return false;
23632369
}
2364-
2365-
return 0;
2370+
ZEND_ASSERT(retval == &tmp_val);
2371+
int res = check_empty ? i_zend_is_true(retval) : Z_TYPE(tmp_val) != IS_NULL;
2372+
zval_ptr_dtor_nogc(retval);
2373+
return res;
23662374
}
23672375

2368-
static int row_dim_exists(zend_object *object, zval *member, int check_empty)
2376+
static int row_dim_exists(zend_object *object, zval *offset, int check_empty)
23692377
{
2370-
pdo_row_t *row = (pdo_row_t *)object;
2371-
pdo_stmt_t *stmt = row->stmt;
2372-
int colno = -1;
2373-
zend_long lval;
2374-
ZEND_ASSERT(stmt);
2378+
if (Z_TYPE_P(offset) == IS_LONG) {
2379+
pdo_row_t *row = (pdo_row_t *)object;
2380+
pdo_stmt_t *stmt = row->stmt;
2381+
ZEND_ASSERT(stmt);
2382+
zend_long column = Z_LVAL_P(offset);
23752383

2376-
if (Z_TYPE_P(member) == IS_LONG) {
2377-
return Z_LVAL_P(member) >= 0 && Z_LVAL_P(member) < stmt->column_count;
2378-
} else if (Z_TYPE_P(member) == IS_STRING) {
2379-
if (is_numeric_string(Z_STRVAL_P(member), Z_STRLEN_P(member), &lval, NULL, 0) == IS_LONG) {
2380-
return lval >=0 && lval < stmt->column_count;
2384+
if (!check_empty) {
2385+
return column >= 0 && column < stmt->column_count;
23812386
}
2387+
2388+
zval tmp_val;
2389+
zval *retval = row_read_column_number(stmt, column, &tmp_val);
2390+
if (!retval) {
2391+
return false;
2392+
}
2393+
ZEND_ASSERT(retval == &tmp_val);
2394+
int res = check_empty ? i_zend_is_true(retval) : Z_TYPE(tmp_val) != IS_NULL;
2395+
zval_ptr_dtor_nogc(retval);
2396+
return res;
23822397
} else {
2383-
if (!try_convert_to_string(member)) {
2398+
zend_string *member = zval_try_get_string(offset);
2399+
if (!member) {
23842400
return 0;
23852401
}
2402+
int result = row_prop_exists(object, member, check_empty, NULL);
2403+
zend_string_release_ex(member, false);
2404+
return result;
23862405
}
2387-
2388-
/* TODO: replace this with a hash of available column names to column
2389-
* numbers */
2390-
for (colno = 0; colno < stmt->column_count; colno++) {
2391-
if (zend_string_equals(stmt->columns[colno].name, Z_STR_P(member))) {
2392-
int res;
2393-
zval val;
2394-
2395-
fetch_value(stmt, &val, colno, NULL);
2396-
res = check_empty ? i_zend_is_true(&val) : Z_TYPE(val) != IS_NULL;
2397-
zval_ptr_dtor_nogc(&val);
2398-
2399-
return res;
2400-
}
2401-
}
2402-
2403-
return 0;
24042406
}
24052407

24062408
static void row_prop_delete(zend_object *object, zend_string *offset, void **cache_slot)

0 commit comments

Comments
 (0)