Skip to Main Content

DevOps, CI/CD and Automation

Announcement

For appeals, questions and feedback about Oracle Forums, please email oracle-forums-moderators_us@oracle.com. Technical questions should be asked in the appropriate category. Thank you!

64-bit ODBC driver with SQL_ATTR_ROW_STATUS_PTR corrupts memory

CervisiaMay 28 2018 — edited May 28 2018

The example program below blows up on 64-bit architectures when using the Oracle ODBC driver. (ODBC drivers for other DBs work correctly.)

Apparently, the driver does not use SQLUSMALLINT but a 64-bit type for the entries in the row status array (set with SQL_ATTR_ROW_STATUS_PTR).

The ODBC specification requires the array entries to be SQLUSMALLINT:

… points to an array of SQLUSMALLINT values containing row status values after a call to SQLFetch or SQLFetchScroll.

(https://docs.microsoft.com/en-us/sql/odbc/reference/syntax/sqlsetstmtattr-function)

And the 64-Bit information page (https://docs.microsoft.com/en-us/sql/odbc/reference/odbc-64-bit-information) does not mention anything about changes to this data type; only the pointer to the array is now 64 bits.

Is there a reason why the driver does not use SQLUSMALLINT?

Tested with the latest version, Instant Client 12.2 (instantclient-basiclite-windows.x64-12.2.0.1.0.zip and instantclient-odbc-windows.x64-12.2.0.1.0-2.zip), but I've seen this also with earlier versions.

#include <stdio.h>

#include <assert.h>

#include <windows.h> // needed for Microsoft's ODBC headers

#include <sql.h>

#include <sqlext.h>

#define DSN      "Oracle"

#define USER     "scott"

#define PASSWORD "tiger"

#define CHECK(fn) do { if ((fn) != SQL_SUCCESS) { fprintf(stderr, "%s failed\n", #fn); return 1; } } while (0)

int main()

{

    SQLHENV hEnv;

    SQLHDBC hDbc;

    SQLHSTMT hStmt;

    struct {

        SQLUSMALLINT rowStatusArray[1];

        char important_data;

    } d;

    assert(sizeof(d.rowStatusArray) == 2);

    CHECK(SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &hEnv));

    CHECK(SQLSetEnvAttr(hEnv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, 0));

    CHECK(SQLAllocHandle(SQL_HANDLE_DBC, hEnv, &hDbc));

    CHECK(SQLConnect(hDbc, (SQLCHAR*)DSN, SQL_NTS, (SQLCHAR*)USER, SQL_NTS, (SQLCHAR*)PASSWORD, SQL_NTS));

    CHECK(SQLAllocHandle(SQL_HANDLE_STMT, hDbc, &hStmt));

    CHECK(SQLExecDirect(hStmt, (SQLCHAR*)"SELECT 42 FROM DUAL", SQL_NTS));

    CHECK(SQLSetStmtAttr(hStmt, SQL_ATTR_ROW_ARRAY_SIZE, (SQLPOINTER)1, 0));

    CHECK(SQLSetStmtAttr(hStmt, SQL_ATTR_ROW_STATUS_PTR, d.rowStatusArray, 0));

   

    d.important_data = 123;

    CHECK(SQLFetch(hStmt));

    assert(d.important_data == 123);

   

    SQLFreeHandle(SQL_HANDLE_STMT, hStmt);

    SQLFreeHandle(SQL_HANDLE_DBC, hDbc);

    SQLFreeHandle(SQL_HANDLE_ENV, hEnv);

    return 0;

}

Assertion failed: d.important_data == 123, file ODBC_64_Test.cpp, line 35

Comments
Locked Post
New comments cannot be posted to this locked post.
Post Details
Locked on Jun 25 2018
Added on May 28 2018
0 comments
782 views