Uploaded image for project: 'MariaDB Connector/ODBC'
  1. MariaDB Connector/ODBC
  2. ODBC-289

Crash fetching from statement after closing and re-executing

    XMLWordPrintable

    Details

    • Type: Bug
    • Status: Closed (View Workflow)
    • Priority: Major
    • Resolution: Fixed
    • Affects Version/s: 3.1.9
    • Fix Version/s: 3.1.10
    • Component/s: General
    • Labels:
      None
    • Environment:
      Fedora 32

      Description

      If SQL_ATTR_ROW_ARRAY_SIZE is set to a value greater than one and you close a cursor by calling SQLFreeStmt with SQL_CLOSE and then start a new query with SQLExecute then the first fetch will cause an attempt to write to the old Stmt->result buffer which was freed when the statement was closed.

      Here's a summary of the valgrind report when this is triggered:

      ==427925== Invalid write of size 8
      ==427925==    at 0x1AE91262: mthd_stmt_fetch_to_bind (mariadb_stmt.c:409 in /usr/lib64/libmariadb.so.3)
      ==427925==    by 0x1AE92DB3: mysql_stmt_fetch (mariadb_stmt.c:1459 in /usr/lib64/libmariadb.so.3)
      ==427925==    by 0x1AE3D7B4: MoveNext (ma_result.c:63 in /usr/lib64/libmaodbc.so)
      ==427925==    by 0x1AE3A344: MADB_StmtFetch (ma_statement.c:2036 in /usr/lib64/libmaodbc.so)
      ==427925==    by 0x1AE32B61: MADB_StmtFetchScroll (ma_statement.c:4596 in /usr/lib64/libmaodbc.so)
      ==427925==    by 0x1AE21916: SQLFetch (odbc_3_api.c:1415 in /usr/lib64/libmaodbc.so)
      ==427925==    by 0x1A9BAE51: SQLFetch (SQLFetch.c:301 in /usr/lib64/libodbc.so.2.0.0)
      ==427925==  Address 0x1b441040 is 80 bytes inside a block of size 336 free'd
      ==427925==    at 0x483B9F5: free (vg_replace_malloc.c:538 in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
      ==427925==    by 0x1AE3687E: MADB_StmtFree (ma_statement.c:205 in /usr/lib64/libmaodbc.so)
      ==427925==    by 0x1A9BC9E9: SQLFreeStmt (SQLFreeStmt.c:218 in /usr/lib64/libodbc.so.2.0.0)
      ==427925==  Block was alloc'd at
      ==427925==    at 0x483CAE9: calloc (vg_replace_malloc.c:760 in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
      ==427925==    by 0x1AE3A3AE: MADB_StmtFetch (ma_statement.c:2003 in /usr/lib64/libmaodbc.so)
      ==427925==    by 0x1AE32B61: MADB_StmtFetchScroll (ma_statement.c:4596 in /usr/lib64/libmaodbc.so)
      ==427925==    by 0x1AE21916: SQLFetch (odbc_3_api.c:1415 in /usr/lib64/libmaodbc.so)
      ==427925==    by 0x1A9BAE51: SQLFetch (SQLFetch.c:301 in /usr/lib64/libodbc.so.2.0.0)
      

      The trigger is that when doing a multi-row fetch MADB_StmtFetch tries to read the first row with MoveNext without calling mysql_stmt_bind_result to bind the result area first.

      On the first execution that is fine as no bind has been done so the C API doesn't try to write the results back.

      On the second execution the library still has the binds from the first time, and tries to write to them, but they point at the old result buffer that was freed when SQLFreeStmt was called to close the cursor.

      If we're not doing a multi-row fetch then we're fine as the new result buffer will be bound with mysql_stmt_bind_result before the rows are fetched for real - it is only this special pre-read fetch of the first row that doesn't bind first.

      It might be that this is a bug in the C connector as the close does call mysql_stmt_free_result but that doesn't currently reset the binds, and it is not clear if it is supposed to or not.

        Attachments

          Issue Links

            Activity

              People

              Assignee:
              Lawrin Lawrin Novitsky
              Reporter:
              TomH Tom Hughes
              Votes:
              0 Vote for this issue
              Watchers:
              3 Start watching this issue

                Dates

                Created:
                Updated:
                Resolved:

                  Git Integration