Skip to content

Commit 7553c69

Browse files
committed
Another pass making some failure states unconditional erros in PDO
Also make internal function return type more accurate to inform usage
1 parent a5cf828 commit 7553c69

File tree

3 files changed

+30
-39
lines changed

3 files changed

+30
-39
lines changed

ext/pdo/pdo_dbh.c

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
#include "zend_interfaces.h"
3535
#include "pdo_dbh_arginfo.h"
3636

37-
static int pdo_dbh_attribute_set(pdo_dbh_t *dbh, zend_long attr, zval *value);
37+
static zend_result pdo_dbh_attribute_set(pdo_dbh_t *dbh, zend_long attr, zval *value);
3838

3939
void pdo_throw_exception(unsigned int driver_errcode, char *driver_errmsg, pdo_error_type *pdo_error)
4040
{
@@ -405,6 +405,7 @@ PHP_METHOD(PDO, __construct)
405405
continue;
406406
}
407407
ZVAL_DEREF(attr_value);
408+
/* TODO: Check that this doesn't fail? */
408409
pdo_dbh_attribute_set(dbh, long_key, attr_value);
409410
} ZEND_HASH_FOREACH_END();
410411
}
@@ -434,6 +435,9 @@ static zval *pdo_stmt_instantiate(pdo_dbh_t *dbh, zval *object, zend_class_entry
434435
}
435436

436437
if (UNEXPECTED(object_init_ex(object, dbstmt_ce) != SUCCESS)) {
438+
if (EXPECTED(!EG(exception))) {
439+
zend_throw_error(NULL, "Cannot instantiate user-supplied statement class");
440+
}
437441
return NULL;
438442
}
439443

@@ -544,13 +548,8 @@ PHP_METHOD(PDO, prepare)
544548
ZVAL_COPY_VALUE(&ctor_args, &dbh->def_stmt_ctor_args);
545549
}
546550

547-
/* Need to check if pdo_stmt_instantiate() throws an exception unconditionally to see if can change the RETURN_FALSE; */
548551
if (!pdo_stmt_instantiate(dbh, return_value, dbstmt_ce, &ctor_args)) {
549-
if (EXPECTED(!EG(exception))) {
550-
zend_throw_error(NULL, "Cannot instantiate user-supplied statement class");
551-
}
552-
PDO_HANDLE_DBH_ERR();
553-
RETURN_FALSE;
552+
RETURN_THROWS();
554553
}
555554
stmt = Z_PDO_STMT_P(return_value);
556555

@@ -674,7 +673,7 @@ PHP_METHOD(PDO, inTransaction)
674673
}
675674
/* }}} */
676675

677-
static int pdo_dbh_attribute_set(pdo_dbh_t *dbh, zend_long attr, zval *value) /* {{{ */
676+
static zend_result pdo_dbh_attribute_set(pdo_dbh_t *dbh, zend_long attr, zval *value) /* {{{ */
678677
{
679678
zend_long lval;
680679

@@ -752,6 +751,7 @@ static int pdo_dbh_attribute_set(pdo_dbh_t *dbh, zend_long attr, zval *value) /*
752751
zval *item;
753752

754753
if (dbh->is_persistent) {
754+
/* TODO: ValueError/ PDOException? */
755755
pdo_raise_impl_error(dbh, NULL, "HY000",
756756
"PDO::ATTR_STATEMENT_CLASS cannot be used with persistent PDO instances"
757757
);
@@ -1070,10 +1070,7 @@ PHP_METHOD(PDO, query)
10701070
PDO_DBH_CLEAR_ERR();
10711071

10721072
if (!pdo_stmt_instantiate(dbh, return_value, dbh->def_stmt_ce, &dbh->def_stmt_ctor_args)) {
1073-
if (EXPECTED(!EG(exception))) {
1074-
pdo_raise_impl_error(dbh, NULL, "HY000", "failed to instantiate user supplied statement class");
1075-
}
1076-
return;
1073+
RETURN_THROWS();
10771074
}
10781075
stmt = Z_PDO_STMT_P(return_value);
10791076

ext/pdo/pdo_stmt.c

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
RETURN_THROWS(); \
4242
} \
4343

