Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix right truncation issue #1408

Merged
merged 5 commits into from
Sep 13, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 14 additions & 14 deletions source/shared/core_stmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -414,10 +414,22 @@ void core_sqlsrv_bind_param( _Inout_ sqlsrv_stmt* stmt, _In_ SQLUSMALLINT param_
}

// If Always Encrypted is enabled, transfer the known param meta data if applicable, which might alter param_z for decimal types
if (stmt->conn->ce_option.enabled) {
if (param_ptr->sql_data_type == SQL_UNKNOWN_TYPE || param_ptr->column_size == SQLSRV_UNKNOWN_SIZE) {
if (stmt->conn->ce_option.enabled
&& (param_ptr->sql_data_type == SQL_UNKNOWN_TYPE || param_ptr->column_size == SQLSRV_UNKNOWN_SIZE)) {
// meta data parameters are always sorted based on parameter number
param_ptr->copy_param_meta_ae(param_z, stmt->params_container.params_meta_ae[param_num]);
}
else {
if (Z_TYPE_P(param_z) == IS_STRING && column_size == SQLSRV_UNKNOWN_SIZE) {
size_t char_size = (encoding == SQLSRV_ENCODING_UTF8) ? sizeof(SQLWCHAR) : sizeof(char);
SQLULEN byte_len = Z_STRLEN_P(param_z) * char_size;

if (byte_len > SQL_SERVER_MAX_FIELD_SIZE) {
param_ptr->column_size = SQL_SERVER_MAX_TYPE_SIZE;
}
else {
param_ptr->column_size = SQL_SERVER_MAX_FIELD_SIZE / char_size;
}
}
}

Expand Down Expand Up @@ -2272,18 +2284,6 @@ bool sqlsrv_param::derive_string_types_sizes(_In_ zval* param_z)
break;
}

// Derive the column size also only if it is unknown
if (column_size == SQLSRV_UNKNOWN_SIZE) {
size_t char_size = (encoding == SQLSRV_ENCODING_UTF8) ? sizeof(SQLWCHAR) : sizeof(char);
SQLULEN byte_len = Z_STRLEN_P(param_z) * char_size;

if (byte_len > SQL_SERVER_MAX_FIELD_SIZE) {
column_size = SQL_SERVER_MAX_TYPE_SIZE;
} else {
column_size = SQL_SERVER_MAX_FIELD_SIZE / char_size;
}
}

return is_numeric;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
--TEST--
GitHub issue 1391 - string truncation error when binding some parameters as longer strings the second time
--DESCRIPTION--
The test shows the same parameters, though bound as short strings in the first insertion, can be bound as longer strings in the subsequent insertions.
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php

require_once("MsSetup.inc");

function dropTable($conn, $tableName)
{
$drop = "IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'" . $tableName . "') AND type in (N'U')) DROP TABLE $tableName";
$conn->exec($drop);
}

try {
$conn = new PDO("sqlsrv:server=$server; Database = $databaseName;", $uid, $pwd);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

dropTable($conn, 'long_strings');

$tsql = <<<CREATESQL
CREATE TABLE long_strings (
id bigint IDENTITY(1,1) NOT NULL,
four_thousand varchar(4002) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
var_max varchar(max) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
nvar_max varchar(max) NOT NULL,
CONSTRAINT PK__long_strings__1391E83F512B1391 PRIMARY KEY (id))
CREATESQL;

$conn->exec($tsql);

$tsql = <<<INSERTSQL
INSERT INTO long_strings (four_thousand, var_max, nvar_max) VALUES (?, ?, ?)
INSERTSQL;

$stmt = $conn->prepare($tsql);

// Bind and execute short string values first
$fourThousand = '4';
$varMax = 'v';
$nvarMax = 'n';
$stmt->bindParam(1, $fourThousand);
$stmt->bindParam(2, $varMax);
$stmt->bindParam(3, $nvarMax);
$stmt->execute();

// Bind and execute long string values second, on same $stmt
$fourThousand = str_repeat('4', 4001);
$varMax = str_repeat('v', 4001);
$nvarMax = str_repeat('n', 4001);
$stmt->bindParam(1, $fourThousand);
$stmt->bindParam(2, $varMax);
$stmt->bindParam(3, $nvarMax);
$stmt->execute();

// fetch the data
$stmt = $conn->prepare("SELECT COUNT(*) FROM long_strings");
$stmt->execute();
$row = $stmt->fetch(PDO::FETCH_NUM);
echo $row[0]."\n";

dropTable($conn, 'long_strings');

echo "Done\n";
} catch (PdoException $e) {
echo $e->getMessage();
}

?>
--EXPECT--
2
Done
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ try {
--EXPECTREGEX--
Array
\(
\[(DriverDllName|DriverName)\] => (msodbcsql1[1-9].dll|(libmsodbcsql-[0-9]{2}\.[0-9]\.so\.[0-9]\.[0-9]|libmsodbcsql.[0-9]{2}.dylib))
\[(DriverDllName|DriverName)\] => (msodbcsql1[1-9].dll|(libmsodbcsql-[0-9]{2}\.[0-9]{1,2}\.so\.[0-9]\.[0-9]|libmsodbcsql.[0-9]{2}.dylib))
\[DriverODBCVer\] => [0-9]{1,2}\.[0-9]{1,2}
\[DriverVer\] => [0-9]{1,2}\.[0-9]{1,2}\.[0-9]{4}
\[ExtensionVer\] => [0-9]\.[0-9]+\.[0-9](-(RC[1-9]?|beta[1-9]))?(\.[0-9]+)?(\+[0-9]+)?
Expand Down
2 changes: 1 addition & 1 deletion test/functional/pdo_sqlsrv/pdo_get_set_attr.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ SQLSTATE\[IMSSP\]: A read-only attribute was designated on the PDO object.
Get Result PDO::ATTR_CLIENT_VERSION :
array\(4\) {
\[\"(DriverDllName|DriverName)\"\]=>
(string\([0-9]+\) \"msodbcsql1[1-9].dll\"|string\([0-9]+\) \"(libmsodbcsql-[0-9]{2}\.[0-9]\.so\.[0-9]\.[0-9]|libmsodbcsql.[0-9]{2}.dylib)\")
(string\([0-9]+\) \"msodbcsql1[1-9].dll\"|string\([0-9]+\) \"(libmsodbcsql-[0-9]{2}\.[0-9]{1,2}\.so\.[0-9]\.[0-9]|libmsodbcsql.[0-9]{2}.dylib)\")
\["DriverODBCVer"\]=>
string\(5\) \"[0-9]{1,2}\.[0-9]{1,2}\"
\["DriverVer"\]=>
Expand Down
2 changes: 1 addition & 1 deletion test/functional/sqlsrv/sqlsrv_client_info.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ var_dump( $client_info );
--EXPECTREGEX--
array\(4\) {
\[\"(DriverDllName|DriverName)\"\]=>
(string\([0-9]+\) \"msodbcsql1[1-9].dll\"|string\([0-9]+\) \"(libmsodbcsql-[0-9]{2}\.[0-9]\.so\.[0-9]\.[0-9]|libmsodbcsql.[0-9]{2}.dylib)\")
(string\([0-9]+\) \"msodbcsql1[1-9].dll\"|string\([0-9]+\) \"(libmsodbcsql-[0-9]{2}\.[0-9]{1,2}\.so\.[0-9]\.[0-9]|libmsodbcsql.[0-9]{2}.dylib)\")
\[\"DriverODBCVer\"\]=>
string\(5\) \"[0-9]{1,2}\.[0-9]{1,2}\"
\[\"DriverVer\"\]=>
Expand Down