-
Notifications
You must be signed in to change notification settings - Fork 374
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Initialize output param buffer when allocating extra space (#907)
- Loading branch information
Showing
3 changed files
with
162 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
80 changes: 80 additions & 0 deletions
80
test/functional/pdo_sqlsrv/pdo_900_output_param_memory_data.phpt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
--TEST-- | ||
GitHub issue 900 - output parameter displays data from memory when not finalized | ||
--DESCRIPTION-- | ||
This test verifies that when there is an active resultset and output parameter not finalized, it should not show any data from client memory. This test does not work with AlwaysEncrypted because the output param is not assigned in the stored procedure. | ||
--ENV-- | ||
PHPT_EXEC=true | ||
--SKIPIF-- | ||
<?php require('skipif_mid-refactor.inc'); ?> | ||
--FILE-- | ||
<?php | ||
require_once("MsSetup.inc"); | ||
require_once("MsCommon_mid-refactor.inc"); | ||
|
||
function getOutputParam($conn, $storedProcName, $dataType, $inout) | ||
{ | ||
$size = rand(1000, 4000); // The maximum anticipated size is 8000 for wide chars | ||
|
||
try { | ||
$output = null; | ||
$stmt = $conn->prepare("$storedProcName @OUTPUT = :output"); | ||
if ($inout) { | ||
$paramType = PDO::PARAM_STR | PDO::PARAM_INPUT_OUTPUT; | ||
} else { | ||
$paramType = PDO::PARAM_STR; | ||
} | ||
$stmt->bindParam('output', $output, $paramType, $size); | ||
|
||
$stmt->execute(); | ||
|
||
// The output param should be doubled in size for wide characters. | ||
// However, it should not contain any data so after trimming it | ||
// should be merely an empty string because it was originally set to null | ||
$len = strlen($output); | ||
$result = trim($output); | ||
|
||
if ($len != ($size * 2) || $result !== "" ) { | ||
echo "Unexpected output param for $dataType: "; | ||
var_dump($output); | ||
} | ||
|
||
$stmt->closeCursor(); | ||
if (!is_null($output)) { | ||
echo "Output param should be null when finalized!"; | ||
} | ||
unset($stmt); | ||
} catch (PdoException $e) { | ||
echo $e->getMessage() . PHP_EOL; | ||
} | ||
} | ||
|
||
try { | ||
// This helper method sets PDO::ATTR_ERRMODE to PDO::ERRMODE_EXCEPTION | ||
// $conn = connect(); | ||
$conn = new PDO( "sqlsrv:server=$server; Database = $databaseName", $uid, $pwd); | ||
$conn->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION ); | ||
|
||
$dataTypes = array("VARCHAR(256)", "VARCHAR(512)", "VARCHAR(max)", "NVARCHAR(256)", "NVARCHAR(512)", "NVARCHAR(max)"); | ||
for ($i = 0, $p = 3; $i < count($dataTypes); $i++, $p++) { | ||
// Create the stored procedure first | ||
$storedProcName = "spNullOutputParam" . $i; | ||
$procArgs = "@OUTPUT $dataTypes[$i] OUTPUT"; | ||
$procCode = "SELECT 1, 2, 3"; | ||
|
||
createProc($conn, $storedProcName, $procArgs, $procCode); | ||
getOutputParam($conn, $storedProcName, $dataTypes[$i], false); | ||
getOutputParam($conn, $storedProcName, $dataTypes[$i], true); | ||
|
||
// Drop the stored procedure | ||
dropProc($conn, $storedProcName); | ||
} | ||
|
||
echo "Done\n"; | ||
|
||
unset($conn); | ||
} catch (PdoException $e) { | ||
echo $e->getMessage() . PHP_EOL; | ||
} | ||
?> | ||
--EXPECT-- | ||
Done |
77 changes: 77 additions & 0 deletions
77
test/functional/sqlsrv/sqlsrv_900_output_param_memory_data.phpt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
--TEST-- | ||
GitHub issue 900 - output parameter displays data from memory when not finalized | ||
--DESCRIPTION-- | ||
This test verifies that when there is an active resultset and output parameter not finalized, it should not show any data from client memory. This test does not work with AlwaysEncrypted because the output param is not assigned in the stored procedure. | ||
--ENV-- | ||
PHPT_EXEC=true | ||
--SKIPIF-- | ||
<?php require('skipif_versions_old.inc'); ?> | ||
--FILE-- | ||
<?php | ||
require_once('MsCommon.inc'); | ||
|
||
function getOutputParam($conn, $storedProcName, $inout, $isVarchar) | ||
{ | ||
$size = rand(1000, 4000); // The maximum anticipated size is 8000 for wide chars | ||
|
||
$output = null; | ||
$dir = ($inout)? SQLSRV_PARAM_INOUT : SQLSRV_PARAM_OUT; | ||
$dataType = ($isVarchar)? "SQLSRV_SQLTYPE_VARCHAR" : "SQLSRV_SQLTYPE_NVARCHAR"; | ||
$sqlType = call_user_func($dataType, $size); | ||
|
||
$stmt = sqlsrv_prepare($conn, "$storedProcName @OUTPUT = ?", array(array(&$output, $dir, null, $sqlType))); | ||
if (!$stmt) { | ||
fatalError("getOutputParam: failed when preparing to call $storedProcName"); | ||
} | ||
if (!sqlsrv_execute($stmt)) { | ||
fatalError("getOutputParam: failed to execute procedure $storedProcName"); | ||
} | ||
|
||
// The output param should be doubled in size for wide characters. | ||
// However, it should not contain any data so after trimming it | ||
// should be merely an empty string because it was originally set to null | ||
$len = strlen($output); | ||
$expectedLen = $size * 2; | ||
$result = trim($output); | ||
|
||
if ($len != $expectedLen || $result !== "" ) { | ||
echo "Unexpected output param for $dataType, $isMax: "; | ||
var_dump($output); | ||
} | ||
|
||
sqlsrv_next_result($stmt); | ||
if (!is_null($output)) { | ||
echo "Output param should be null when finalized!"; | ||
} | ||
} | ||
|
||
set_time_limit(0); | ||
sqlsrv_configure('WarningsReturnAsErrors', 1); | ||
|
||
$conn = connect(array("CharacterSet" => "UTF-8")); | ||
if (!$conn) { | ||
fatalError("Could not connect.\n"); | ||
} | ||
|
||
$dataTypes = array("VARCHAR(256)", "VARCHAR(512)", "VARCHAR(max)", "NVARCHAR(256)", "NVARCHAR(512)", "NVARCHAR(max)"); | ||
for ($i = 0, $p = 3; $i < count($dataTypes); $i++, $p++) { | ||
// Create the stored procedure first | ||
$storedProcName = "spNullOutputParam" . $i; | ||
$procArgs = "@OUTPUT $dataTypes[$i] OUTPUT"; | ||
$procCode = "SELECT 1, 2, 3"; | ||
|
||
createProc($conn, $storedProcName, $procArgs, $procCode); | ||
getOutputParam($conn, $storedProcName, false, ($i < 3)); | ||
getOutputParam($conn, $storedProcName, true, ($i < 3)); | ||
|
||
// Drop the stored procedure | ||
dropProc($conn, $storedProcName); | ||
} | ||
|
||
echo "Done\n"; | ||
|
||
sqlsrv_close($conn); | ||
|
||
?> | ||
--EXPECT-- | ||
Done |