in source/shared/core_stmt.cpp [2701:2770]
void sqlsrv_param_inout::process_string_param(_Inout_ sqlsrv_stmt* stmt, _Inout_ zval* param_z)
{
bool is_numeric_type = derive_string_types_sizes(param_z);
buffer = Z_STRVAL_P(param_z);
buffer_length = Z_STRLEN_P(param_z);
if (ZSTR_IS_INTERNED(Z_STR_P(param_z))) {
// PHP 5.4 added interned strings, and since we obviously want to change that string here in some fashion,
// we reallocate the string if it's interned
core::sqlsrv_zval_stringl(param_z, static_cast<const char*>(buffer), buffer_length);
// reset buffer and its length
buffer = Z_STRVAL_P(param_z);
buffer_length = Z_STRLEN_P(param_z);
}
// If it's a UTF-8 input output parameter (signified by the C type being SQL_C_WCHAR)
// or if the PHP type is a binary encoded string with a N(VAR)CHAR/NTEXT SQL type,
// convert it to wchar first
if (direction == SQL_PARAM_INPUT_OUTPUT &&
(c_data_type == SQL_C_WCHAR ||
(c_data_type == SQL_C_BINARY &&
(sql_data_type == SQL_WCHAR || sql_data_type == SQL_WVARCHAR || sql_data_type == SQL_WLONGVARCHAR)))) {
if (buffer_length > 0) {
sqlsrv_malloc_auto_ptr<SQLWCHAR> wide_buffer;
unsigned int wchar_size = 0;
wide_buffer = utf16_string_from_mbcs_string(SQLSRV_ENCODING_UTF8, reinterpret_cast<const char*>(buffer), static_cast<int>(buffer_length), &wchar_size);
CHECK_CUSTOM_ERROR(wide_buffer == 0, stmt, SQLSRV_ERROR_INPUT_PARAM_ENCODING_TRANSLATE, param_pos + 1, get_last_error_message()) {
throw core::CoreException();
}
wide_buffer[wchar_size] = L'\0';
core::sqlsrv_zval_stringl(param_z, reinterpret_cast<char*>(wide_buffer.get()), wchar_size * sizeof(SQLWCHAR));
buffer = Z_STRVAL_P(param_z);
buffer_length = Z_STRLEN_P(param_z);
}
}
strlen_or_indptr = buffer_length;
// Since this is an output string, assure there is enough space to hold the requested size and
// update all the variables accordingly (param_z, buffer, buffer_length, and strlen_or_indptr)
resize_output_string_buffer(param_z, is_numeric_type);
if (is_numeric_type) {
encoding = SQLSRV_ENCODING_CHAR;
}
// For output parameters, if we set the column_size to be same as the buffer_len,
// then if there is a truncation due to the data coming from the server being
// greater than the column_size, we don't get any truncation error. In order to
// avoid this silent truncation, we set the column_size to be "MAX" size for
// string types. This will guarantee that there is no silent truncation for
// output parameters.
// if column encryption is enabled, at this point the correct column size has been set by SQLDescribeParam
if (direction == SQL_PARAM_OUTPUT && !stmt->conn->ce_option.enabled) {
switch (sql_data_type) {
case SQL_VARBINARY:
case SQL_VARCHAR:
case SQL_WVARCHAR:
column_size = SQL_SS_LENGTH_UNLIMITED;
break;
default:
break;
}
}
}