You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@iceberg.apache.org by ze...@apache.org on 2026/07/27 20:30:01 UTC
(iceberg-go) branch main updated: fix(literals): reject timestamp nanos overflow (#1533)
This is an automated email from the ASF dual-hosted git repository.
zeroshade pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/iceberg-go.git
The following commit(s) were added to refs/heads/main by this push:
new f8cc75a45 fix(literals): reject timestamp nanos overflow (#1533)
f8cc75a45 is described below
commit f8cc75a458ddbf58c31adc906b9f90e593d87216
Author: Minh Vu <vu...@gmail.com>
AuthorDate: Mon Jul 27 22:29:49 2026 +0200
fix(literals): reject timestamp nanos overflow (#1533)
## Summary
- check microsecond timestamp bounds before converting to nanoseconds
- return ErrBadCast instead of silently wrapping int64 values
- cover both timestamp_ns variants and both overflow directions
This follows the checked multiplication used by the Java implementation.
## Testing
- go test . -count=1
- all repository packages except io/gocloud
---
literals.go | 8 +++++---
literals_test.go | 29 +++++++++++++++++++++++++++++
2 files changed, 34 insertions(+), 3 deletions(-)
diff --git a/literals.go b/literals.go
index ec5a5fced..5a0a068de 100644
--- a/literals.go
+++ b/literals.go
@@ -824,9 +824,11 @@ func (t TimestampLiteral) To(typ Type) (Literal, error) {
return t, nil
case TimestampTzType:
return t, nil
- case TimestampNsType:
- return TimestampNsLiteral(Timestamp(t).ToNanos()), nil
- case TimestampTzNsType:
+ case TimestampNsType, TimestampTzNsType:
+ if t > math.MaxInt64/1000 || t < math.MinInt64/1000 {
+ return nil, fmt.Errorf("%w: timestamp %d is outside the nanosecond range", ErrBadCast, t)
+ }
+
return TimestampNsLiteral(Timestamp(t).ToNanos()), nil
case DateType:
return DateLiteral(Timestamp(t).ToDate()), nil
diff --git a/literals_test.go b/literals_test.go
index e4715dda7..42875df10 100644
--- a/literals_test.go
+++ b/literals_test.go
@@ -235,6 +235,35 @@ func TestTimestampNanoLiteralConversions(t *testing.T) {
}
}
+func TestTimestampLiteralToNanosRejectsOverflow(t *testing.T) {
+ targets := []iceberg.Type{
+ iceberg.PrimitiveTypes.TimestampNs,
+ iceberg.PrimitiveTypes.TimestampTzNs,
+ }
+
+ for _, target := range targets {
+ t.Run(target.String(), func(t *testing.T) {
+ for _, value := range []iceberg.TimestampLiteral{
+ iceberg.TimestampLiteral(math.MaxInt64/1000 + 1),
+ iceberg.TimestampLiteral(math.MinInt64/1000 - 1),
+ } {
+ actual, err := value.To(target)
+ assert.Nil(t, actual)
+ assert.ErrorIs(t, err, iceberg.ErrBadCast)
+ }
+
+ for _, value := range []iceberg.TimestampLiteral{
+ iceberg.TimestampLiteral(math.MaxInt64 / 1000),
+ iceberg.TimestampLiteral(math.MinInt64 / 1000),
+ } {
+ actual, err := value.To(target)
+ require.NoError(t, err)
+ assert.Equal(t, iceberg.TimestampNsLiteral(value*1000), actual)
+ }
+ })
+ }
+}
+
func TestInt64Conversions(t *testing.T) {
tests := []struct {
from iceberg.Int64Literal