Browse Source

Merge pull request #15621 from volodymyr-babak/fix-sum-overflow-43

fix(cf): prevent integer overflow in calculated field SUM output
pull/15731/head
Viacheslav Klimov 2 months ago
committed by GitHub
parent
commit
3aacc66074
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 2
      application/src/main/java/org/thingsboard/server/service/cf/ctx/state/SimpleCalculatedFieldState.java
  2. 4
      application/src/test/java/org/thingsboard/server/service/cf/ctx/state/SimpleCalculatedFieldStateTest.java
  3. 6
      common/util/src/main/java/org/thingsboard/common/util/NumberUtils.java
  4. 11
      common/util/src/test/java/org/thingsboard/common/util/NumberUtilsTest.java

2
application/src/main/java/org/thingsboard/server/service/cf/ctx/state/SimpleCalculatedFieldState.java

@ -67,6 +67,8 @@ public class SimpleCalculatedFieldState extends BaseCalculatedFieldState {
ObjectNode valuesNode = JacksonUtil.newObjectNode(); ObjectNode valuesNode = JacksonUtil.newObjectNode();
if (result instanceof Double doubleValue) { if (result instanceof Double doubleValue) {
valuesNode.put(outputName, doubleValue); valuesNode.put(outputName, doubleValue);
} else if (result instanceof Long longValue) {
valuesNode.put(outputName, longValue);
} else if (result instanceof Integer integerValue) { } else if (result instanceof Integer integerValue) {
valuesNode.put(outputName, integerValue); valuesNode.put(outputName, integerValue);
} else { } else {

4
application/src/test/java/org/thingsboard/server/service/cf/ctx/state/SimpleCalculatedFieldStateTest.java

@ -154,7 +154,7 @@ public class SimpleCalculatedFieldStateTest {
Output output = getCalculatedFieldConfig().getOutput(); Output output = getCalculatedFieldConfig().getOutput();
assertThat(result.getType()).isEqualTo(output.getType()); assertThat(result.getType()).isEqualTo(output.getType());
assertThat(result.getScope()).isEqualTo(output.getScope()); assertThat(result.getScope()).isEqualTo(output.getScope());
assertThat(result.getResult()).isEqualTo(JacksonUtil.valueToTree(Map.of("output", 49))); assertThat(result.getResult()).isEqualTo(JacksonUtil.valueToTree(Map.of("output", 49L)));
} }
@Test @Test
@ -184,7 +184,7 @@ public class SimpleCalculatedFieldStateTest {
Output output = getCalculatedFieldConfig().getOutput(); Output output = getCalculatedFieldConfig().getOutput();
assertThat(result.getType()).isEqualTo(output.getType()); assertThat(result.getType()).isEqualTo(output.getType());
assertThat(result.getScope()).isEqualTo(output.getScope()); assertThat(result.getScope()).isEqualTo(output.getScope());
assertThat(result.getResult()).isEqualTo(JacksonUtil.valueToTree(Map.of("output", 35))); assertThat(result.getResult()).isEqualTo(JacksonUtil.valueToTree(Map.of("output", 35L)));
} }
@Test @Test

6
common/util/src/main/java/org/thingsboard/common/util/NumberUtils.java

@ -36,12 +36,16 @@ public class NumberUtils {
return BigDecimal.valueOf(value).setScale(0, RoundingMode.HALF_UP).intValue(); return BigDecimal.valueOf(value).setScale(0, RoundingMode.HALF_UP).intValue();
} }
public static long toLong(double value) {
return BigDecimal.valueOf(value).setScale(0, RoundingMode.HALF_UP).longValue();
}
public static Object roundResult(double value, Integer precision) { public static Object roundResult(double value, Integer precision) {
if (precision == null) { if (precision == null) {
return value; return value;
} }
if (precision.equals(0)) { if (precision.equals(0)) {
return toInt(value); return toLong(value);
} }
return toFixed(value, precision); return toFixed(value, precision);
} }

11
common/util/src/test/java/org/thingsboard/common/util/NumberUtilsTest.java

@ -51,11 +51,20 @@ public class NumberUtilsTest {
assertThat(NumberUtils.toInt(28.0)).isEqualTo(28); assertThat(NumberUtils.toInt(28.0)).isEqualTo(28);
} }
@Test
public void toLong() {
assertThat(NumberUtils.toLong(doubleVal)).isEqualTo(1729L);
assertThat(NumberUtils.toLong(12.8)).isEqualTo(13L);
assertThat(NumberUtils.toLong(28.0)).isEqualTo(28L);
assertThat(NumberUtils.toLong(3_980_173_734.0)).isEqualTo(3_980_173_734L);
}
@Test @Test
public void roundResult() { public void roundResult() {
assertThat(NumberUtils.roundResult(doubleVal, null)).isEqualTo(1729.1729); assertThat(NumberUtils.roundResult(doubleVal, null)).isEqualTo(1729.1729);
assertThat(NumberUtils.roundResult(doubleVal, 0)).isEqualTo(1729); assertThat(NumberUtils.roundResult(doubleVal, 0)).isEqualTo(1729L);
assertThat(NumberUtils.roundResult(doubleVal, 2)).isEqualTo(1729.17); assertThat(NumberUtils.roundResult(doubleVal, 2)).isEqualTo(1729.17);
assertThat(NumberUtils.roundResult(3_980_173_734.0, 0)).isEqualTo(3_980_173_734L);
} }
} }

Loading…
Cancel
Save