Skip to content
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
10 changes: 10 additions & 0 deletions CodeQL.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
queries:
# Exclude all external PHP SDK source code
- exclude:
path:
- "buildscripts/php-sdk"
# Include only the SQLSRV and PDO_SQLSRV source files within the PHP SDK, where we drop them for compilation
- include:
path:
- "buildscripts/php-sdk/**/sqlsrv"
- "buildscripts/php-sdk/**/pdo_sqlsrv"
4 changes: 2 additions & 2 deletions source/shared/core_sqlsrv.h
Original file line number Diff line number Diff line change
Expand Up @@ -1462,7 +1462,7 @@ struct sqlsrv_param

void copy_param_meta_ae(_Inout_ zval* param_z, _In_ param_meta_data& meta); // Only used when Always Encrypted is enabled

virtual ~sqlsrv_param(){ release_data(); }
virtual ~sqlsrv_param(){ sqlsrv_param::release_data(); }
virtual void release_data();

bool derive_string_types_sizes(_In_ zval* param_z);
Expand Down Expand Up @@ -1539,7 +1539,7 @@ struct sqlsrv_param_tvp : public sqlsrv_param
{
ZVAL_UNDEF(&placeholder_z);
}
virtual ~sqlsrv_param_tvp() { release_data(); }
virtual ~sqlsrv_param_tvp() { sqlsrv_param_tvp::release_data(); }
virtual void release_data();
virtual void bind_param(_Inout_ sqlsrv_stmt* stmt);
virtual void process_param(_Inout_ sqlsrv_stmt* stmt, _Inout_ zval* param_z);
Expand Down
7 changes: 4 additions & 3 deletions source/shared/core_stmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2911,9 +2911,10 @@ void sqlsrv_param_inout::finalize_output_string()
char* outString = NULL;
SQLLEN outLen = 0;

// When encoding is UTF-8 or SYSTEM, ODBC returns data as UTF-16 wide characters
// in the output parameter buffer. ODBC guarantees proper alignment and valid UTF-16 data.
const SQLWCHAR* wide_str = reinterpret_cast<const SQLWCHAR*>(str);
// For UTF-8/SYSTEM encoding, the output parameter buffer was bound with SQL_C_WCHAR via
// SQLBindParameter, so ODBC wrote UTF-16 data into it. The reinterpret_cast is necessary
// because the ODBC API binds output params to a generic char* buffer.
const SQLWCHAR* wide_str = reinterpret_cast<const SQLWCHAR*>(str); // CodeQL [SM02986] buffer contains UTF-16 data from ODBC output parameter bound with SQL_C_WCHAR
bool result = convert_string_from_utf16(encoding, wide_str, int(str_len / sizeof(SQLWCHAR)), &outString, outLen);
CHECK_CUSTOM_ERROR(!result, stmt, SQLSRV_ERROR_OUTPUT_PARAM_ENCODING_TRANSLATE, get_last_error_message(), NULL) {
throw core::CoreException();
Expand Down
8 changes: 4 additions & 4 deletions source/shared/core_stream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -200,10 +200,10 @@ size_t sqlsrv_stream_read(_Inout_ php_stream* stream, _Out_writes_bytes_(count)
throw core::CoreException();
}

// When encoding is UTF-8, SQLGetData fills temp_buf with UTF-16 wide character data (SQL_C_WCHAR).
// The buffer is allocated as char* but contains properly aligned UTF-16 data from ODBC.
// Reinterpret as LPCWSTR for conversion functions. This is safe because ODBC guarantees proper alignment.
const LPCWSTR wide_buffer = reinterpret_cast<LPCWSTR>( temp_buf.get() );
// temp_buf contains UTF-16 data written by the ODBC driver via SQLGetData with SQL_C_WCHAR
// (set at line 88 when ss->encoding == CP_UTF8). The char* buffer is a generic allocation;
// the reinterpret_cast is necessary because the ODBC API uses SQLPOINTER (void*) buffers.
const LPCWSTR wide_buffer = reinterpret_cast<LPCWSTR>( temp_buf.get() ); // CodeQL [SM02986] buffer contains UTF-16 data from ODBC SQLGetData with SQL_C_WCHAR
#ifndef _WIN32
int enc_len = SystemLocale::FromUtf16( ss->encoding, wide_buffer,
static_cast<int>(read >> 1), buf, static_cast<int>(count), NULL, NULL );
Expand Down
8 changes: 5 additions & 3 deletions source/shared/core_util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,9 +106,11 @@ bool convert_string_from_utf16_inplace( _In_ SQLSRV_ENCODING encoding, _Inout_up
char* outString = NULL;
SQLLEN outLen = 0;

// The string buffer contains UTF-16 encoded data. Reinterpret as SQLWCHAR* for conversion.
// This is safe because the caller ensures the buffer contains valid UTF-16 data.
const SQLWCHAR* wide_str = reinterpret_cast<const SQLWCHAR*>(*string);
// The buffer contains UTF-16 data written by the ODBC driver via SQLGetData with SQL_C_WCHAR.
// The only caller (get_field_as_string in core_stmt.cpp) guards this call with
// "if (c_type == SQL_C_WCHAR)", ensuring the buffer was populated as UTF-16 by the driver.
// The reinterpret_cast is necessary because the ODBC API uses a generic char* buffer.
const SQLWCHAR* wide_str = reinterpret_cast<const SQLWCHAR*>(*string); // CodeQL [SM02986] buffer is ensured to contain UTF-16 data
bool result = convert_string_from_utf16( encoding, wide_str, int(len / sizeof(SQLWCHAR)), &outString, outLen );

if (result)
Expand Down
2 changes: 1 addition & 1 deletion test/tools/mock_tds_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -1341,7 +1341,7 @@ def generate_self_signed_cert(cert_path, key_path):
.public_key(key.public_key())
.serial_number(x509.random_serial_number())
.not_valid_before(datetime.datetime.now(datetime.timezone.utc))
.not_valid_after(datetime.datetime.now(datetime.timezone.utc) + datetime.timedelta(days=365))
.not_valid_after(datetime.datetime.now(datetime.timezone.utc) + datetime.timedelta(days=30))
.sign(key, hashes.SHA256())
)
with open(key_path, "wb") as f:
Expand Down
Loading