44-
static inline int rewrite_name_to_position(pdo_stmt_t *stmt, struct pdo_bound_param_data *param) /* {{{ */
44+
static inline bool rewrite_name_to_position(pdo_stmt_t *stmt, struct pdo_bound_param_data *param) /* {{{ */
4545
{
4646
if (stmt->bound_param_map) {
4747
/* rewriting :name to ? style.
@@ -90,9 +90,9 @@ static inline int rewrite_name_to_position(pdo_stmt_t *stmt, struct pdo_bound_pa
9090
/* }}} */
9191

9292
/* trigger callback hook for parameters */
93-
static int dispatch_param_event(pdo_stmt_t *stmt, enum pdo_param_event event_type) /* {{{ */
93+
static bool dispatch_param_event(pdo_stmt_t *stmt, enum pdo_param_event event_type) /* {{{ */
9494
{
95-
int ret = 1, is_param = 1;
95+
bool ret = 1, is_param = 1;
9696
struct pdo_bound_param_data *param;
9797
HashTable *ht;
9898

@@ -212,7 +212,7 @@ static void param_dtor(zval *el) /* {{{ */
212212
}
213213
/* }}} */
214214

215-
static int really_register_bound_param(struct pdo_bound_param_data *param, pdo_stmt_t *stmt, int is_param) /* {{{ */
215+
static bool really_register_bound_param(struct pdo_bound_param_data *param, pdo_stmt_t *stmt, bool is_param) /* {{{ */
216216
{
217217
HashTable *hash;
218218
zval *parameter;
@@ -381,12 +381,7 @@ PHP_METHOD(PDOStatement, execute)
381381
param.paramno = -1;
382382
} else {
383383
/* we're okay to be zero based here */
384-
/* num_index is unsignend
385-
if (num_index < 0) {
386-
pdo_raise_impl_error(stmt->dbh, stmt, "HY093", NULL);
387-
RETURN_FALSE;
388-
}
389-
*/
384+
/* num_index is unsignend */
390385
param.paramno = num_index;
391386
}
392387

@@ -601,7 +596,7 @@ static inline void fetch_value(pdo_stmt_t *stmt, zval *dest, int colno, int *typ
601596
}
602597
/* }}} */
603598

604-
static int do_fetch_common(pdo_stmt_t *stmt, enum pdo_fetch_orientation ori, zend_long offset) /* {{{ */
599+
static bool do_fetch_common(pdo_stmt_t *stmt, enum pdo_fetch_orientation ori, zend_long offset) /* {{{ */
605600
{
606601
if (!stmt->executed) {
607602
return 0;
@@ -652,7 +647,7 @@ static int do_fetch_common(pdo_stmt_t *stmt, enum pdo_fetch_orientation ori, zen
652647
}
653648
/* }}} */
654649

655-
static int do_fetch_class_prepare(pdo_stmt_t *stmt) /* {{{ */
650+
static bool do_fetch_class_prepare(pdo_stmt_t *stmt) /* {{{ */
656651
{
657652
zend_class_entry *ce = stmt->fetch.cls.ce;
658653
zend_fcall_info *fci = &stmt->fetch.cls.fci;
@@ -677,16 +672,15 @@ static int do_fetch_class_prepare(pdo_stmt_t *stmt) /* {{{ */
677672
fcc->called_scope = ce;
678673
return 1;
679674
} else if (!Z_ISUNDEF(stmt->fetch.cls.ctor_args)) {
680-
/* TODO Error? */
681-
pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "user-supplied class does not have a constructor, use NULL for the ctor_params parameter, or simply omit it");
675+
zend_throw_error(NULL, "User-supplied statement does not accept constructor arguments");
682676
return 0;
683677
} else {
684678
return 1; /* no ctor no args is also ok */
685679
}
686680
}
687681
/* }}} */
688682

689-
static int make_callable_ex(pdo_stmt_t *stmt, zval *callable, zend_fcall_info * fci, zend_fcall_info_cache * fcc, int num_args) /* {{{ */
683+
static bool make_callable_ex(pdo_stmt_t *stmt, zval *callable, zend_fcall_info * fci, zend_fcall_info_cache * fcc, int num_args) /* {{{ */
690684
{
691685
char *is_callable_error = NULL;
692686

@@ -809,6 +803,7 @@ static bool do_fetch(pdo_stmt_t *stmt, zval *return_value, enum pdo_fetch_type h
809803

810804
case PDO_FETCH_KEY_PAIR:
811805
if (stmt->column_count != 2) {
806+
/* TODO: Error? */
812807
pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "PDO::FETCH_KEY_PAIR fetch mode requires the result set to contain exactly 2 columns.");
813808
return 0;
814809
}
@@ -904,6 +899,7 @@ static bool do_fetch(pdo_stmt_t *stmt, zval *return_value, enum pdo_fetch_type h
904899
break;
905900

906901
case PDO_FETCH_INTO:
902+
/* TODO: Make this an assertion and ensure this is true higher up? */
907903
if (Z_ISUNDEF(stmt->fetch.into)) {
908904
/* TODO ArgumentCountError? */
909905
pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "No fetch-into object specified.");
@@ -919,6 +915,7 @@ static bool do_fetch(pdo_stmt_t *stmt, zval *return_value, enum pdo_fetch_type h
919915
break;
920916

921917
case PDO_FETCH_FUNC:
918+
/* TODO: Make this an assertion and ensure this is true higher up? */
922919
if (Z_ISUNDEF(stmt->fetch.func.function)) {
923920
/* TODO ArgumentCountError? */
924921
pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "No fetch function specified");
@@ -1633,7 +1630,7 @@ PHP_METHOD(PDOStatement, setAttribute)
16331630

16341631
/* {{{ Get an attribute */
16351632

1636-
static int generic_stmt_attr_get(pdo_stmt_t *stmt, zval *return_value, zend_long attr)
1633+
static bool generic_stmt_attr_get(pdo_stmt_t *stmt, zval *return_value, zend_long attr)
16371634
{
16381635
switch (attr) {
16391636
case PDO_ATTR_EMULATE_PREPARES:

ext/pdo_mysql/tests/pdo_mysql_attr_statement_class.phpt

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -114,13 +114,15 @@ $db = MySQLPDOTest::factory();
114114
// Yes, this is a fatal error and I want it to fail.
115115
abstract class mystatement6 extends mystatement5 {
116116
}
117-
if (true !== ($tmp = $db->setAttribute(PDO::ATTR_STATEMENT_CLASS, array('mystatement6', array('mystatement6')))))
118-
printf("[011] Expecting boolean/true got %s\n", var_export($tmp, true));
119-
$stmt = $db->query('SELECT id, label FROM test ORDER BY id ASC LIMIT 1');
117+
try {
118+
$db->setAttribute(PDO::ATTR_STATEMENT_CLASS, ['mystatement6', ['mystatement6']]);
119+
$stmt = $db->query('SELECT id, label FROM test ORDER BY id ASC LIMIT 1');
120+
} catch (\Error $e) {
121+
echo get_class($e), ': ', $e->getMessage(), \PHP_EOL;
122+
}
120123

121-
print "done!";
122124
?>
123-
--EXPECTF--
125+
--EXPECT--
124126
array(1) {
125127
[0]=>
126128
string(12) "PDOStatement"
@@ -157,9 +159,4 @@ array(1) {
157159
string(1) "a"
158160
}
159161
}
160-
161-
Fatal error: Uncaught Error: Cannot instantiate abstract class mystatement6 in %s:%d
162-
Stack trace:
163-
#0 %s(%d): PDO->query('SELECT id, labe...')
164-
#1 {main}
165-
thrown in %s on line %d
162+
Error: Cannot instantiate abstract class mystatement6

0 commit comments

Comments
 (0)