@@ -656,7 +656,7 @@ static bool pdo_call_fetch_object_constructor(zend_function *constructor, HashTa
656
656
};
657
657
658
658
zend_call_function (& fci , & fcc );
659
- bool failed = Z_TYPE (retval_constructor_call ) == IS_UNDEF ;
659
+ bool failed = Z_ISUNDEF (retval_constructor_call ); ;
660
660
zval_ptr_dtor (& retval_constructor_call );
661
661
662
662
return failed ;
@@ -755,11 +755,11 @@ static bool do_fetch(pdo_stmt_t *stmt, zval *return_value, enum pdo_fetch_type h
755
755
if (flags & PDO_FETCH_CLASSTYPE ) {
756
756
zval ce_name_from_column ;
757
757
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 */
758
761
if (Z_TYPE (ce_name_from_column ) == IS_STRING ) {
759
762
ce = zend_lookup_class (Z_STR (ce_name_from_column ));
760
- if (ce == NULL ) {
761
- ce = zend_standard_class_def ;
762
- }
763
763
}
764
764
/* Use default CE if present */
765
765
if (ce == NULL ) {
@@ -779,7 +779,7 @@ static bool do_fetch(pdo_stmt_t *stmt, zval *return_value, enum pdo_fetch_type h
779
779
ZEND_ASSERT (ce != NULL );
780
780
if (flags & PDO_FETCH_SERIALIZE ) {
781
781
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. */
783
783
pdo_raise_impl_error (stmt -> dbh , stmt , "HY000" , "cannot unserialize class" );
784
784
return false;
785
785
}
@@ -1071,30 +1071,22 @@ PHP_METHOD(PDOStatement, fetchObject)
1071
1071
old_ce = stmt -> fetch .cls .ce ;
1072
1072
old_ctor_args = stmt -> fetch .cls .ctor_args ;
1073
1073
stmt -> fetch .cls .ctor_args = NULL ;
1074
+ if (ce == NULL) {
1075
+ ce = zend_standard_class_def ;
1076
+ }
1074
1077
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 ();
1087
1081
}
1082
+ stmt -> fetch .cls .ce = ce ;
1083
+ stmt -> fetch .cls .ctor_args = ctor_args ;
1088
1084
1089
1085
if (!do_fetch (stmt , return_value , PDO_FETCH_CLASS , PDO_FETCH_ORI_NEXT , /* offset */ 0 , NULL )) {
1090
1086
PDO_HANDLE_STMT_ERR ();
1091
1087
RETVAL_FALSE ;
1092
1088
}
1093
1089
1094
- reset_old_ctor_args :
1095
- if (stmt -> fetch .cls .ctor_args != NULL ) {
1096
- zend_hash_release (stmt -> fetch .cls .ctor_args );
1097
- }
1098
1090
stmt -> fetch .cls .ce = old_ce ;
1099
1091
stmt -> fetch .cls .ctor_args = old_ctor_args ;
1100
1092
}
@@ -1149,7 +1141,6 @@ PHP_METHOD(PDOStatement, fetchAll)
1149
1141
zval * arg2 = NULL ;
1150
1142
zend_class_entry * old_ce ;
1151
1143
HashTable * old_ctor_args , * ctor_args = NULL ;
1152
- bool is_default_fetch_mode = false;
1153
1144
1154
1145
ZEND_PARSE_PARAMETERS_START (0 , 3 )
1155
1146
Z_PARAM_OPTIONAL
@@ -1171,31 +1162,34 @@ PHP_METHOD(PDOStatement, fetchAll)
1171
1162
1172
1163
/* TODO Would be good to reuse part of pdo_stmt_setup_fetch_mode() in some way */
1173
1164
switch (fetch_mode ) {
1174
- case PDO_FETCH_CLASS :
1165
+ case PDO_FETCH_CLASS : {
1175
1166
/* Figure out correct class */
1167
+ zend_class_entry * fetch_class = NULL ;
1176
1168
if (arg2 ) {
1177
1169
if (Z_TYPE_P (arg2 ) != IS_STRING ) {
1178
1170
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 () ;
1180
1172
}
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 ) {
1183
1175
zend_argument_type_error (2 , "must be a valid class" );
1184
- goto reset_old_ctor_args ;
1176
+ RETURN_THROWS () ;
1185
1177
}
1186
1178
} else {
1187
- stmt -> fetch . cls . ce = zend_standard_class_def ;
1179
+ fetch_class = zend_standard_class_def ;
1188
1180
}
1189
1181
1190
1182
if (ctor_args && zend_hash_num_elements (ctor_args ) > 0 ) {
1191
- if (! stmt -> fetch . cls . ce -> constructor ) {
1183
+ if (fetch_class -> constructor == NULL ) {
1192
1184
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 () ;
1194
1186
}
1195
- GC_TRY_ADDREF (ctor_args );
1196
1187
stmt -> fetch .cls .ctor_args = ctor_args ;
1197
1188
}
1189
+ stmt -> fetch .cls .ce = fetch_class ;
1190
+
1198
1191
break ;
1192
+ }
1199
1193
1200
1194
case PDO_FETCH_FUNC : /* Cannot be a default fetch mode */
1201
1195
if (ZEND_NUM_ARGS () != 2 ) {
@@ -1250,7 +1244,6 @@ PHP_METHOD(PDOStatement, fetchAll)
1250
1244
flags |= stmt -> default_fetch_type & PDO_FETCH_FLAGS ;
1251
1245
fetch_mode = stmt -> default_fetch_type & ~PDO_FETCH_FLAGS ;
1252
1246
how = fetch_mode | flags ;
1253
- is_default_fetch_mode = true;
1254
1247
}
1255
1248
1256
1249
PDO_STMT_CLEAR_ERR ();
@@ -1290,15 +1283,9 @@ PHP_METHOD(PDOStatement, fetchAll)
1290
1283
}
1291
1284
}
1292
1285
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 ;
1302
1289
1303
1290
PDO_HANDLE_STMT_ERR ();
1304
1291
}
@@ -1594,6 +1581,24 @@ PHP_METHOD(PDOStatement, getColumnMeta)
1594
1581
}
1595
1582
/* }}} */
1596
1583
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
+
1597
1602
/* {{{ Changes the default fetch mode for subsequent fetches (params have different meaning for different fetch modes) */
1598
1603
1599
1604
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
1604
1609
uint32_t constructor_arg_num = mode_arg_num + 2 ;
1605
1610
uint32_t total_num_args = mode_arg_num + variadic_num_args ;
1606
1611
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 );
1623
1613
1624
1614
stmt -> default_fetch_type = PDO_FETCH_BOTH ;
1625
1615
@@ -2031,16 +2021,7 @@ PDO_API void php_pdo_free_statement(pdo_stmt_t *stmt)
2031
2021
}
2032
2022
2033
2023
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 );
2044
2025
2045
2026
if (!Z_ISUNDEF (stmt -> database_object_handle )) {
2046
2027
zval_ptr_dtor (& stmt -> database_object_handle );
0 commit comments