From 752f3361cea115cf807e2284b5acc6f1705b9726 Mon Sep 17 00:00:00 2001 From: gargsaumya Date: Thu, 30 Oct 2025 14:24:07 +0530 Subject: [PATCH 1/2] suppressing false warnings --- mssql_python/pybind/ddbc_bindings.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/mssql_python/pybind/ddbc_bindings.cpp b/mssql_python/pybind/ddbc_bindings.cpp index 96a8d9f7..00ada29d 100644 --- a/mssql_python/pybind/ddbc_bindings.cpp +++ b/mssql_python/pybind/ddbc_bindings.cpp @@ -2403,7 +2403,9 @@ static py::object FetchLobColumnData(SQLHSTMT hStmt, // Wide characters size_t wcharSize = sizeof(SQLWCHAR); if (bytesRead >= wcharSize) { - auto sqlwBuf = reinterpret_cast(chunk.data()); + auto sqlwBuf = reinterpret_cast(chunk.data()); // CodeQL [SM02986] This cast is safe because 1. std::vector guarantees proper alignment for its allocations + // 2. SQLGetData writes complete SQLWCHAR units to the buffer + // 3. bytesRead is controlled by the ODBC driver to be SQLWCHAR-aligned size_t wcharCount = bytesRead / wcharSize; while (wcharCount > 0 && sqlwBuf[wcharCount - 1] == 0) { --wcharCount; @@ -2434,13 +2436,17 @@ static py::object FetchLobColumnData(SQLHSTMT hStmt, } if (isWideChar) { #if defined(_WIN32) - std::wstring wstr(reinterpret_cast(buffer.data()), buffer.size() / sizeof(wchar_t)); + std::wstring wstr(reinterpret_cast(buffer.data()), buffer.size() / sizeof(wchar_t)); // CodeQL [SM02986] This cast is safe because 1. std::vector guarantees proper alignment for its allocations + // 2. SQLGetData writes complete SQLWCHAR units to the buffer + // 3. bytesRead is controlled by the ODBC driver to be SQLWCHAR-aligned std::string utf8str = WideToUTF8(wstr); return py::str(utf8str); #else // Linux/macOS handling size_t wcharCount = buffer.size() / sizeof(SQLWCHAR); - const SQLWCHAR* sqlwBuf = reinterpret_cast(buffer.data()); + const SQLWCHAR* sqlwBuf = reinterpret_cast(buffer.data()); // CodeQL [SM02986] This cast is safe because 1. std::vector guarantees proper alignment for its allocations + // 2. SQLGetData writes complete SQLWCHAR units to the buffer + // 3. bytesRead is controlled by the ODBC driver to be SQLWCHAR-aligned std::wstring wstr = SQLWCHARToWString(sqlwBuf, wcharCount); std::string utf8str = WideToUTF8(wstr); return py::str(utf8str); From 8d7d173eac9a8b2a523610654754902b35055607 Mon Sep 17 00:00:00 2001 From: gargsaumya Date: Thu, 30 Oct 2025 16:24:34 +0530 Subject: [PATCH 2/2] pushing the fix --- mssql_python/pybind/ddbc_bindings.cpp | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/mssql_python/pybind/ddbc_bindings.cpp b/mssql_python/pybind/ddbc_bindings.cpp index 00ada29d..a06fe4fd 100644 --- a/mssql_python/pybind/ddbc_bindings.cpp +++ b/mssql_python/pybind/ddbc_bindings.cpp @@ -8,6 +8,7 @@ #include "connection/connection_pool.h" #include +#include // For std::memcpy #include // std::setw, std::setfill #include #include // std::forward @@ -2402,12 +2403,11 @@ static py::object FetchLobColumnData(SQLHSTMT hStmt, } else { // Wide characters size_t wcharSize = sizeof(SQLWCHAR); - if (bytesRead >= wcharSize) { - auto sqlwBuf = reinterpret_cast(chunk.data()); // CodeQL [SM02986] This cast is safe because 1. std::vector guarantees proper alignment for its allocations - // 2. SQLGetData writes complete SQLWCHAR units to the buffer - // 3. bytesRead is controlled by the ODBC driver to be SQLWCHAR-aligned + if (bytesRead >= wcharSize && (bytesRead % wcharSize == 0)) { size_t wcharCount = bytesRead / wcharSize; - while (wcharCount > 0 && sqlwBuf[wcharCount - 1] == 0) { + std::vector alignedBuf(wcharCount); + std::memcpy(alignedBuf.data(), chunk.data(), bytesRead); + while (wcharCount > 0 && alignedBuf[wcharCount - 1] == 0) { --wcharCount; bytesRead -= wcharSize; } @@ -2436,18 +2436,18 @@ static py::object FetchLobColumnData(SQLHSTMT hStmt, } if (isWideChar) { #if defined(_WIN32) - std::wstring wstr(reinterpret_cast(buffer.data()), buffer.size() / sizeof(wchar_t)); // CodeQL [SM02986] This cast is safe because 1. std::vector guarantees proper alignment for its allocations - // 2. SQLGetData writes complete SQLWCHAR units to the buffer - // 3. bytesRead is controlled by the ODBC driver to be SQLWCHAR-aligned + size_t wcharCount = buffer.size() / sizeof(wchar_t); + std::vector alignedBuf(wcharCount); + std::memcpy(alignedBuf.data(), buffer.data(), buffer.size()); + std::wstring wstr(alignedBuf.data(), wcharCount); std::string utf8str = WideToUTF8(wstr); return py::str(utf8str); #else // Linux/macOS handling size_t wcharCount = buffer.size() / sizeof(SQLWCHAR); - const SQLWCHAR* sqlwBuf = reinterpret_cast(buffer.data()); // CodeQL [SM02986] This cast is safe because 1. std::vector guarantees proper alignment for its allocations - // 2. SQLGetData writes complete SQLWCHAR units to the buffer - // 3. bytesRead is controlled by the ODBC driver to be SQLWCHAR-aligned - std::wstring wstr = SQLWCHARToWString(sqlwBuf, wcharCount); + std::vector alignedBuf(wcharCount); + std::memcpy(alignedBuf.data(), buffer.data(), buffer.size()); + std::wstring wstr = SQLWCHARToWString(alignedBuf.data(), wcharCount); std::string utf8str = WideToUTF8(wstr); return py::str(utf8str); #endif @@ -2564,8 +2564,7 @@ SQLRETURN SQLGetData_wrap(SqlHandlePtr StatementHandle, SQLUSMALLINT colCount, p uint64_t numCharsInData = dataLen / sizeof(SQLWCHAR); if (numCharsInData < dataBuffer.size()) { #if defined(__APPLE__) || defined(__linux__) - const SQLWCHAR* sqlwBuf = reinterpret_cast(dataBuffer.data()); - std::wstring wstr = SQLWCHARToWString(sqlwBuf, numCharsInData); + std::wstring wstr = SQLWCHARToWString(dataBuffer.data(), numCharsInData); std::string utf8str = WideToUTF8(wstr); row.append(py::str(utf8str)); #else