MSSQL Server ODBC driver crash

From: Jason Hinsperger (NO_jason_hinsperger_spam_at_hotmail.com)
Date: 02/27/04


Date: Fri, 27 Feb 2004 13:31:05 -0800

If the SQL Server driver's option "Use ANSI nulls, paddings and warnings"
is not set and the length of char is over 623, MS SQL Server driver will
crash in calling SQLFreeHandle.

Repro:

Version of SQL Server Driver: 2000.81.9042.00
Database: SQL Server 2000

1. Create the table ssint2:

create table ssint2(
id int not null primary key,
source char( 1000 ) )

2. Create a dsn using SQL server driver, don't set the option "Use ANSI
nulls, paddings and warnings". Run the repro as:

charcrash "DSN=SQL_Server_Data_source;UID=userid;PWD=password"

You will see the repro crashing in calling SQLFreeHandle of the
statement "select id, source from ssint2".

Notes: This crash is related to the size of char column. If the size is
less than 623, it won't crash.

Here is a sample program which demonstrates the problem:
#include <stdio.h>
#include <stdlib.h>
#include <d:\odbcbug\odbc.h>
#include <string.h>

#if ODBCVER < 0x0350
    #error "***** This module requires ODBC 3.5 or higher *****"
#endif

typedef struct ml_host_data {
        SQLHENV env;
} ml_host_data, *p_ml_host_data;

typedef struct ml_host_conn {
    p_ml_host_data host;
    SQLHDBC dbc;
} ml_host_conn, *p_ml_host_conn;

p_ml_host_data Init( void )
/*************************/
{
    p_ml_host_data host;
    RETCODE ret;

    host = (p_ml_host_data) malloc( sizeof( *host ) );
    if( host != NULL ) {
        ret = SQLAllocHandle( SQL_HANDLE_ENV, SQL_NULL_HANDLE, &host->env );
    
        ret = SQLSetEnvAttr( host->env,
                       SQL_ATTR_ODBC_VERSION,
                       (SQLPOINTER)SQL_OV_ODBC3,
                       0 );
    }

    return( host );
}

void Fini( p_ml_host_data host )
/******************************/
{
    RETCODE ret;

    // Clean up any resources and shut the module down.
    if( host->env != SQL_NULL_HENV ) {
        ret = SQLFreeHandle( SQL_HANDLE_ENV, host->env );
    }
}

p_ml_host_conn Connect(
/**********************/
    p_ml_host_data host,
    char * conn_str )
{
    // Establish a connection with the host database. This may
    // create a new connection or just grab one from a pool
    // of connections.
    p_ml_host_conn conn;
    SQLSMALLINT conn_str_len;
    char out_str[ 2048 ];
    RETCODE ret = SQL_ERROR;

    conn = (p_ml_host_conn) malloc( sizeof( ml_host_conn ) );
    if( conn == NULL ) {
        goto done;
    }

    conn->host = host;
    conn->dbc = SQL_NULL_HDBC;

    ret = SQLAllocHandle( SQL_HANDLE_DBC, host->env, &conn->dbc );

    ret = SQLDriverConnect( conn->dbc,
                            NULL, // HWND_NULL,
                            (SQLCHAR *)conn_str,
                            SQL_NTS,
                            (SQLCHAR *)out_str,
                            sizeof( out_str ),
                            &conn_str_len,
                            SQL_DRIVER_NOPROMPT );
    if( ret == 0 ) printf( "Connection succeed\n" );

    // Establish connection options

    // Use transactions instead of auto-commit
    ret = SQLSetConnectAttr( conn->dbc,
                             SQL_ATTR_AUTOCOMMIT,
                             (SQLPOINTER)SQL_AUTOCOMMIT_OFF,
                             SQL_IS_UINTEGER );
    if( ret == 0 ) printf( "Set Connection succeed\n" );

done:
    return( conn );
}

void Disconnect( p_ml_host_conn conn )
/************************************/
{
    if( conn != NULL ) {
        if( conn->dbc != SQL_NULL_HDBC ) {
            SQLDisconnect( conn->dbc );
            SQLFreeHandle( SQL_HANDLE_DBC, conn->dbc );
        }
    
        free( conn );
    }
}

void ShowBug( p_ml_host_conn conn )
/*********************************/
{

    SQLHSTMT stmt;
    RETCODE ret;
    int id;
    SQLINTEGER ind1=0, ind2=0;
    SQLWCHAR source[1001];
 

    ret = SQLAllocHandle( SQL_HANDLE_STMT, conn->dbc, &stmt );
    ret = SQLPrepare( stmt,
                      (SQLCHAR *)"select id, source from ssint2", SQL_NTS );
    ret = SQLExecute( stmt );

    ret = SQLBindCol( stmt, 1, SQL_C_SLONG, &id, 4, ind1 );
    ret = SQLBindCol( stmt, 2, SQL_C_WCHAR, source, sizeof( source), ind2);

    
    ret = SQLFetchScroll( stmt, SQL_FETCH_NEXT, 0 );

    while( ret == SQL_NO_DATA_FOUND ) {
       ret = SQLFetchScroll( stmt, SQL_FETCH_NEXT, 0 );
    }

    ret = SQLFreeHandle( SQL_HANDLE_STMT, stmt );

    ret = SQLEndTran( SQL_HANDLE_DBC, conn->dbc, SQL_ROLLBACK );
}

int main( int argc, char *argv[] )
/********************************/
{
    p_ml_host_data host = NULL;
    p_ml_host_conn conn = NULL;

    host = Init();
    if( host != NULL ) {
        argc = argc; // Unused
        conn = Connect( host, argv[ 1 ] );
        if( conn != NULL ) {
            // ===========================
            ShowBug( conn );
            // ===========================
            Disconnect( conn );
        }
        Fini( host );
    }

    return( 0 );
}



Relevant Pages

  • MS SQL Server 2000 ODBC driver crash
    ... If the SQL Server driver's option "Use ANSI nulls, paddings and warnings" ... is not set and the length of char is over 623, MS SQL Server driver will ...
    (microsoft.public.data.odbc)
  • Re: Run As Command
    ... Declare @VCHCOMMAND Char, ... if you are using BACKUP DATABASE command to backup the database then ... to use a seperate logon for the destination server. ... to SQL server bacause SQL Server cannot see that domain. ...
    (microsoft.public.sqlserver.security)
  • Re: Maintaining Field Length in .txt format
    ... If the types are VARCHAR, ... converts them to CHAR types. ... >are on a SQL Server 2000 environment and I can create ... The header information for the feed to be ...
    (microsoft.public.sqlserver.programming)
  • Re: returning @@RowCount
    ... use VARCHAR. ... CHAR will pad the data with spaces ... SQL Server MVP ... >> alter procedure stp_Family ...
    (microsoft.public.sqlserver.programming)
  • Re: CLOB Problem with DBD::ODBC/DBD::ADO for SQL Server
    ... I am unsure why the code does not insert CR\LF as I am 100% sure the file itself contains CR\LF. ... At 24000 chrs it works and at 48000 chrs you lose each \ followed by a. ... It is of no consolation to you but I have duplicated it with the MS SQL Server driver and also demonstrated it works fine with our sql server driver. ...
    (perl.dbi.users)