vikrantpuppala opened a new issue, #50560:
URL: https://github.com/apache/arrow/issues/50560

   # [C++][FlightRPC][ODBC] SQLDescribeCol writes only 2 of 8 bytes of 
column_size for numeric/decimal columns
   
   ### Describe the bug, including details regarding any error messages, 
version, and platform.
   
   In the Arrow Flight SQL ODBC driver, `SQLDescribeCol` returns garbage in the
   upper bytes of the `column_size` (a.k.a. `ColumnSizePtr`) output argument for
   numeric / decimal columns. Only the low 2 bytes are written; the upper 6 
bytes
   are left uninitialized.
   
   **Root cause — a write-width mismatch.**
   
   `DescriptorRecord::precision` is declared `SQLSMALLINT` (2 bytes) in
   `cpp/src/arrow/flight/sql/odbc/odbc_impl/odbc_descriptor.h`:
   
   ```cpp
   SQLSMALLINT precision = 0;   // ~line 58
   ...
   SQLSMALLINT scale = 0;       // ~line 60
   ```
   
   `ODBCDescriptor::GetField(SQL_DESC_PRECISION, ...)` forwards to the 
`GetAttribute`
   template in `cpp/src/arrow/flight/sql/odbc/odbc_impl/odbc_descriptor.cc`
   (~line 417):
   
   ```cpp
   case SQL_DESC_PRECISION:
     GetAttribute(record.precision, value, buffer_length, output_length);
     break;
   ```
   
   and that template 
(`cpp/src/arrow/flight/sql/odbc/odbc_impl/attribute_utils.h`)
   copies exactly `sizeof(T)` bytes — `T` being deduced from the field, i.e.
   `SQLSMALLINT` (2 bytes). The `buffer_length` argument is **ignored** for the
   write:
   
   ```cpp
   template <typename T, typename O>
   inline void GetAttribute(T attribute_value, SQLPOINTER output, O output_size,
                            O* output_len_ptr) {
     if (output) {
       T* typed_output = reinterpret_cast<T*>(output);  // reinterprets the 
caller's pointer
       *typed_output = attribute_value;                 // writes only 
sizeof(T) = 2 bytes
     }
     ...
   }
   ```
   
   But in `SQLDescribeCol`
   (`cpp/src/arrow/flight/sql/odbc/odbc_api.cc`, ~line 1584) the numeric path
   passes the `SQLULEN* column_size_ptr` (8 bytes) directly and claims
   `sizeof(SQLULEN)`:
   
   ```cpp
   case SQL_DOUBLE: {
     ird->GetField(column_number, SQL_DESC_PRECISION, column_size_ptr,
                   sizeof(SQLULEN), nullptr);
     break;
   }
   ```
   
   `GetAttribute` then reinterprets the `SQLULEN*` as a `SQLSMALLINT*` and 
writes
   only 2 bytes. **The upper 6 bytes of the caller's `SQLULEN` remain
   uninitialized garbage.** An application that reads the full 8-byte 
`column_size`
   (the correct ODBC type for `ColumnSizePtr`) sees a wildly wrong value for 
every
   `DECIMAL` / `NUMERIC` / integer / `REAL` / `FLOAT` / `DOUBLE` column.
   
   **Two related, lower-severity smells at the `decimal_digits` sites.** The
   `SQL_DESC_SCALE` path (~line 1606) and the datetime/interval 
`SQL_DESC_PRECISION`
   path (~line 1624) pass `sizeof(SQLULEN)` (8) as the buffer size even though
   `decimal_digits_ptr` is a `SQLSMALLINT*` (2 bytes) and the underlying field 
is a
   2-byte `SQLSMALLINT`. These do **not** corrupt memory today (the write width 
is
   2 bytes, matching the 2-byte target), but the claimed buffer size is wrong 
and
   misleading. They should pass `sizeof(SQLSMALLINT)`.
   
   **Trace of the affected call sites** (all in `odbc_api.cc::SQLDescribeCol`):
   
   1. `SQL_DESC_PRECISION → column_size_ptr` (numeric/decimal) — **the real 
bug**:
      2-byte write into an 8-byte `SQLULEN`, upper 6 bytes garbage.
   2. `SQL_DESC_SCALE → decimal_digits_ptr` (exact numeric) — wrong `sizeof`, no
      corruption.
   3. `SQL_DESC_PRECISION → decimal_digits_ptr` (datetime / 
interval-with-seconds)
      — wrong `sizeof`, no corruption.
   
   ### Introduced by
   
   PR apache/arrow#48052 (GH-47724, "[C++][FlightRPC][ODBC] implement
   SQLDescribeCol"). The bug is still present on `main`.
   
   ### Component(s)
   
   C++, FlightRPC
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to