Skip to content

Commit

Permalink
Fuzzer duckdb#590: MAKE_TIMESTAMPTZ Extreme Paranoia
Browse files Browse the repository at this point in the history
Wrap every transformation in the function body.
  • Loading branch information
Richard Wesley committed Aug 8, 2023
1 parent fd683b9 commit 6122490
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 7 deletions.
18 changes: 12 additions & 6 deletions extension/icu/icu-makedate.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
#include "duckdb/common/operator/add.hpp"
#include "duckdb/common/operator/cast_operators.hpp"
#include "duckdb/common/operator/subtract.hpp"
#include "duckdb/common/types/date.hpp"
#include "duckdb/common/types/time.hpp"
#include "duckdb/common/types/timestamp.hpp"
Expand Down Expand Up @@ -66,19 +68,23 @@ struct ICUMakeDate : public ICUDateFunc {
struct ICUMakeTimestampTZFunc : public ICUDateFunc {
template <typename T>
static inline timestamp_t Operation(icu::Calendar *calendar, T yyyy, T mm, T dd, T hr, T mn, double ss) {
const auto year = yyyy + (yyyy < 0);
const auto year = Cast::Operation<T, int32_t>(AddOperator::Operation<T, T, T>(yyyy, (yyyy < 0)));
const auto month = Cast::Operation<T, int32_t>(SubtractOperatorOverflowCheck::Operation<T, T, T>(mm, 1));
const auto day = Cast::Operation<T, int32_t>(dd);
const auto hour = Cast::Operation<T, int32_t>(hr);
const auto min = Cast::Operation<T, int32_t>(mn);

const auto secs = Cast::Operation<double, int32_t>(ss);
ss -= secs;
ss *= Interval::MSECS_PER_SEC;
const auto millis = int32_t(ss);
int64_t micros = std::round((ss - millis) * Interval::MICROS_PER_MSEC);

calendar->set(UCAL_YEAR, int32_t(year));
calendar->set(UCAL_MONTH, int32_t(mm - 1));
calendar->set(UCAL_DATE, int32_t(dd));
calendar->set(UCAL_HOUR_OF_DAY, int32_t(hr));
calendar->set(UCAL_MINUTE, int32_t(mn));
calendar->set(UCAL_YEAR, year);
calendar->set(UCAL_MONTH, month);
calendar->set(UCAL_DATE, day);
calendar->set(UCAL_HOUR_OF_DAY, hour);
calendar->set(UCAL_MINUTE, min);
calendar->set(UCAL_SECOND, secs);
calendar->set(UCAL_MILLISECOND, millis);

Expand Down
2 changes: 1 addition & 1 deletion test/fuzzer/sqlsmith/timestamptz_double_cast.test
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,4 @@ SELECT
OVER (PARTITION BY ref_0."smallint" ORDER BY ref_0.int_array) AS c2
FROM main.all_types AS ref_0
----
Invalid Input Error: Type DOUBLE with value
Invalid Input Error: Type INT64 with value
16 changes: 16 additions & 0 deletions test/sql/function/timestamp/test_icu_makedate.test
Original file line number Diff line number Diff line change
Expand Up @@ -408,3 +408,19 @@ SELECT ts, ts::DATE FROM timeparts
2021-05-02 05:11:49.5-07 2021-05-02
2021-12-01 05:54:48.123456-08 2021-12-01
NULL NULL

# Overflow
statement error
WITH all_types AS (
select * exclude(small_enum, medium_enum, large_enum)
from test_all_types()
)
SELECT make_timestamptz(
CAST(century(CAST(a."interval" AS INTERVAL)) AS BIGINT),
CAST(a."bigint" AS BIGINT), CAST(a."bigint" AS BIGINT),
CAST(a."bigint" AS BIGINT), CAST(a."bigint" AS BIGINT),
CAST(txid_current() AS BIGINT),
CAST(CAST(COALESCE(a."bigint", a."bigint") AS BIGINT) AS BIGINT))
FROM all_types a;
----
Overflow in subtraction

0 comments on commit 6122490

Please sign in to comment.