diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/json/WxDateTypeAdapter.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/json/WxDateTypeAdapter.java index fd54cf3f4..0dbad926c 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/json/WxDateTypeAdapter.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/json/WxDateTypeAdapter.java @@ -35,7 +35,12 @@ public Date read(JsonReader in) throws IOException { in.nextNull(); return null; case NUMBER: - return new Date(in.nextInt() * 1000); + long seconds = in.nextLong(); + try { + return new Date(Math.multiplyExact(seconds, 1000L)); + } catch (ArithmeticException e) { + throw new JsonParseException("Timestamp seconds out of range: " + seconds, e); + } default: throw new JsonParseException("Expected NUMBER but was " + peek); } diff --git a/weixin-java-common/src/test/java/me/chanjar/weixin/common/util/json/WxDateTypeAdapterTest.java b/weixin-java-common/src/test/java/me/chanjar/weixin/common/util/json/WxDateTypeAdapterTest.java new file mode 100644 index 000000000..66395b6b5 --- /dev/null +++ b/weixin-java-common/src/test/java/me/chanjar/weixin/common/util/json/WxDateTypeAdapterTest.java @@ -0,0 +1,47 @@ +package me.chanjar.weixin.common.util.json; + +import com.google.gson.JsonParseException; +import org.testng.annotations.Test; + +import java.io.IOException; +import java.util.Date; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +/** + * Tests for {@link WxDateTypeAdapter}. + */ +public class WxDateTypeAdapterTest { + private final WxDateTypeAdapter adapter = new WxDateTypeAdapter(); + + @Test + public void testReadTimestampAfter2038() throws IOException { + Date date = this.adapter.fromJson("4102444800"); + + assertThat(date).isEqualTo(new Date(4102444800000L)); + } + + @Test + public void testReadRejectsPositiveMillisecondOverflow() { + long overflowingSeconds = Long.MAX_VALUE / 1000 + 1; + + assertThatThrownBy(() -> this.adapter.fromJson(Long.toString(overflowingSeconds))) + .isInstanceOf(JsonParseException.class) + .hasMessageContaining("out of range"); + } + + @Test + public void testReadRejectsNegativeMillisecondOverflow() { + long overflowingSeconds = Long.MIN_VALUE / 1000 - 1; + + assertThatThrownBy(() -> this.adapter.fromJson(Long.toString(overflowingSeconds))) + .isInstanceOf(JsonParseException.class) + .hasMessageContaining("out of range"); + } + + @Test + public void testWriteUsesSeconds() throws IOException { + assertThat(this.adapter.toJson(new Date(4102444800123L))).isEqualTo("4102444800"); + } +} diff --git a/weixin-java-common/src/test/resources/testng.xml b/weixin-java-common/src/test/resources/testng.xml index a5c082f03..a11351308 100644 --- a/weixin-java-common/src/test/resources/testng.xml +++ b/weixin-java-common/src/test/resources/testng.xml @@ -7,6 +7,7 @@ +