Skip to content

Commit b667939

Browse files
authored
ext/pdo: Fix zend_object std layout for _pdo_row_t (#17606)
As of PHP 7 [1] the `std` should be at the end of the struct instead of at the beginning. See GH-17598 for more UB related details. [1] https://www.npopov.com/2015/06/19/Internal-value-representation-in-PHP-7-part-2.html#objects-in-php-7
1 parent 0a14ab1 commit b667939

File tree

2 files changed

+12
-7
lines changed

2 files changed

+12
-7
lines changed

ext/pdo/pdo_stmt.c

+7-6
Original file line numberDiff line numberDiff line change
@@ -2267,7 +2267,7 @@ static zval *row_read_column_number(pdo_stmt_t *stmt, zend_long column, zval *rv
22672267

22682268
static zval *row_prop_read(zend_object *object, zend_string *name, int type, void **cache_slot, zval *rv)
22692269
{
2270-
pdo_row_t *row = (pdo_row_t *)object;
2270+
pdo_row_t *row = php_pdo_row_fetch_object(object);
22712271
pdo_stmt_t *stmt = row->stmt;
22722272
zend_long lval;
22732273
zval *retval;
@@ -2304,7 +2304,7 @@ static zval *row_dim_read(zend_object *object, zval *offset, int type, zval *rv)
23042304
return NULL;
23052305
}
23062306
if (Z_TYPE_P(offset) == IS_LONG) {
2307-
pdo_row_t *row = (pdo_row_t *)object;
2307+
pdo_row_t *row = php_pdo_row_fetch_object(object);
23082308
pdo_stmt_t *stmt = row->stmt;
23092309
ZEND_ASSERT(stmt);
23102310

@@ -2342,7 +2342,7 @@ static void row_dim_write(zend_object *object, zval *member, zval *value)
23422342
// todo: make row_prop_exists return bool as well
23432343
static int row_prop_exists(zend_object *object, zend_string *name, int check_empty, void **cache_slot)
23442344
{
2345-
pdo_row_t *row = (pdo_row_t *)object;
2345+
pdo_row_t *row = php_pdo_row_fetch_object(object);
23462346
pdo_stmt_t *stmt = row->stmt;
23472347
zend_long lval;
23482348
zval tmp_val;
@@ -2370,7 +2370,7 @@ static int row_prop_exists(zend_object *object, zend_string *name, int check_emp
23702370
static int row_dim_exists(zend_object *object, zval *offset, int check_empty)
23712371
{
23722372
if (Z_TYPE_P(offset) == IS_LONG) {
2373-
pdo_row_t *row = (pdo_row_t *)object;
2373+
pdo_row_t *row = php_pdo_row_fetch_object(object);
23742374
pdo_stmt_t *stmt = row->stmt;
23752375
ZEND_ASSERT(stmt);
23762376
zend_long column = Z_LVAL_P(offset);
@@ -2411,7 +2411,7 @@ static void row_dim_delete(zend_object *object, zval *offset)
24112411

24122412
static HashTable *row_get_properties_for(zend_object *object, zend_prop_purpose purpose)
24132413
{
2414-
pdo_row_t *row = (pdo_row_t *)object;
2414+
pdo_row_t *row = php_pdo_row_fetch_object(object);
24152415
pdo_stmt_t *stmt = row->stmt;
24162416
HashTable *props;
24172417
int i;
@@ -2453,7 +2453,7 @@ static zval *pdo_row_get_property_ptr_ptr(zend_object *object, zend_string *name
24532453

24542454
void pdo_row_free_storage(zend_object *std)
24552455
{
2456-
pdo_row_t *row = (pdo_row_t *)std;
2456+
pdo_row_t *row = php_pdo_row_fetch_object(std);
24572457
if (row->stmt) {
24582458
ZVAL_UNDEF(&row->stmt->lazy_object_ref);
24592459
OBJ_RELEASE(&row->stmt->std);
@@ -2490,6 +2490,7 @@ void pdo_stmt_init(void)
24902490
pdo_row_ce->default_object_handlers = &pdo_row_object_handlers;
24912491

24922492
memcpy(&pdo_row_object_handlers, &std_object_handlers, sizeof(zend_object_handlers));
2493+
pdo_row_object_handlers.offset = XtOffsetOf(pdo_row_t, std);
24932494
pdo_row_object_handlers.free_obj = pdo_row_free_storage;
24942495
pdo_row_object_handlers.clone_obj = NULL;
24952496
pdo_row_object_handlers.get_property_ptr_ptr = pdo_row_get_property_ptr_ptr;

ext/pdo/php_pdo_driver.h

+5-1
Original file line numberDiff line numberDiff line change
@@ -643,10 +643,14 @@ static inline pdo_stmt_t *php_pdo_stmt_fetch_object(zend_object *obj) {
643643
#define Z_PDO_STMT_P(zv) php_pdo_stmt_fetch_object(Z_OBJ_P((zv)))
644644

645645
struct _pdo_row_t {
646-
zend_object std;
647646
pdo_stmt_t *stmt;
647+
zend_object std;
648648
};
649649

650+
static inline pdo_row_t *php_pdo_row_fetch_object(zend_object *obj) {
651+
return (pdo_row_t *)((char*)(obj) - XtOffsetOf(pdo_row_t, std));
652+
}
653+
650654
struct _pdo_scanner_t {
651655
const char *ptr, *cur, *tok, *end;
652656
};

0 commit comments

Comments
 (0)