From dceead809ef0a20758a3471469deec3878bb3e02 Mon Sep 17 00:00:00 2001 From: Tonu Samuel Date: Tue, 23 Jun 2026 11:15:11 +0300 Subject: [PATCH] core: FileStorage reads integers above INT_MAX into float/double without truncation FileNode::operator double() and operator float() read an INT node via readInt() (32-bit), truncating values above INT_MAX -- e.g. an integer 6662329666 from an externally-produced json/yaml/xml is read back as -1927604926. The node stores the value as int64 (operator int64_t() already reads it correctly via readLong), so use readLong() for the floating-point conversions too. Values that fit in int32 are unchanged (sign-extended); larger ones are now correct. Reader side of #29363 (the writer side was #29364). --- modules/core/src/persistence.cpp | 4 ++-- modules/core/test/test_io.cpp | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/modules/core/src/persistence.cpp b/modules/core/src/persistence.cpp index b10980c07e..a4903db981 100644 --- a/modules/core/src/persistence.cpp +++ b/modules/core/src/persistence.cpp @@ -2376,7 +2376,7 @@ FileNode::operator float() const if( type == INT ) { - return (float)readInt(p); + return (float)readLong(p); } else if( type == REAL ) { @@ -2397,7 +2397,7 @@ FileNode::operator double() const if( type == INT ) { - return (double)readInt(p); + return (double)readLong(p); } else if( type == REAL ) { diff --git a/modules/core/test/test_io.cpp b/modules/core/test/test_io.cpp index 42e49c5b93..ac6f187eb2 100644 --- a/modules/core/test/test_io.cpp +++ b/modules/core/test/test_io.cpp @@ -2099,6 +2099,24 @@ TEST(Core_InputOutput, FileStorage_int64_26829) } } +TEST(Core_InputOutput, FileStorage_read_bigint_as_real_29363) +{ + // An integer above INT_MAX (e.g. from externally-produced json/yaml/xml) must + // convert to float/double without truncating to int32. Regression for #29363. + String content = + "%YAML:1.0\n" + "a: 6662329666\n" // ~6.6e9, exact in double + "b: -9876543210\n" + "c: 4294967296\n"; // 2^32, exact in double and float + FileStorage fs(content, FileStorage::READ | FileStorage::MEMORY); + + EXPECT_EQ(6662329666.0, (double)fs["a"]); + EXPECT_EQ(-9876543210.0, (double)fs["b"]); + EXPECT_EQ(4294967296.0, (double)fs["c"]); + EXPECT_EQ(4294967296.0f, (float)fs["c"]); + EXPECT_EQ((int64_t)6662329666LL, (int64_t)fs["a"]); // int64 path unchanged +} + template T fsWriteRead(const T& expectedValue, const char* ext) {