summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHauke Mehrtens2026-04-16 20:16:42 +0000
committerHauke Mehrtens2026-06-18 22:06:53 +0000
commit3bbf83c3a3eb0ec79c5dffe5b9106e46e3180af1 (patch)
tree5b91be017c0a7faefd686ef2d153aafe7a63308c
parent52868080dc8852b71077d24178957006d125b9f5 (diff)
downloadlibubox-3bbf83c3a3eb0ec79c5dffe5b9106e46e3180af1.tar.gz
blobmsg_json: fix double format string to avoid truncation and data loss
Using %lf (= %f) with the default precision of 6 fractional decimal digits requires up to 317 characters for negative values close to -DBL_MAX (1 sign + 309 integer digits + 1 decimal point + 6 fraction digits + NUL), but buf[] only holds 317 bytes, leaving no room for the NUL terminator — snprintf truncates the last digit silently. Additionally, 6 fractional digits do not give round-trip accuracy for IEEE 754 doubles; 17 significant digits (%.17g) are required. Switch to %.17g which uses scientific notation for very large or small values, keeping the output well within the buffer, and guarantees round-trip accuracy for all finite doubles. Update the cram fixtures test_blobmsg.t and test_blobmsg_types.t to match the new output. The previous fixtures encoded the buggy behaviour: DBL_MIN serialised as "0.000000" and was silently flattened to zero on the JSON round-trip, while DBL_MAX produced a 309-digit decimal string. Link: https://github.com/openwrt/libubox/pull/42 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de> (cherry picked from commit 23c6618a5b9088644bb6b509c83f4f88ee8998d3)
-rw-r--r--blobmsg_json.c2
-rw-r--r--tests/cram/test_blobmsg.t8
-rw-r--r--tests/cram/test_blobmsg_types.t8
3 files changed, 9 insertions, 9 deletions
diff --git a/blobmsg_json.c b/blobmsg_json.c
index 49eea61..04bb9a1 100644
--- a/blobmsg_json.c
+++ b/blobmsg_json.c
@@ -272,7 +272,7 @@ static void blobmsg_format_element(struct strbuf *s, struct blob_attr *attr, boo
snprintf(buf, sizeof(buf), "%" PRId64, (int64_t) be64_to_cpu(*(uint64_t *)data));
break;
case BLOBMSG_TYPE_DOUBLE:
- snprintf(buf, sizeof(buf), "%lf", blobmsg_get_double(attr));
+ snprintf(buf, sizeof(buf), "%.17g", blobmsg_get_double(attr));
break;
case BLOBMSG_TYPE_STRING:
blobmsg_format_string(s, data);
diff --git a/tests/cram/test_blobmsg.t b/tests/cram/test_blobmsg.t
index 0c192c5..67a9d80 100644
--- a/tests/cram/test_blobmsg.t
+++ b/tests/cram/test_blobmsg.t
@@ -35,7 +35,7 @@ check that blobmsg is producing expected results:
\tworld : 2 (str) (esc)
}
- [*] blobmsg to json: {"message":"Hello, world!","testdata":{"dbl-min":0.000000,"dbl-max":179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.000000,"foo":false,"poo":true,"moo-min":true,"moo-max":true,"bar-min":-32768,"bar-max":32767,"baz-min":-2147483648,"baz-max":2147483647,"taz-min":-9223372036854775808,"taz-max":9223372036854775807,"world":"2"},"list":[false,true,true,true,-32768,32767,-2147483648,2147483647,-9223372036854775808,9223372036854775807,0.000000,179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.000000]}
+ [*] blobmsg to json: {"message":"Hello, world!","testdata":{"dbl-min":2.2250738585072014e-308,"dbl-max":1.7976931348623157e+308,"foo":false,"poo":true,"moo-min":true,"moo-max":true,"bar-min":-32768,"bar-max":32767,"baz-min":-2147483648,"baz-max":2147483647,"taz-min":-9223372036854775808,"taz-max":9223372036854775807,"world":"2"},"list":[false,true,true,true,-32768,32767,-2147483648,2147483647,-9223372036854775808,9223372036854775807,2.2250738585072014e-308,1.7976931348623157e+308]}
[*] blobmsg from json:
Message: Hello, world!
@@ -102,7 +102,7 @@ check that blobmsg is producing expected results:
\tworld : 2 (str) (esc)
}
- [*] blobmsg to json: {"message":"Hello, world!","testdata":{"dbl-min":0.000000,"dbl-max":179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.000000,"foo":false,"poo":true,"moo-min":true,"moo-max":true,"bar-min":-32768,"bar-max":32767,"baz-min":-2147483648,"baz-max":2147483647,"taz-min":-9223372036854775808,"taz-max":9223372036854775807,"world":"2"},"list":[false,true,true,true,-32768,32767,-2147483648,2147483647,-9223372036854775808,9223372036854775807,0.000000,179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.000000]}
+ [*] blobmsg to json: {"message":"Hello, world!","testdata":{"dbl-min":2.2250738585072014e-308,"dbl-max":1.7976931348623157e+308,"foo":false,"poo":true,"moo-min":true,"moo-max":true,"bar-min":-32768,"bar-max":32767,"baz-min":-2147483648,"baz-max":2147483647,"taz-min":-9223372036854775808,"taz-max":9223372036854775807,"world":"2"},"list":[false,true,true,true,-32768,32767,-2147483648,2147483647,-9223372036854775808,9223372036854775807,2.2250738585072014e-308,1.7976931348623157e+308]}
[*] blobmsg from json:
Message: Hello, world!
@@ -169,7 +169,7 @@ check that blobmsg is producing expected results:
\tworld : 2 (str) (esc)
}
- [*] blobmsg to json: {"message":"Hello, world!","testdata":{"dbl-min":0.000000,"dbl-max":179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.000000,"foo":false,"poo":true,"moo-min":true,"moo-max":true,"bar-min":-32768,"bar-max":32767,"baz-min":-2147483648,"baz-max":2147483647,"taz-min":-9223372036854775808,"taz-max":9223372036854775807,"world":"2"},"list":[false,true,true,true,-32768,32767,-2147483648,2147483647,-9223372036854775808,9223372036854775807,0.000000,179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.000000]}
+ [*] blobmsg to json: {"message":"Hello, world!","testdata":{"dbl-min":2.2250738585072014e-308,"dbl-max":1.7976931348623157e+308,"foo":false,"poo":true,"moo-min":true,"moo-max":true,"bar-min":-32768,"bar-max":32767,"baz-min":-2147483648,"baz-max":2147483647,"taz-min":-9223372036854775808,"taz-max":9223372036854775807,"world":"2"},"list":[false,true,true,true,-32768,32767,-2147483648,2147483647,-9223372036854775808,9223372036854775807,2.2250738585072014e-308,1.7976931348623157e+308]}
[*] blobmsg from json:
Message: Hello, world!
@@ -236,7 +236,7 @@ check that blobmsg is producing expected results:
\tworld : 2 (str) (esc)
}
- [*] blobmsg to json: {"message":"Hello, world!","testdata":{"dbl-min":0.000000,"dbl-max":179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.000000,"foo":false,"poo":true,"moo-min":true,"moo-max":true,"bar-min":-32768,"bar-max":32767,"baz-min":-2147483648,"baz-max":2147483647,"taz-min":-9223372036854775808,"taz-max":9223372036854775807,"world":"2"},"list":[false,true,true,true,-32768,32767,-2147483648,2147483647,-9223372036854775808,9223372036854775807,0.000000,179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.000000]}
+ [*] blobmsg to json: {"message":"Hello, world!","testdata":{"dbl-min":2.2250738585072014e-308,"dbl-max":1.7976931348623157e+308,"foo":false,"poo":true,"moo-min":true,"moo-max":true,"bar-min":-32768,"bar-max":32767,"baz-min":-2147483648,"baz-max":2147483647,"taz-min":-9223372036854775808,"taz-max":9223372036854775807,"world":"2"},"list":[false,true,true,true,-32768,32767,-2147483648,2147483647,-9223372036854775808,9223372036854775807,2.2250738585072014e-308,1.7976931348623157e+308]}
[*] blobmsg from json:
Message: Hello, world!
diff --git a/tests/cram/test_blobmsg_types.t b/tests/cram/test_blobmsg_types.t
index 190e1f2..4def0e6 100644
--- a/tests/cram/test_blobmsg_types.t
+++ b/tests/cram/test_blobmsg_types.t
@@ -40,7 +40,7 @@ check that blobmsg is producing expected results:
double_max: 1.797693e+308
double_min: 2.225074e-308
- [*] blobmsg to json: {"string":"Hello, world!","int64_max":9223372036854775807,"int64_min":-9223372036854775808,"int32_max":2147483647,"int32_min":-2147483648,"int16_max":32767,"int16_min":-32768,"int8_max":true,"int8_min":true,"double_max":179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.000000,"double_min":0.000000}
+ [*] blobmsg to json: {"string":"Hello, world!","int64_max":9223372036854775807,"int64_min":-9223372036854775808,"int32_max":2147483647,"int32_min":-2147483648,"int16_max":32767,"int16_min":-32768,"int8_max":true,"int8_min":true,"double_max":1.7976931348623157e+308,"double_min":2.2250738585072014e-308}
[*] blobmsg from json:
string: Hello, world!
@@ -53,7 +53,7 @@ check that blobmsg is producing expected results:
int8_max: 1
int8_min: 1
double_max: 1.797693e+308
- double_min: 0.000000e+00
+ double_min: 2.225074e-308
[*] blobmsg from json/cast_u64:
string: Hello, world!
@@ -66,7 +66,7 @@ check that blobmsg is producing expected results:
int8_max: 1
int8_min: 1
double_max: 1.797693e+308
- double_min: 0.000000e+00
+ double_min: 2.225074e-308
[*] blobmsg from json/cast_s64:
string: Hello, world!
@@ -79,4 +79,4 @@ check that blobmsg is producing expected results:
int8_max: 1
int8_min: 1
double_max: 1.797693e+308
- double_min: 0.000000e+00
+ double_min: 2.225074e-308