From 2aec3b4a952f29fff76199c22c593b5d68858999 Mon Sep 17 00:00:00 2001 From: v-kaywon Date: Fri, 21 Apr 2017 13:04:24 -0700 Subject: [PATCH] added error handling for emulate prepared statement with inout parameters --- source/pdo_sqlsrv/pdo_stmt.cpp | 4 + source/pdo_sqlsrv/pdo_util.cpp | 4 + source/pdo_sqlsrv/php_pdo_sqlsrv.h | 2 +- ...ement_bindParam_inout_emulate_prepare.phpt | 30 +++++++ ..._140_emulate_prepare_pos_placehodlers.phpt | 82 +++++++++++++++++++ 5 files changed, 121 insertions(+), 1 deletion(-) create mode 100644 test/pdo_sqlsrv/pdoStatement_bindParam_inout_emulate_prepare.phpt create mode 100644 test/pdo_sqlsrv/pdo_140_emulate_prepare_pos_placehodlers.phpt diff --git a/source/pdo_sqlsrv/pdo_stmt.cpp b/source/pdo_sqlsrv/pdo_stmt.cpp index 89ca6430..3b4e56d7 100644 --- a/source/pdo_sqlsrv/pdo_stmt.cpp +++ b/source/pdo_sqlsrv/pdo_stmt.cpp @@ -1115,6 +1115,10 @@ int pdo_sqlsrv_stmt_param_hook(pdo_stmt_t *stmt, // since the param isn't reliable, we don't do anything here case PDO_PARAM_EVT_ALLOC: + if ( stmt->supports_placeholders == PDO_PLACEHOLDER_NONE && (param->param_type & PDO_PARAM_INPUT_OUTPUT )) { + sqlsrv_stmt* driver_stmt = reinterpret_cast( stmt->driver_data ); + THROW_PDO_ERROR( driver_stmt, PDO_SQLSRV_ERROR_EMULATE_INOUT_UNSUPPORTED ); + } break; case PDO_PARAM_EVT_FREE: break; diff --git a/source/pdo_sqlsrv/pdo_util.cpp b/source/pdo_sqlsrv/pdo_util.cpp index a67b194e..227cc83b 100644 --- a/source/pdo_sqlsrv/pdo_util.cpp +++ b/source/pdo_sqlsrv/pdo_util.cpp @@ -373,6 +373,10 @@ pdo_error PDO_ERRORS[] = { SQLSRV_ERROR_BUFFER_LIMIT_EXCEEDED, { IMSSP, (SQLCHAR*) "Memory limit of %1!d! KB exceeded for buffered query", -71, true } }, + { + PDO_SQLSRV_ERROR_EMULATE_INOUT_UNSUPPORTED, + { IMSSP, (SQLCHAR*) "Statement with emulate prepare on does not support output or input_output parameters.", -72, false } + }, { UINT_MAX, {} } }; diff --git a/source/pdo_sqlsrv/php_pdo_sqlsrv.h b/source/pdo_sqlsrv/php_pdo_sqlsrv.h index 3a853658..26bb0cc1 100644 --- a/source/pdo_sqlsrv/php_pdo_sqlsrv.h +++ b/source/pdo_sqlsrv/php_pdo_sqlsrv.h @@ -389,7 +389,7 @@ enum PDO_ERROR_CODES { PDO_SQLSRV_ERROR_INVALID_COLUMN_INDEX, PDO_SQLSRV_ERROR_INVALID_OUTPUT_PARAM_TYPE, PDO_SQLSRV_ERROR_INVALID_CURSOR_WITH_SCROLL_TYPE, - + PDO_SQLSRV_ERROR_EMULATE_INOUT_UNSUPPORTED, }; extern pdo_error PDO_ERRORS[]; diff --git a/test/pdo_sqlsrv/pdoStatement_bindParam_inout_emulate_prepare.phpt b/test/pdo_sqlsrv/pdoStatement_bindParam_inout_emulate_prepare.phpt new file mode 100644 index 00000000..93483b30 --- /dev/null +++ b/test/pdo_sqlsrv/pdoStatement_bindParam_inout_emulate_prepare.phpt @@ -0,0 +1,30 @@ +--TEST-- +uses an input/output parameter with emulate prepare +--SKIPIF-- +--FILE-- +setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + + $dbh->query("IF OBJECT_ID('sp_ReverseString', 'P') IS NOT NULL DROP PROCEDURE sp_ReverseString"); + $dbh->query("CREATE PROCEDURE sp_ReverseString @String as VARCHAR(2048) OUTPUT as SELECT @String = REVERSE(@String)"); + $stmt = $dbh->prepare("EXEC sp_ReverseString ?", array(PDO::ATTR_EMULATE_PREPARES => true)); + $string = "123456789"; + $stmt->bindParam(1, $string, PDO::PARAM_STR | PDO::PARAM_INPUT_OUTPUT, 2048); + $stmt->execute(); + print "Result: ".$string; + + //free the statement and connection + $stmt = null; + $dbh = null; +} +catch(PDOException $e) { + print("Error: " . $e->getMessage() . "\n"); +} +?> +--EXPECT-- +Error: SQLSTATE[IMSSP]: Statement with emulate prepare on does not support output or input_output parameters. \ No newline at end of file diff --git a/test/pdo_sqlsrv/pdo_140_emulate_prepare_pos_placehodlers.phpt b/test/pdo_sqlsrv/pdo_140_emulate_prepare_pos_placehodlers.phpt new file mode 100644 index 00000000..cf3abf55 --- /dev/null +++ b/test/pdo_sqlsrv/pdo_140_emulate_prepare_pos_placehodlers.phpt @@ -0,0 +1,82 @@ +--TEST-- +Test emulate prepare with mix bound param encodings and positional placeholders (i.e., using '?' as placeholders) +--SKIPIF-- +--FILE-- +prepare('DROP TABLE WATCHDOG', $pdo_options); + + $st->execute(); +} +catch(\Exception $e) {} + +$tablescript = <<prepare($tablescript, $pdo_options); +$st->execute(); + +$query = <<prepare($query, $pdo_options); + +$system_param = 'system encoded string'; +$utf8_param = '가각ácasa'; +$binary_param = fopen('php://memory', 'a'); +fwrite($binary_param, 'asdgasdgasdgsadg'); +rewind($binary_param); + +$st->bindParam(1, $system_param, PDO::PARAM_STR); +$st->bindParam(2, $utf8_param, PDO::PARAM_STR, 0, PDO::SQLSRV_ENCODING_UTF8); +$st->bindParam(3, $binary_param, PDO::PARAM_LOB, 0, PDO::SQLSRV_ENCODING_BINARY); + +$st->execute(); + +$st = $cnn->query("SELECT * FROM [watchdog]"); +var_dump($st->fetchAll()); + +$st = NULL; +$cnn = NULL; + +?> +--EXPECT-- +array(1) { + [0]=> + array(6) { + ["system_encoding"]=> + string(21) "system encoded string" + [0]=> + string(21) "system encoded string" + ["utf8_encoding"]=> + string(12) "가각ácasa" + [1]=> + string(12) "가각ácasa" + ["binary_encoding"]=> + string(16) "asdgasdgasdgsadg" + [2]=> + string(16) "asdgasdgasdgsadg" + } +} \ No newline at end of file