Skip to content

[BUG] Heap corruption when fetching 'long' binary data #428

@matthew-wozniczka

Description

@matthew-wozniczka

I encountered some heap corruption when using this library. We've forked it to fix that issue (& some others, might also bring them up here later), but it's a pain for me to create a pull request, so I'll just share the diff of our internal fix here, hopefully that's helpful:

$ git -C src show 42d678d539a6eb2a7f85f8466121fbc399328d8d
commit 42d678d539a6eb2a7f85f8466121fbc399328d8d
Author: Matthew Wozniczka <Matthew.Wozniczka@insightsoftware.com>
Date:   Fri Jun 27 19:03:03 2025 -0700

    [SC-292] Fix a bug where it used the value `SQL_NO_TOTAL` as if it were an actual length while fetching 'long' binary data, causing a buffer overflow (writing _before_ the start of the buffer, corrupting the heap)

diff --git a/src/odbc_connection.cpp b/src/odbc_connection.cpp
index 4f1313c..e5b9106 100644
--- a/src/odbc_connection.cpp
+++ b/src/odbc_connection.cpp
@@ -21,6 +21,7 @@
 #include "odbc_statement.h"
 #include "odbc_cursor.h"

+#include <cassert>
 #include <cstdint>

 #define MAX_UTF8_BYTES 4
@@ -3709,11 +3710,17 @@ fetch_and_store
                   {
                     case SQL_C_BINARY:
                     {
-                      data_returned_length = (
-                        row[column_index].size + string_length_or_indicator <= buffer_size ?
-                        string_length_or_indicator :
-                        buffer_size - row[column_index].size
-                      );
+                      if ((SQL_NO_TOTAL == string_length_or_indicator) ||
+                          (string_length_or_indicator > buffer_size))
+                      {
+                        data_returned_length = buffer_size;
+                      }
+                      else
+                      {
+                        assert(string_length_or_indicator >= 0);
+                        data_returned_length = string_length_or_indicator;
+                      }
+
                       buffer_size =
                         string_length_or_indicator == SQL_NO_TOTAL ?
                         buffer_size * 2 :

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions