From eefc4313eaa8c42292beba27f8399ac97f781def Mon Sep 17 00:00:00 2001 From: Michael Jerris Date: Sun, 16 Aug 2026 07:00:51 -0500 Subject: [PATCH] ks_json_check: decimal_between_zero_and_one mixed an exact floor with a truncating ceiling `ks_json_check_number_is_decimal_between_zero_and_one` read `valuedouble` for its lower bound but `valueint` for its upper. `valueint` is cJSON's saturating truncation toward zero, so `valueint <= 1` admits every value below 2, and the predicate enforced (0,2) rather than the [0,1] its name promises. The defect ran in two directions at once: 0.0 REJECTED -- though the string_ twin one function above accepts it 1.5 ACCEPTED -- the whole [1,2) band the name excludes 1.9999 ACCEPTED 2.0 rejected -- so the over-accept band is exactly [1,2) So a caller's accepted set depended on whether the value arrived number- or string-encoded, for two functions with the same name and the same documented contract. `ks_json_check_string_is_decimal_between_zero_and_one` (:82) was already correct, using atof on both bounds with an inclusive lower. This change makes the number_ arm agree with it exactly: valuedouble on both bounds, inclusive lower. The two variants now enforce the same domain. The inclusive lower bound is taken from the string_ twin rather than from the name alone: both variants landed together, and the author's contemporaneous reading of "between zero and one" includes zero. No callers exist in this repo (2 definitions, 2 declarations, 0 call sites), so nothing here changes behaviour today. The exposure is a downstream consumer calling a public API whose name reads as obviously safe for a 0..1 parameter and silently getting (0,2) with 0.0 refused. The identical defect was fixed in mod_infrastructure's parallel copy (cjson_check.c:98), which is where it was found. The two copies were written independently and drifted the same way; this restores them to agreement. --- src/ks_json_check.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ks_json_check.c b/src/ks_json_check.c index 3861b0a8..9d023df5 100644 --- a/src/ks_json_check.c +++ b/src/ks_json_check.c @@ -101,7 +101,7 @@ KS_DECLARE(int) ks_json_check_number_is_positive_or_neg_one(ks_json_t* item) KS_DECLARE(int) ks_json_check_number_is_decimal_between_zero_and_one(ks_json_t* item) { - return ks_json_type_is_number(item) && (item->valuedouble > 0.0f && item->valueint <= 1.0f); + return ks_json_type_is_number(item) && (item->valuedouble >= 0.0f && item->valuedouble <= 1.0f); } KS_DECLARE(int) ks_json_check_number_is_8_bit_unsigned(ks_json_t *item)