From dad68c59fee5a484aa6b349a1ea957204d22295e Mon Sep 17 00:00:00 2001 From: Mark Tozzi Date: Fri, 15 Nov 2019 12:32:26 -0500 Subject: [PATCH] Avoid precision loss in DocValueFormat.RAW#parseLong (#49063) (#49169) --- .../main/java/org/elasticsearch/search/DocValueFormat.java | 6 ++++++ .../java/org/elasticsearch/search/DocValueFormatTests.java | 5 +++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/server/src/main/java/org/elasticsearch/search/DocValueFormat.java b/server/src/main/java/org/elasticsearch/search/DocValueFormat.java index 3c9e3dc3731..02ce9959bb3 100644 --- a/server/src/main/java/org/elasticsearch/search/DocValueFormat.java +++ b/server/src/main/java/org/elasticsearch/search/DocValueFormat.java @@ -117,6 +117,12 @@ public interface DocValueFormat extends NamedWriteable { @Override public long parseLong(String value, boolean roundUp, LongSupplier now) { + try { + // Prefer parsing as a long to avoid losing precision + return Long.parseLong(value); + } catch (NumberFormatException e) { + // retry as a double + } double d = Double.parseDouble(value); if (roundUp) { d = Math.ceil(d); diff --git a/server/src/test/java/org/elasticsearch/search/DocValueFormatTests.java b/server/src/test/java/org/elasticsearch/search/DocValueFormatTests.java index df948a5bff7..321ec43bb1d 100644 --- a/server/src/test/java/org/elasticsearch/search/DocValueFormatTests.java +++ b/server/src/test/java/org/elasticsearch/search/DocValueFormatTests.java @@ -168,6 +168,7 @@ public class DocValueFormatTests extends ESTestCase { public void testRawParse() { assertEquals(-1L, DocValueFormat.RAW.parseLong("-1", randomBoolean(), null)); assertEquals(1L, DocValueFormat.RAW.parseLong("1", randomBoolean(), null)); + assertEquals(Long.MAX_VALUE - 2, DocValueFormat.RAW.parseLong(Long.toString(Long.MAX_VALUE - 2), randomBoolean(), null)); // not checking exception messages as they could depend on the JVM expectThrows(IllegalArgumentException.class, () -> DocValueFormat.RAW.parseLong("", randomBoolean(), null)); expectThrows(IllegalArgumentException.class, () -> DocValueFormat.RAW.parseLong("abc", randomBoolean(), null)); @@ -176,8 +177,8 @@ public class DocValueFormatTests extends ESTestCase { assertEquals(1d, DocValueFormat.RAW.parseDouble("1", randomBoolean(), null), 0d); assertEquals(.5, DocValueFormat.RAW.parseDouble("0.5", randomBoolean(), null), 0d); // not checking exception messages as they could depend on the JVM - expectThrows(IllegalArgumentException.class, () -> DocValueFormat.RAW.parseLong("", randomBoolean(), null)); - expectThrows(IllegalArgumentException.class, () -> DocValueFormat.RAW.parseLong("abc", randomBoolean(), null)); + expectThrows(IllegalArgumentException.class, () -> DocValueFormat.RAW.parseDouble("", randomBoolean(), null)); + expectThrows(IllegalArgumentException.class, () -> DocValueFormat.RAW.parseDouble("abc", randomBoolean(), null)); assertEquals(new BytesRef("abc"), DocValueFormat.RAW.parseBytesRef("abc")); }