This is an automated email from the ASF dual-hosted git repository.

lidavidm pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow-adbc.git


The following commit(s) were added to refs/heads/main by this push:
     new e7fa7c6c fix(c/driver/postgresql): check for underflow (#1389)
e7fa7c6c is described below

commit e7fa7c6cdf8abaf0d8fbcd5d678d03f1080add43
Author: David Li <[email protected]>
AuthorDate: Wed Dec 20 15:16:59 2023 -0500

    fix(c/driver/postgresql): check for underflow (#1389)
    
    Fixes #1190.
---
 c/driver/postgresql/postgres_copy_reader.h | 19 ++++++++++++++++---
 c/driver/postgresql/statement.cc           | 15 +++++++++++++--
 2 files changed, 29 insertions(+), 5 deletions(-)

diff --git a/c/driver/postgresql/postgres_copy_reader.h 
b/c/driver/postgresql/postgres_copy_reader.h
index 66a31418..7ba29ea3 100644
--- a/c/driver/postgresql/postgres_copy_reader.h
+++ b/c/driver/postgresql/postgres_copy_reader.h
@@ -17,10 +17,14 @@
 
 #pragma once
 
+// Windows
+#define NOMINMAX
+
 #include <algorithm>
 #include <cerrno>
 #include <cinttypes>
 #include <cstdint>
+#include <limits>
 #include <memory>
 #include <string>
 #include <utility>
@@ -68,6 +72,9 @@ constexpr int64_t kMaxSafeMicrosToNanos = 9223372036854775L;
 // without overflow
 constexpr int64_t kMinSafeMicrosToNanos = -9223372036854775L;
 
+// 2000-01-01 00:00:00.000000 in microseconds
+constexpr int64_t kPostgresTimestampEpoch = 946684800000000L;
+
 // Read a value from the buffer without checking the buffer size. Advances
 // the cursor of data and reduces its size by sizeof(T).
 template <typename T>
@@ -1333,14 +1340,20 @@ class PostgresCopyTimestampFieldWriter : public 
PostgresCopyFieldWriter {
 
     if (!overflow_safe) {
       ArrowErrorSet(error,
-                    "Row %" PRId64 " timestamp value %" PRId64
+                    "[libpq] Row %" PRId64 " timestamp value %" PRId64
                     " with unit %d would overflow",
                     index, raw_value, TU);
       return ADBC_STATUS_INVALID_ARGUMENT;
     }
 
-    // 2000-01-01 00:00:00.000000 in microseconds
-    constexpr int64_t kPostgresTimestampEpoch = 946684800000000;
+    if (value < std::numeric_limits<int64_t>::min() + kPostgresTimestampEpoch) 
{
+      ArrowErrorSet(error,
+                    "[libpq] Row %" PRId64 " timestamp value %" PRId64
+                    " with unit %d would underflow",
+                    index, raw_value, TU);
+      return ADBC_STATUS_INVALID_ARGUMENT;
+    }
+
     const int64_t scaled = value - kPostgresTimestampEpoch;
     NANOARROW_RETURN_NOT_OK(WriteChecked<int64_t>(buffer, scaled, error));
 
diff --git a/c/driver/postgresql/statement.cc b/c/driver/postgresql/statement.cc
index 656e1876..6c0541a6 100644
--- a/c/driver/postgresql/statement.cc
+++ b/c/driver/postgresql/statement.cc
@@ -15,6 +15,9 @@
 // specific language governing permissions and limitations
 // under the License.
 
+// Windows
+#define NOMINMAX
+
 #include "statement.h"
 
 #include <array>
@@ -23,6 +26,7 @@
 #include <cinttypes>
 #include <cstring>
 #include <iostream>
+#include <limits>
 #include <memory>
 #include <utility>
 #include <vector>
@@ -432,8 +436,6 @@ struct BindStream {
             case ArrowType::NANOARROW_TYPE_TIMESTAMP: {
               int64_t val = 
array_view->children[col]->buffer_views[1].data.as_int64[row];
 
-              // 2000-01-01 00:00:00.000000 in microseconds
-              constexpr int64_t kPostgresTimestampEpoch = 946684800000000;
               bool overflow_safe = true;
 
               auto unit = bind_schema_fields[col].time_unit;
@@ -469,6 +471,15 @@ struct BindStream {
                 return ADBC_STATUS_INVALID_ARGUMENT;
               }
 
+              if (val < std::numeric_limits<int64_t>::min() + 
kPostgresTimestampEpoch) {
+                SetError(error,
+                         "[libpq] Field #%" PRId64 " ('%s') Row #%" PRId64
+                         " has value '%" PRIi64 "' which would underflow",
+                         col + 1, bind_schema->children[col]->name, row + 1,
+                         
array_view->children[col]->buffer_views[1].data.as_int64[row]);
+                return ADBC_STATUS_INVALID_ARGUMENT;
+              }
+
               if (bind_schema_fields[col].type == 
ArrowType::NANOARROW_TYPE_TIMESTAMP) {
                 const uint64_t value = ToNetworkInt64(val - 
kPostgresTimestampEpoch);
                 std::memcpy(param_values[col], &value, sizeof(int64_t));

Reply via email to