Skip to content

Commit dbfbb15

Browse files
committed
Validate string is numeric for integer PDO attribute value
1 parent 900bed0 commit dbfbb15

File tree

2 files changed

+26
-19
lines changed

2 files changed

+26
-19
lines changed

ext/pdo/pdo_dbh.c

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -678,11 +678,20 @@ PHP_METHOD(PDO, inTransaction)
678678
}
679679
/* }}} */
680680

681-
/* TODO: Make distinction between numeric and non-numeric strings */
682-
#define PDO_LONG_PARAM_CHECK \
683-
if (Z_TYPE_P(value) != IS_LONG && Z_TYPE_P(value) != IS_STRING && Z_TYPE_P(value) != IS_FALSE && Z_TYPE_P(value) != IS_TRUE) { \
684-
zend_type_error("Attribute value must be of type int for selected attribute, %s given", zend_zval_type_name(value)); \
685-
return false; \
681+
#define PDO_GET_LONG_PARAM(zval) \
682+
switch (Z_TYPE_P(zval)) { \
683+
case IS_LONG: \
684+
case IS_TRUE: \
685+
case IS_FALSE: \
686+
lval = zval_get_long(zval); \
687+
break; \
688+
case IS_STRING: \
689+
if (IS_LONG == is_numeric_str_function(Z_STR_P(zval), &lval, NULL)) { \
690+
break; \
691+
} \
692+
/* fallthrough */ \
693+
default: \
694+
zend_type_error("Attribute value must be of type int for selected attribute, %s given", zend_zval_type_name(zval)); \
686695
} \
687696

688697
/* Return false on failure, true otherwise */
@@ -692,8 +701,7 @@ static bool pdo_dbh_attribute_set(pdo_dbh_t *dbh, zend_long attr, zval *value) /
692701

693702
switch (attr) {
694703
case PDO_ATTR_ERRMODE:
695-
PDO_LONG_PARAM_CHECK;
696-
lval = zval_get_long(value);
704+
PDO_GET_LONG_PARAM(value);
697705
switch (lval) {
698706
case PDO_ERRMODE_SILENT:
699707
case PDO_ERRMODE_WARNING:
@@ -707,8 +715,7 @@ static bool pdo_dbh_attribute_set(pdo_dbh_t *dbh, zend_long attr, zval *value) /
707715
return false;
708716

709717
case PDO_ATTR_CASE:
710-
PDO_LONG_PARAM_CHECK;
711-
lval = zval_get_long(value);
718+
PDO_GET_LONG_PARAM(value);
712719
switch (lval) {
713720
case PDO_CASE_NATURAL:
714721
case PDO_CASE_UPPER:
@@ -722,8 +729,8 @@ static bool pdo_dbh_attribute_set(pdo_dbh_t *dbh, zend_long attr, zval *value) /
722729
return false;
723730

724731
case PDO_ATTR_ORACLE_NULLS:
725-
PDO_LONG_PARAM_CHECK;
726-
dbh->oracle_nulls = zval_get_long(value);
732+
PDO_GET_LONG_PARAM(value);
733+
dbh->oracle_nulls = lval;
727734
return true;
728735

729736
case PDO_ATTR_DEFAULT_FETCH_MODE:
@@ -735,10 +742,10 @@ static bool pdo_dbh_attribute_set(pdo_dbh_t *dbh, zend_long attr, zval *value) /
735742
return false;
736743
}
737744
}
745+
lval = zval_get_long(value);
738746
} else {
739-
PDO_LONG_PARAM_CHECK;
747+
PDO_GET_LONG_PARAM(value);
740748
}
741-
lval = zval_get_long(value);
742749
if (lval == PDO_FETCH_USE_DEFAULT) {
743750
zend_value_error("Fetch mode must be a bitmask of PDO::FETCH_* constants");
744751
return false;
@@ -747,8 +754,8 @@ static bool pdo_dbh_attribute_set(pdo_dbh_t *dbh, zend_long attr, zval *value) /
747754
return true;
748755

749756
case PDO_ATTR_STRINGIFY_FETCHES:
750-
PDO_LONG_PARAM_CHECK;
751-
dbh->stringify = zval_get_long(value) ? 1 : 0;
757+
PDO_GET_LONG_PARAM(value);
758+
dbh->stringify = lval ? 1 : 0;
752759
return true;
753760

754761
case PDO_ATTR_STATEMENT_CLASS: {

ext/pdo/tests/bug_44159.phpt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,12 @@ foreach ($attrs as $attr) {
2424
echo get_class($e), ': ', $e->getMessage(), \PHP_EOL;
2525
}
2626
try {
27-
var_dump($pdo->setAttribute($attr, 1));
27+
var_dump($pdo->setAttribute($attr, 'nonsense'));
2828
} catch (\Error $e) {
2929
echo get_class($e), ': ', $e->getMessage(), \PHP_EOL;
3030
}
3131
try {
32-
var_dump($pdo->setAttribute($attr, 'nonsense'));
32+
var_dump($pdo->setAttribute($attr, 1));
3333
} catch (\Error $e) {
3434
echo get_class($e), ': ', $e->getMessage(), \PHP_EOL;
3535
}
@@ -40,8 +40,8 @@ foreach ($attrs as $attr) {
4040
?>
4141
--EXPECT--
4242
TypeError: PDO::ATTR_STATEMENT_CLASS value must be of type array, null given
43-
TypeError: PDO::ATTR_STATEMENT_CLASS value must be of type array, int given
4443
TypeError: PDO::ATTR_STATEMENT_CLASS value must be of type array, string given
44+
TypeError: PDO::ATTR_STATEMENT_CLASS value must be of type array, int given
4545
TypeError: Attribute value must be of type int for selected attribute, null given
46-
bool(true)
46+
TypeError: Attribute value must be of type int for selected attribute, string given
4747
bool(true)

0 commit comments

Comments
 (0)