From 4a01ab87e3308d0bbc5f8b8921e824fd109adf15 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Mon, 10 Aug 2026 19:11:02 +0900 Subject: [PATCH 1/2] test(analytics): reject invalid persisted KPI numerics --- .../clearfolio/viewer/analytics/KpiSnapshotLedgerTest.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/test/java/com/clearfolio/viewer/analytics/KpiSnapshotLedgerTest.java b/src/test/java/com/clearfolio/viewer/analytics/KpiSnapshotLedgerTest.java index d42349fde..a91f129e2 100644 --- a/src/test/java/com/clearfolio/viewer/analytics/KpiSnapshotLedgerTest.java +++ b/src/test/java/com/clearfolio/viewer/analytics/KpiSnapshotLedgerTest.java @@ -82,7 +82,13 @@ void rejectsInvalidPersistedLedgerLines() throws Exception { assertInvalidLedger(snapshotLine().replace(NOW.toString(), "not-instant")); assertInvalidLedger(snapshotLine().replace("\t2\t", "\tnot-int\t")); assertInvalidLedger(snapshotLine().replace("\t0.5\t", "\tnot-rate\t")); + assertInvalidLedger(snapshotLine().replace("\t0.5\t", "\tNaN\t")); + assertInvalidLedger(snapshotLine().replace("\t0.5\t", "\tInfinity\t")); + assertInvalidLedger(snapshotLine().replace("\t0.5\t", "\t-Infinity\t")); + assertInvalidLedger(snapshotLine().replace("\t0.5\t", "\t-0.01\t")); + assertInvalidLedger(snapshotLine().replace("\t0.5\t", "\t1.01\t")); assertInvalidLedger(snapshotLine().replace("\t123", "\tnot-long")); + assertInvalidLedger(snapshotLine().replace("\t123", "\t-1")); assertInvalidLedger(snapshotLine().replace(encoded("tenant-a"), "!")); } From 66c7afc6eeb1e5862e414d14e7d236e275536082 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Mon, 10 Aug 2026 19:14:34 +0900 Subject: [PATCH 2/2] fix(analytics): validate persisted KPI numeric evidence --- .../viewer/analytics/KpiSnapshotLedger.java | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/clearfolio/viewer/analytics/KpiSnapshotLedger.java b/src/main/java/com/clearfolio/viewer/analytics/KpiSnapshotLedger.java index 85ef8df1c..6cdfb9690 100644 --- a/src/main/java/com/clearfolio/viewer/analytics/KpiSnapshotLedger.java +++ b/src/main/java/com/clearfolio/viewer/analytics/KpiSnapshotLedger.java @@ -211,7 +211,11 @@ private static int integer(String field) { private static double rate(String field) { try { - return Double.parseDouble(field); + double value = Double.parseDouble(field); + if (!Double.isFinite(value) || value < 0.0 || value > 1.0) { + throw invalidLine(); + } + return value; } catch (NumberFormatException ex) { throw invalidLine(ex); } @@ -222,7 +226,11 @@ private static Long nullableLong(String field) { return null; } try { - return Long.parseLong(field); + long value = Long.parseLong(field); + if (value < 0L) { + throw invalidLine(); + } + return value; } catch (NumberFormatException ex) { throw invalidLine(ex); }