postgresql-jdbc.git / summary / log / commit / refs
commit ec06d5871cd61310fbdc50e275d53565fcd3264e
Author: Sehrope Sarkuni <sehrope@jackdb.com>
Date: Thu Jun 11 14:12:59 2026 +0000
fix: reject out of range and NaN values in PGInterval.setSeconds
PGInterval.setSeconds validated its argument against the long range in
microseconds, but the wholeSeconds field is an int and the cast after
division truncated without any check. Values beyond the int range of
whole seconds, about 68 years, silently wrapped. For example
new PGInterval(0, 0, 0, 0, 0, 3000000000.0) produced a negative
interval with no exception. The old error message also described a
bound that the code never enforced on the stored field.
The whole seconds value is now computed as a long and checked against
the int range before being stored, so out of range values throw
IllegalArgumentException instead of wrapping. NaN is rejected
explicitly because it passed the old comparisons and Math.round mapped
it to zero, turning NaN input into a zero interval. Infinite values are
caught by the range check since Math.round saturates at the long
bounds. The isNull flag is now only cleared after validation succeeds
so a rejected value no longer mutates the object.
.../src/main/java/org/postgresql/util/PGInterval.java | 18 +++++++++++-------
1 file changed, 11 insertions(+), 7 deletions(-)
diff --git a/pgjdbc/src/main/java/org/postgresql/util/PGInterval.java b/pgjdbc/src/main/java/org/postgresql/util/PGInterval.java
index 076c6be3..4e54ea26 100644
--- a/pgjdbc/src/main/java/org/postgresql/util/PGInterval.java
+++ b/pgjdbc/src/main/java/org/postgresql/util/PGInterval.java
@@ -427,14 +427,18 @@ public class PGInterval extends PGobject implements Serializable, Cloneable {
* @param seconds seconds to set
*/
public void setSeconds(double seconds) {
- isNull = false;
-
- double micros = seconds * MICROS_IN_SECOND;
- if (micros > Long.MAX_VALUE || micros < Long.MIN_VALUE) {
- throw new IllegalArgumentException("Number of seconds should be within Long.MIN_VALUE/1000000...Long.MAX_VALUE/1000000");
+ if (Double.isNaN(seconds)) {
+ throw new IllegalArgumentException("Number of seconds must not be NaN");
}
- long totalMicros = Math.round(micros);
- wholeSeconds = (int) (totalMicros / MICROS_IN_SECOND);
+ // Math.round saturates at Long.MAX_VALUE / Long.MIN_VALUE so the division below
+ // cannot overflow even for infinite or extremely large arguments
+ long totalMicros = Math.round(seconds * MICROS_IN_SECOND);
+ long newWholeSeconds = totalMicros / MICROS_IN_SECOND;
+ if (newWholeSeconds < Integer.MIN_VALUE || newWholeSeconds > Integer.MAX_VALUE) {
+ throw new IllegalArgumentException("Number of whole seconds should be within Integer.MIN_VALUE...Integer.MAX_VALUE");
+ }
+ isNull = false;
+ wholeSeconds = (int) newWholeSeconds;
microSeconds = (int) (totalMicros % MICROS_IN_SECOND);
}
[parent: bab4cb85d2de]