Skip to content

Commit 44b1d2b

Browse files
committed
First round of reviews
1 parent 5feb9aa commit 44b1d2b

File tree

2 files changed

+48
-71
lines changed

2 files changed

+48
-71
lines changed

ext/pdo/pdo_stmt.c

Lines changed: 48 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -656,7 +656,7 @@ static bool pdo_call_fetch_object_constructor(zend_function *constructor, HashTa
656656
};
657657

658658
zend_call_function(&fci, &fcc);
659-
bool failed = Z_TYPE(retval_constructor_call) == IS_UNDEF;
659+
bool failed = Z_ISUNDEF(retval_constructor_call);;
660660
zval_ptr_dtor(&retval_constructor_call);
661661

662662
return failed;
@@ -755,11 +755,11 @@ static bool do_fetch(pdo_stmt_t *stmt, zval *return_value, enum pdo_fetch_type h
755755
if (flags & PDO_FETCH_CLASSTYPE) {
756756
zval ce_name_from_column;
757757
fetch_value(stmt, &ce_name_from_column, column_index_to_fetch++, NULL);
758+
/* This used to use try_convert_to_string() which would silently support integers, floats, null
759+
* even if any such value could not generate a valid class name, as no class was found it would
760+
* then proceed to use stdClass */
758761
if (Z_TYPE(ce_name_from_column) == IS_STRING) {
759762
ce = zend_lookup_class(Z_STR(ce_name_from_column));
760-
if (ce == NULL) {
761-
ce = zend_standard_class_def;
762-
}
763763
}
764764
/* Use default CE if present */
765765
if (ce == NULL) {
@@ -779,7 +779,7 @@ static bool do_fetch(pdo_stmt_t *stmt, zval *return_value, enum pdo_fetch_type h
779779
ZEND_ASSERT(ce != NULL);
780780
if (flags & PDO_FETCH_SERIALIZE) {
781781
if (!ce->unserialize) {
782-
// TODO, should we mention the class? Considering this option is broken and deprecated...
782+
/* As this option is deprecated we do not bother to mention the class name. */
783783
pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "cannot unserialize class");
784784
return false;
785785
}
@@ -1071,30 +1071,22 @@ PHP_METHOD(PDOStatement, fetchObject)
10711071
old_ce = stmt->fetch.cls.ce;
10721072
old_ctor_args = stmt->fetch.cls.ctor_args;
10731073
stmt->fetch.cls.ctor_args = NULL;
1074+
if (ce == NULL) {
1075+
ce = zend_standard_class_def;
1076+
}
10741077

1075-
if (ce) {
1076-
stmt->fetch.cls.ce = ce;
1077-
if (ctor_args && zend_hash_num_elements(ctor_args)) {
1078-
if (ce->constructor == NULL) {
1079-
zend_argument_value_error(2, "must be empty when class provided in argument #1 ($class) does not have a constructor");
1080-
goto reset_old_ctor_args;
1081-
}
1082-
GC_TRY_ADDREF(ctor_args);
1083-
stmt->fetch.cls.ctor_args = ctor_args;
1084-
}
1085-
} else {
1086-
stmt->fetch.cls.ce = zend_standard_class_def;
1078+
if (ctor_args && zend_hash_num_elements(ctor_args) && ce->constructor == NULL) {
1079+
zend_argument_value_error(2, "must be empty when class provided in argument #1 ($class) does not have a constructor");
1080+
RETURN_THROWS();
10871081
}
1082+
stmt->fetch.cls.ce = ce;
1083+
stmt->fetch.cls.ctor_args = ctor_args;
10881084

10891085
if (!do_fetch(stmt, return_value, PDO_FETCH_CLASS, PDO_FETCH_ORI_NEXT, /* offset */ 0, NULL)) {
10901086
PDO_HANDLE_STMT_ERR();
10911087
RETVAL_FALSE;
10921088
}
10931089

1094-
reset_old_ctor_args:
1095-
if (stmt->fetch.cls.ctor_args != NULL) {
1096-
zend_hash_release(stmt->fetch.cls.ctor_args);
1097-
}
10981090
stmt->fetch.cls.ce = old_ce;
10991091
stmt->fetch.cls.ctor_args = old_ctor_args;
11001092
}
@@ -1149,7 +1141,6 @@ PHP_METHOD(PDOStatement, fetchAll)
11491141
zval *arg2 = NULL;
11501142
zend_class_entry *old_ce;
11511143
HashTable *old_ctor_args, *ctor_args = NULL;
1152-
bool is_default_fetch_mode = false;
11531144

11541145
ZEND_PARSE_PARAMETERS_START(0, 3)
11551146
Z_PARAM_OPTIONAL
@@ -1171,31 +1162,34 @@ PHP_METHOD(PDOStatement, fetchAll)
11711162

11721163
/* TODO Would be good to reuse part of pdo_stmt_setup_fetch_mode() in some way */
11731164
switch (fetch_mode) {
1174-
case PDO_FETCH_CLASS:
1165+
case PDO_FETCH_CLASS: {
11751166
/* Figure out correct class */
1167+
zend_class_entry *fetch_class = NULL;
11761168
if (arg2) {
11771169
if (Z_TYPE_P(arg2) != IS_STRING) {
11781170
zend_argument_type_error(2, "must be of type string, %s given", zend_zval_value_name(arg2));
1179-
goto reset_old_ctor_args;
1171+
RETURN_THROWS();
11801172
}
1181-
stmt->fetch.cls.ce = zend_lookup_class(Z_STR_P(arg2));
1182-
if (!stmt->fetch.cls.ce) {
1173+
fetch_class = zend_lookup_class(Z_STR_P(arg2));
1174+
if (fetch_class == NULL) {
11831175
zend_argument_type_error(2, "must be a valid class");
1184-
goto reset_old_ctor_args;
1176+
RETURN_THROWS();
11851177
}
11861178
} else {
1187-
stmt->fetch.cls.ce = zend_standard_class_def;
1179+
fetch_class = zend_standard_class_def;
11881180
}
11891181

11901182
if (ctor_args && zend_hash_num_elements(ctor_args) > 0) {
1191-
if (!stmt->fetch.cls.ce->constructor) {
1183+
if (fetch_class->constructor == NULL) {
11921184
zend_argument_value_error(3, "must be empty when class provided in argument #2 ($class) does not have a constructor");
1193-
goto reset_old_ctor_args;
1185+
RETURN_THROWS();
11941186
}
1195-
GC_TRY_ADDREF(ctor_args);
11961187
stmt->fetch.cls.ctor_args = ctor_args;
11971188
}
1189+
stmt->fetch.cls.ce = fetch_class;
1190+
11981191
break;
1192+
}
11991193

12001194
case PDO_FETCH_FUNC: /* Cannot be a default fetch mode */
12011195
if (ZEND_NUM_ARGS() != 2) {
@@ -1250,7 +1244,6 @@ PHP_METHOD(PDOStatement, fetchAll)
12501244
flags |= stmt->default_fetch_type & PDO_FETCH_FLAGS;
12511245
fetch_mode = stmt->default_fetch_type & ~PDO_FETCH_FLAGS;
12521246
how = fetch_mode | flags;
1253-
is_default_fetch_mode = true;
12541247
}
12551248

12561249
PDO_STMT_CLEAR_ERR();
@@ -1290,15 +1283,9 @@ PHP_METHOD(PDOStatement, fetchAll)
12901283
}
12911284
}
12921285

1293-
/* Restore defaults which were changed by PDO_FETCH_CLASS mode */
1294-
if (!is_default_fetch_mode && fetch_mode == PDO_FETCH_CLASS) {
1295-
reset_old_ctor_args:
1296-
if (stmt->fetch.cls.ctor_args != NULL) {
1297-
zend_hash_release(stmt->fetch.cls.ctor_args);
1298-
}
1299-
stmt->fetch.cls.ce = old_ce;
1300-
stmt->fetch.cls.ctor_args = old_ctor_args;
1301-
}
1286+
/* Restore defaults */
1287+
stmt->fetch.cls.ce = old_ce;
1288+
stmt->fetch.cls.ctor_args = old_ctor_args;
13021289

13031290
PDO_HANDLE_STMT_ERR();
13041291
}
@@ -1594,6 +1581,24 @@ PHP_METHOD(PDOStatement, getColumnMeta)
15941581
}
15951582
/* }}} */
15961583

1584+
void pdo_stmt_free_default_fetch_mode(pdo_stmt_t *stmt)
1585+
{
1586+
enum pdo_fetch_type default_fetch_mode = stmt->default_fetch_type & ~PDO_FETCH_FLAGS;
1587+
if (default_fetch_mode == PDO_FETCH_INTO) {
1588+
// Assert that we have an object to fetch into?
1589+
if (stmt->fetch.into) {
1590+
OBJ_RELEASE(stmt->fetch.into);
1591+
}
1592+
stmt->fetch.into = NULL;
1593+
} else if (default_fetch_mode == PDO_FETCH_CLASS) {
1594+
if (stmt->fetch.cls.ctor_args != NULL) {
1595+
zend_hash_release(stmt->fetch.cls.ctor_args);
1596+
}
1597+
stmt->fetch.cls.ctor_args = NULL;
1598+
stmt->fetch.cls.ce = NULL;
1599+
}
1600+
}
1601+
15971602
/* {{{ Changes the default fetch mode for subsequent fetches (params have different meaning for different fetch modes) */
15981603

15991604
bool pdo_stmt_setup_fetch_mode(pdo_stmt_t *stmt, zend_long mode, uint32_t mode_arg_num,
@@ -1604,22 +1609,7 @@ bool pdo_stmt_setup_fetch_mode(pdo_stmt_t *stmt, zend_long mode, uint32_t mode_a
16041609
uint32_t constructor_arg_num = mode_arg_num + 2;
16051610
uint32_t total_num_args = mode_arg_num + variadic_num_args;
16061611

1607-
switch (stmt->default_fetch_type) {
1608-
case PDO_FETCH_INTO:
1609-
if (stmt->fetch.into) {
1610-
OBJ_RELEASE(stmt->fetch.into);
1611-
stmt->fetch.into = NULL;
1612-
}
1613-
break;
1614-
case PDO_FETCH_CLASS:
1615-
if (stmt->fetch.cls.ctor_args != NULL) {
1616-
zend_hash_release(stmt->fetch.cls.ctor_args);
1617-
stmt->fetch.cls.ctor_args = NULL;
1618-
}
1619-
stmt->fetch.cls.ce = NULL;
1620-
default:
1621-
;
1622-
}
1612+
pdo_stmt_free_default_fetch_mode(stmt);
16231613

16241614
stmt->default_fetch_type = PDO_FETCH_BOTH;
16251615

@@ -2031,16 +2021,7 @@ PDO_API void php_pdo_free_statement(pdo_stmt_t *stmt)
20312021
}
20322022

20332023
pdo_stmt_reset_columns(stmt);
2034-
2035-
if (stmt->fetch.into && stmt->default_fetch_type == PDO_FETCH_INTO) {
2036-
OBJ_RELEASE(stmt->fetch.into);
2037-
stmt->fetch.into = NULL;
2038-
}
2039-
2040-
if (stmt->fetch.cls.ctor_args != NULL) {
2041-
zend_hash_release(stmt->fetch.cls.ctor_args);
2042-
stmt->fetch.cls.ctor_args = NULL;
2043-
}
2024+
pdo_stmt_free_default_fetch_mode(stmt);
20442025

20452026
if (!Z_ISUNDEF(stmt->database_object_handle)) {
20462027
zval_ptr_dtor(&stmt->database_object_handle);

ext/pdo/php_pdo_driver.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -612,14 +612,10 @@ struct _pdo_stmt_t {
612612
union {
613613
int column;
614614
struct {
615-
zval dummy; /* This exists due to alignment reasons with fetch.into */
616615
HashTable *ctor_args;
617616
zend_class_entry *ce;
618617
} cls;
619618
struct {
620-
zval dummy; /* This exists due to alignment reasons with fetch.into */
621-
HashTable *dummy_ht; /* This exists to prevent conflict with cls.ctor_args */
622-
zend_class_entry *dummy_ce; /* This exists to prevent conflict with cls.ce */
623619
zend_fcall_info_cache fcc;
624620
} func;
625621
zend_object *into;

0 commit comments

Comments
 (0)