Skip to content

Commit d7e5a02

Browse files
diegomarquezplqiu96
authored andcommitted
fix(gax): prevent truncation/overflow when converting time values (#3095)
#1872 (comment) --------- Co-authored-by: Lawrence Qiu <[email protected]>
1 parent 5bc9823 commit d7e5a02

File tree

2 files changed

+50
-4
lines changed

2 files changed

+50
-4
lines changed

gax-java/gax/src/main/java/com/google/api/gax/util/TimeConversionUtils.java

+4-4
Original file line numberDiff line numberDiff line change
@@ -35,27 +35,27 @@ public static java.time.Duration toJavaTimeDuration(org.threeten.bp.Duration sou
3535
if (source == null) {
3636
return null;
3737
}
38-
return java.time.Duration.ofNanos(source.toNanos());
38+
return java.time.Duration.ofSeconds(source.getSeconds(), source.getNano());
3939
}
4040

4141
public static org.threeten.bp.Duration toThreetenDuration(java.time.Duration source) {
4242
if (source == null) {
4343
return null;
4444
}
45-
return org.threeten.bp.Duration.ofNanos(source.toNanos());
45+
return org.threeten.bp.Duration.ofSeconds(source.getSeconds(), source.getNano());
4646
}
4747

4848
public static java.time.Instant toJavaTimeInstant(org.threeten.bp.Instant source) {
4949
if (source == null) {
5050
return null;
5151
}
52-
return java.time.Instant.ofEpochMilli(source.toEpochMilli());
52+
return java.time.Instant.ofEpochSecond(source.getEpochSecond(), source.getNano());
5353
}
5454

5555
public static org.threeten.bp.Instant toThreetenInstant(java.time.Instant source) {
5656
if (source == null) {
5757
return null;
5858
}
59-
return org.threeten.bp.Instant.ofEpochMilli(source.toEpochMilli());
59+
return org.threeten.bp.Instant.ofEpochSecond(source.getEpochSecond(), source.getNano());
6060
}
6161
}

gax-java/gax/src/test/java/com/google/api/gax/util/TimeConversionUtilsTest.java

+46
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,12 @@
3737

3838
public class TimeConversionUtilsTest {
3939

40+
// 0.999999999 seconds (1 second - 1 nano) - we need to subtract the nano or the Duration would
41+
// overflow otherwise
42+
final long MAX_DURATION_NANOS =
43+
1 * 1000 /*=1 micro*/ * 1000 /*=1 milli*/ * 1000 /*=1 second*/ - 1;
44+
45+
// Arbitrary durations/instants to confirm conversion works as expected
4046
final org.threeten.bp.Duration ttDuration = org.threeten.bp.Duration.ofMillis(123);
4147
final org.threeten.bp.Instant ttInstant = org.threeten.bp.Instant.ofEpochMilli(123);
4248
final java.time.Duration jtDuration = java.time.Duration.ofMillis(345);
@@ -69,4 +75,44 @@ void testToThreetenTimeInstant_validInput_succeeds() {
6975
jtInstant.toEpochMilli(), TimeConversionUtils.toThreetenInstant(jtInstant).toEpochMilli());
7076
assertNull(TimeConversionUtils.toThreetenInstant(null));
7177
}
78+
79+
@Test
80+
void testToThreeteenInstant_bigInput_doesNotOverflow() {
81+
// defaults to MAX_SECONDS plus the max value of long for the nanos part
82+
java.time.Instant jtInstant = java.time.Instant.MAX;
83+
org.threeten.bp.Instant ttInstant = TimeConversionUtils.toThreetenInstant(jtInstant);
84+
assertEquals(jtInstant.getEpochSecond(), ttInstant.getEpochSecond());
85+
assertEquals(jtInstant.getNano(), ttInstant.getNano());
86+
}
87+
88+
@Test
89+
void testToJavaTimeInstant_bigInput_doesNotOverflow() {
90+
// defaults to MAX_SECONDS plus the max value of long for the nanos part
91+
org.threeten.bp.Instant ttInstant = org.threeten.bp.Instant.MAX;
92+
java.time.Instant jtInstant = TimeConversionUtils.toJavaTimeInstant(ttInstant);
93+
assertEquals(jtInstant.getEpochSecond(), ttInstant.getEpochSecond());
94+
assertEquals(jtInstant.getNano(), ttInstant.getNano());
95+
}
96+
97+
@Test
98+
void testToThreeteenDuration_bigInput_doesNotOverflow() {
99+
// we use the max long value for the seconds part and an arbitrary int for the nanos part, so we
100+
// can confirm that both components are preserved
101+
java.time.Duration jtDuration =
102+
java.time.Duration.ofSeconds(Long.MAX_VALUE, MAX_DURATION_NANOS);
103+
org.threeten.bp.Duration ttDuration = TimeConversionUtils.toThreetenDuration(jtDuration);
104+
assertEquals(jtDuration.getSeconds(), ttDuration.getSeconds());
105+
assertEquals(jtDuration.getNano(), ttDuration.getNano());
106+
}
107+
108+
@Test
109+
void testToJavaTimeDuration_bigInput_doesNotOverflow() {
110+
// we use the max long value for the seconds part and an arbitrary int for the nanos part, so we
111+
// can confirm that both components are preserved
112+
org.threeten.bp.Duration ttDuration =
113+
org.threeten.bp.Duration.ofSeconds(Long.MAX_VALUE, MAX_DURATION_NANOS);
114+
java.time.Duration jtDuration = TimeConversionUtils.toJavaTimeDuration(ttDuration);
115+
assertEquals(jtDuration.getSeconds(), ttDuration.getSeconds());
116+
assertEquals(jtDuration.getNano(), ttDuration.getNano());
117+
}
72118
}

0 commit comments

Comments
 (0)