diff --git a/docs/en/changes/changes.md b/docs/en/changes/changes.md index 49d72f6a19..af1e9e224a 100644 --- a/docs/en/changes/changes.md +++ b/docs/en/changes/changes.md @@ -8,6 +8,7 @@ * Add component ID(133) for impala JDBC Java agent plugin and component ID(134) for impala server * Use prepareStatement in H2SQLExecutor#getByIDs.(No function change). * Bump up snakeyaml to 1.31 for fixing CVE-2022-25857 +* Fix `DurationUtils.convertToTimeBucket` missed verify date format. #### UI diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/DurationUtils.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/DurationUtils.java index db14658432..d74c98ec3a 100644 --- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/DurationUtils.java +++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/DurationUtils.java @@ -46,48 +46,41 @@ public enum DurationUtils { * Convert date in `yyyy-MM-dd HHmmss` style to `yyyyMMddHHmmss` no matter the precision. Such as, in day precision, * this covert `yyyy-MM-dd` style to `yyyyMMdd`. */ - public long convertToTimeBucket(String dateStr) { + public long convertToTimeBucket(Step step, String dateStr) { + verifyDateTimeString(step, dateStr); dateStr = dateStr.replaceAll(Const.LINE, Const.EMPTY_STRING); dateStr = dateStr.replaceAll(Const.SPACE, Const.EMPTY_STRING); return Long.parseLong(dateStr); } public long startTimeDurationToSecondTimeBucket(Step step, String dateStr) { - long secondTimeBucket = 0; + long secondTimeBucket = convertToTimeBucket(step, dateStr); switch (step) { case DAY: - secondTimeBucket = convertToTimeBucket(dateStr) * 100 * 100 * 100; - break; + return secondTimeBucket * 100 * 100 * 100; case HOUR: - secondTimeBucket = convertToTimeBucket(dateStr) * 100 * 100; - break; + return secondTimeBucket * 100 * 100; case MINUTE: - secondTimeBucket = convertToTimeBucket(dateStr) * 100; - break; + return secondTimeBucket * 100; case SECOND: - secondTimeBucket = convertToTimeBucket(dateStr); - break; + return secondTimeBucket; } - return secondTimeBucket; + throw new UnexpectedException("Unsupported step " + step.name()); } public long endTimeDurationToSecondTimeBucket(Step step, String dateStr) { - long secondTimeBucket = 0; + long secondTimeBucket = convertToTimeBucket(step, dateStr); switch (step) { case DAY: - secondTimeBucket = ((convertToTimeBucket(dateStr) * 100 + 99) * 100 + 99) * 100 + 99; - break; + return ((secondTimeBucket * 100 + 23) * 100 + 59) * 100 + 59; case HOUR: - secondTimeBucket = (convertToTimeBucket(dateStr) * 100 + 99) * 100 + 99; - break; + return (secondTimeBucket * 100 + 59) * 100 + 59; case MINUTE: - secondTimeBucket = convertToTimeBucket(dateStr) * 100 + 99; - break; + return secondTimeBucket * 100 + 59; case SECOND: - secondTimeBucket = convertToTimeBucket(dateStr); - break; + return secondTimeBucket; } - return secondTimeBucket; + throw new UnexpectedException("Unsupported step " + step.name()); } public List getDurationPoints(Step step, long startTimeBucket, long endTimeBucket) { @@ -163,7 +156,7 @@ public enum DurationUtils { throw new UnexpectedException("Unsupported step " + step.name()); } - private DateTime parseToDateTime(Step step, long time) { + public DateTime parseToDateTime(Step step, long time) { switch (step) { case DAY: return YYYYMMDD.parseDateTime(String.valueOf(time)); @@ -176,4 +169,23 @@ public enum DurationUtils { } throw new UnexpectedException("Unexpected downsampling: " + step.name()); } + + public void verifyDateTimeString(Step step, String dateStr) { + switch (step) { + case DAY: + YYYY_MM_DD.parseDateTime(dateStr); + return; + case HOUR: + YYYY_MM_DD_HH.parseDateTime(dateStr); + return; + case MINUTE: + YYYY_MM_DD_HHMM.parseDateTime(dateStr); + return; + case SECOND: + YYYY_MM_DD_HHMMSS.parseDateTime(dateStr); + return; + } + throw new UnexpectedException("Unsupported step " + step.name()); + } + } diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/input/Duration.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/input/Duration.java index 600b4dbad3..a9d16ba397 100644 --- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/input/Duration.java +++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/input/Duration.java @@ -33,17 +33,17 @@ public class Duration { private Step step; /** - * See {@link DurationUtils#convertToTimeBucket(String)} + * See {@link DurationUtils#convertToTimeBucket(Step, String)} */ public long getStartTimeBucket() { - return DurationUtils.INSTANCE.convertToTimeBucket(start); + return DurationUtils.INSTANCE.convertToTimeBucket(step, start); } /** - * See {@link DurationUtils#convertToTimeBucket(String)} + * See {@link DurationUtils#convertToTimeBucket(Step, String)} */ public long getEndTimeBucket() { - return DurationUtils.INSTANCE.convertToTimeBucket(end); + return DurationUtils.INSTANCE.convertToTimeBucket(step, end); } public long getStartTimestamp() { diff --git a/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/query/DurationTest.java b/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/query/DurationTest.java new file mode 100644 index 0000000000..a51cea7a0c --- /dev/null +++ b/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/query/DurationTest.java @@ -0,0 +1,83 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.skywalking.oap.server.core.query; + +import org.apache.skywalking.oap.server.core.query.enumeration.Step; +import org.junit.Assert; +import org.junit.Test; + +public class DurationTest { + + @Test + public void testConvertToTimeBucket() { + Assert.assertEquals(20220908L, DurationUtils.INSTANCE.convertToTimeBucket(Step.DAY, "2022-09-08")); + Assert.assertEquals(2022090810L, DurationUtils.INSTANCE.convertToTimeBucket(Step.HOUR, "2022-09-08 10")); + Assert.assertEquals(202209081010L, DurationUtils.INSTANCE.convertToTimeBucket(Step.MINUTE, "2022-09-08 1010")); + Assert.assertEquals( + 20220908101010L, DurationUtils.INSTANCE.convertToTimeBucket(Step.SECOND, "2022-09-08 101010")); + try { + DurationUtils.INSTANCE.convertToTimeBucket(Step.DAY, "2022-09-08 10"); + Assert.fail("Should throw IllegalArgumentException"); + } catch (IllegalArgumentException e) { + Assert.assertTrue(true); + } + } + + @Test + public void testStartTimeDurationToSecondTimeBucket() { + Assert.assertEquals( + 20220908000000L, DurationUtils.INSTANCE.startTimeDurationToSecondTimeBucket(Step.DAY, "2022-09-08")); + Assert.assertEquals( + 20220908100000L, DurationUtils.INSTANCE.startTimeDurationToSecondTimeBucket(Step.HOUR, "2022-09-08 10")); + Assert.assertEquals( + 20220908101000L, + DurationUtils.INSTANCE.startTimeDurationToSecondTimeBucket(Step.MINUTE, "2022-09-08 1010") + ); + Assert.assertEquals( + 20220908101010L, + DurationUtils.INSTANCE.startTimeDurationToSecondTimeBucket(Step.SECOND, "2022-09-08 101010") + ); + try { + DurationUtils.INSTANCE.startTimeDurationToSecondTimeBucket(Step.HOUR, "2022-09-08 30"); + Assert.fail("Should throw IllegalArgumentException"); + } catch (IllegalArgumentException e) { + Assert.assertTrue(true); + } + } + + @Test + public void testEndTimeDurationToSecondTimeBucket() { + Assert.assertEquals( + 20220908235959L, DurationUtils.INSTANCE.endTimeDurationToSecondTimeBucket(Step.DAY, "2022-09-08")); + Assert.assertEquals( + 20220908105959L, DurationUtils.INSTANCE.endTimeDurationToSecondTimeBucket(Step.HOUR, "2022-09-08 10")); + Assert.assertEquals( + 20220908101059L, DurationUtils.INSTANCE.endTimeDurationToSecondTimeBucket(Step.MINUTE, "2022-09-08 1010")); + Assert.assertEquals( + 20220908101010L, + DurationUtils.INSTANCE.endTimeDurationToSecondTimeBucket(Step.SECOND, "2022-09-08 101010") + ); + try { + DurationUtils.INSTANCE.endTimeDurationToSecondTimeBucket(Step.HOUR, "2022-09-08 30"); + Assert.fail("Should throw IllegalArgumentException"); + } catch (IllegalArgumentException e) { + Assert.assertTrue(true); + } + } +}