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));