Skip to content

PDO execute not correctly binding booleans #9644

Open
@8ctopus

Description

@8ctopus

Description

The following code:

<?php

$db = new PDO(...);

$sql = <<<SQL
    CREATE TABLE test (
        `id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
        `birthday` DATE NOT NULL,
        `name` VARCHAR(40) NOT NULL,
        `salary` INT NOT NULL,
        `boss` BIT NOT NULL
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8
SQL;

$query = $db->prepare($sql);
$query->execute();

$sql = <<<SQL
    INSERT INTO test
    (birthday, name, salary, boss)
    VALUES (:birthday, :name, :salary, :boss)
SQL;

$query = $db->prepare($sql);

$staff = [
    [
        'birthday' => (new DateTime('1995-05-01'))->format('Y-m-d'),
        'name' => 'Sharon',
        'salary' => '200',
        'boss' => TRUE,
    ],
];

foreach ($staff as $member) {
/* works
    $query->bindValue('birthday', $member['birthday'], PDO::PARAM_STR);
    $query->bindValue('name', $member['name'], PDO::PARAM_STR);
    $query->bindValue('salary', $member['salary'], PDO::PARAM_INT);
    $query->bindValue('boss', $member['boss'], PDO::PARAM_BOOL);
    $query->execute();
*/
    // does not work
    $query->execute($member);
}

Resulted in this output:

SQLSTATE[22001]: String data, right truncated: 1406 Data too long for column 'boss' at row 1

But I expected execute() not to throw an error.

I clearly see the problem in the source as the parameter is always set to be a string on line 424:

php-src/ext/pdo/pdo_stmt.c

Lines 411 to 425 in 615b800

ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(input_params), num_index, key, tmp) {
memset(&param, 0, sizeof(param));
if (key) {
/* yes this is correct. we don't want to count the null byte. ask wez */
param.name = key;
param.paramno = -1;
} else {
/* we're okay to be zero based here */
/* num_index is unsignend */
param.paramno = num_index;
}
param.param_type = PDO_PARAM_STR;
ZVAL_COPY(&param.parameter, tmp);

Can't the execute() code be improved to check for the param type like it is done in bindValue()?

php-src/ext/pdo/pdo_stmt.c

Lines 1465 to 1475 in 615b800

memset(&param, 0, sizeof(param));
ZEND_PARSE_PARAMETERS_START(2, 3)
Z_PARAM_STR_OR_LONG(param.name, param.paramno)
Z_PARAM_ZVAL(parameter)
Z_PARAM_OPTIONAL
Z_PARAM_LONG(param_type)
ZEND_PARSE_PARAMETERS_END();
PHP_STMT_GET_OBJ;
param.param_type = (int) param_type;

PHP Version

8.2.0 RC3

Operating System

Alpine Linux

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions