Blog Post

SQL Server Blog
1 MIN READ

Update: ODBC Driver 18.1.2 for SQL Server Released

David-Engel's avatar
David-Engel
Iron Contributor
Nov 03, 2022

Version 18.1.2 of the Microsoft ODBC Driver 18 for SQL Server has been released. Version 18.1.2 brings a few fixes to the driver.

 

Fixes

  • Fix VBS-NONE enclave attestation protocol
  • Fix error when retrieving numeric column with Regional=Yes
  • Fix intermittent lack of error when server is stopped during bcp out operation
  • Fix error when stored procedure call contains unquoted string parameter

Next steps

For Windows installations, you can directly download the Microsoft ODBC Driver 18 for SQL Server.

Linux and macOS packages are also available. For installation details see the online instructions for Linux or macOS.

 

Roadmap

We are committed to improving quality and bringing more feature support for connecting to SQL Server Azure SQL Database Azure SQL DW, and Azure SQL Managed Instance through regular driver releases. We invite you to explore the latest the Microsoft Data Platform has to offer via a trial of Microsoft Azure SQL Database or by evaluating Microsoft SQL Server.

David Engel

Updated Dec 06, 2022
Version 2.0

14 Comments

  • YOSHIZAKI_Shota's avatar
    YOSHIZAKI_Shota
    Copper Contributor

    AddressSanitizer warnings memory leaks occured when repeating connecting/disconnecting to a db with msodbcsql for linux both 17.10 and 18.1.

     

    This may be same issue as this comment https://techcommunity.microsoft.com/t5/sql-server-blog/odbc-driver-17-6-for-sql-server-released/bc-p/1954999/highlight/true#M1658 .

    I have a reproduction code. 

     

     

    My program repeats connecting and disconnecting to a db server.

     

    pseud code

    AllocHandle(hEnv)
    AllocHandle(hDbc)
    
    repeat N
      Connect(hDbc)
      Disconnect(hDbc)
    
    FreeHandle(hDbc)
    FeeHandle(hEnv)

    When N > 1, AddressSanitizer outputs memory leak detections.

     

    Also I tried like below and got same warnings.

    repeat N
      AllocHandle(hEnv)
      AllocHandle(hDbc)
    
      Connect(hDbc)
      Disconnect(hDbc)
    
      FreeHandle(hDbc)
      FeeHandle(hEnv)

     

    I want to know this is a false-positive detection or not.

    Or, is there a workaround ?

     

    Thank you.

     

    The details are listed below.

     

    Environment

    OracleLinux 8.6

    GCC11 with AddressSanitizer

     

    Packages

     

    $ dnf list --installed | grep gcc
    gcc-toolset-11-binutils.x86_64          2.36.1-2.0.1.el8                                  @ol8_appstream              
    gcc-toolset-11-gcc.x86_64               11.2.1-9.1.0.2.el8                                @ol8_appstream              
    gcc-toolset-11-gcc-c++.x86_64           11.2.1-9.1.0.2.el8                                @ol8_appstream              
    gcc-toolset-11-libasan-devel.x86_64     11.2.1-9.1.0.2.el8                                @ol8_appstream              
    gcc-toolset-11-libstdc++-devel.x86_64   11.2.1-9.1.0.2.el8                                @ol8_appstream              
    gcc-toolset-11-runtime.x86_64           11.1-1.el8                                        @ol8_appstream              
    libgcc.x86_64                           8.5.0-10.1.0.1.el8_6                              @System       
    
    
    $ dnf list --installed | grep unixODBC
    unixODBC.x86_64                         2.3.7-1.rh                                        @packages-microsoft-com-prod
    unixODBC-devel.x86_64                   2.3.7-1.rh                                        @packages-microsoft-com-prod
    
    $ dnf list --installed | grep msodbc
    msodbcsql17.x86_64                      17.10.1.1-1                                       @packages-microsoft-com-prod
    msodbcsql18.x86_64                      18.1.2.1-1                                        @packages-microsoft-com-prod
    

     

     

    SourceCode

    main.c

    rewrite L56 when using.

    #include <msodbcsql.h>
    #include <sql.h>
    #include <sqlext.h>
    #include <stddef.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
     
    void HandleDiagnosticRecord(SQLHANDLE hHandle, SQLSMALLINT hType, RETCODE RetCode) {
      SQLSMALLINT iRec = 0;
      SQLINTEGER iError;
      char wszMessage[1000];
      char wszState[SQL_SQLSTATE_SIZE + 1];
     
      if (RetCode == SQL_INVALID_HANDLE) {
        fprintf(stderr, "Invalid handle!\n");
        return;
      }
     
      while (SQLGetDiagRec(hType, hHandle, ++iRec, wszState, &iError, wszMessage,
                           (SQLSMALLINT)(sizeof(wszMessage) / sizeof(char)), (SQLSMALLINT *)NULL) == SQL_SUCCESS) {
        // Hide data truncated..
        if (strncmp(wszState, "01004", 5)) {
          fprintf(stderr, "[%5.5s] %s (%d)\n", wszState, wszMessage, iError);
        }
      }
    }
     
    #define TRYODBC(h, ht, x)                   \
      {                                         \
        RETCODE rc = x;                         \
        if (rc != SQL_SUCCESS) {                \
          HandleDiagnosticRecord(h, ht, rc);    \
        }                                       \
        if (rc == SQL_ERROR) {                  \
          fprintf(stderr, "Error in " #x "\n"); \
          goto Exit;                            \
        }                                       \
      }
     
    int main(void) {
      SQLHENV hEnv = NULL;
      SQLHDBC hDbc = NULL;
     
      if (SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &hEnv) == SQL_ERROR) {
        fprintf(stderr, "Unable to allocate an environment handle\n");
        exit(-1);
      }
     
      TRYODBC(hEnv, SQL_HANDLE_ENV, SQLSetEnvAttr(hEnv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, 0));
     
      TRYODBC(hEnv, SQL_HANDLE_ENV, SQLAllocHandle(SQL_HANDLE_DBC, hEnv, &hDbc));
     
      const int LOOP = 2;  // (LOOP - 1) * 24byte direct leak detected
      for (int i = 0; i < LOOP; i++) {
        const char *connStr = "CONNECTION STRING";
        TRYODBC(hDbc, SQL_HANDLE_DBC,
                SQLDriverConnect(hDbc, NULL, (SQLCHAR *)connStr, strlen(connStr), NULL, 0, NULL, SQL_DRIVER_NOPROMPT));
     
        printf("Connected!\n");
     
        TRYODBC(hDbc, SQL_HANDLE_DBC, SQLDisconnect(hDbc));
     
        printf("Disconnected\n");
      }
     
    Exit:
      if (hDbc) {
        SQLDisconnect(hDbc);
        SQLFreeHandle(SQL_HANDLE_DBC, hDbc);
        hDbc = NULL;
      }
     
      if (hEnv) {
        SQLFreeHandle(SQL_HANDLE_ENV, hEnv);
        hEnv = NULL;
      }
      return 0;
    }

     

    build and run 

    $ gcc main.c -std=c11 -I/opt/microsoft/msodbcsql18/include -lodbc -g -O0 -fsanitize=address -lasan -o main.o
    
    $ ./main.o
    [01000] [Microsoft][ODBC Driver 18 for SQL Server][SQL Server]Changed database context to 'master'. (5701)
    [01000] [Microsoft][ODBC Driver 18 for SQL Server][SQL Server]Changed language setting to us_english. (5703)
    Connected!
    Disconnected
    [01000] [Microsoft][ODBC Driver 18 for SQL Server][SQL Server]Changed database context to 'master'. (5701)
    [01000] [Microsoft][ODBC Driver 18 for SQL Server][SQL Server]Changed language setting to us_english. (5703)
    Connected!
    Disconnected
     
    =================================================================
    ==1103==ERROR: LeakSanitizer: detected memory leaks
     
    Direct leak of 24 byte(s) in 1 object(s) allocated from:
        #0 0x7f8f00b21307 in operator new(unsigned long) (/lib64/libasan.so.6+0xb6307)
        #1 0x7f8efbb5b2ca  (/opt/microsoft/msodbcsql18/lib64/libmsodbcsql-18.1.so.2.1+0x1822ca)
     
    Indirect leak of 88 byte(s) in 1 object(s) allocated from:
        #0 0x7f8f00b21307 in operator new(unsigned long) (/lib64/libasan.so.6+0xb6307)
        #1 0x7f8efbae3379  (/opt/microsoft/msodbcsql18/lib64/libmsodbcsql-18.1.so.2.1+0x10a379)
     
    SUMMARY: AddressSanitizer: 112 byte(s) leaked in 2 allocation(s).

     

     

  • juanrgm's avatar
    juanrgm
    Copper Contributor

    This update broke the "SQL Server" driver (sqlsrv32.dll v10.0.19041.2251).

     

    Now we can't read decimal values with the `SQLGetData` function, it returns always `SQL_NULL_DATA` and sometimes memory corruption (possible stack overflow?).

     

    Thousands of computers are being affected by this bug.