From 1cf3837c18abc74eb860db14a6f458d64d7c0ecc Mon Sep 17 00:00:00 2001 From: fhgffy <102001626+fhgffy@users.noreply.github.com> Date: Sun, 4 Oct 2026 03:47:03 -0400 Subject: [PATCH] Preserve explicit 64-bit suffixes when parsing nondecimal integers --- lib/util.c | 4 ++- tests/testdata/int64-suffix.cfg | 3 ++ tests/testdata/int64-suffix.txt | 3 ++ tests/tests.c | 51 +++++++++++++++++++++++++++++++++ 4 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 tests/testdata/int64-suffix.cfg create mode 100644 tests/testdata/int64-suffix.txt diff --git a/lib/util.c b/lib/util.c index 8e1e82d..c30b3b6 100644 --- a/lib/util.c +++ b/lib/util.c @@ -123,7 +123,9 @@ int libconfig_parse_integer(const char *s, int base, long long *val, errno = 0; *val = strtoll(s, &endptr, base); - if((base != 10) && (*val > INT32_MAX) && (*val <= UINT32_MAX)) + /* Only unsuffixed non-decimal values use 32-bit signed interpretation. */ + if((base != 10) && (*endptr != 'L') + && (*val > INT32_MAX) && (*val <= UINT32_MAX)) *val = (long long)(int)*val; *is_long = ((*val < INT32_MIN) || (*val > INT32_MAX)); diff --git a/tests/testdata/int64-suffix.cfg b/tests/testdata/int64-suffix.cfg new file mode 100644 index 0000000..14b5178 --- /dev/null +++ b/tests/testdata/int64-suffix.cfg @@ -0,0 +1,3 @@ +hex = 0xFFFFFFFFL; +binary = 0b11111111111111111111111111111111L; +octal = 0o37777777777L; diff --git a/tests/testdata/int64-suffix.txt b/tests/testdata/int64-suffix.txt new file mode 100644 index 0000000..5bd50c1 --- /dev/null +++ b/tests/testdata/int64-suffix.txt @@ -0,0 +1,3 @@ +hex = 0xFFFFFFFFL; +binary = 0b11111111111111111111111111111111L; +octal = 4294967295L; diff --git a/tests/tests.c b/tests/tests.c index 85fa430..0b71890 100644 --- a/tests/tests.c +++ b/tests/tests.c @@ -760,6 +760,56 @@ TT_TEST(BinaryAndHex) /* ------------------------------------------------------------------------- */ +TT_TEST(NonDecimalInt64Suffix) +{ + static const struct + { + const char *text; + long long value; + int type; + } cases[] = { + { "v = 0x7FFFFFFFL;", 2147483647LL, CONFIG_TYPE_INT64 }, + { "v = 0x80000000L;", 2147483648LL, CONFIG_TYPE_INT64 }, + { "v = 0xFFFFFFFFLL;", 4294967295LL, CONFIG_TYPE_INT64 }, + { "v = 0x100000000L;", 4294967296LL, CONFIG_TYPE_INT64 }, + { "v = 0b10000000000000000000000000000000L;", 2147483648LL, + CONFIG_TYPE_INT64 }, + { "v = 0b11111111111111111111111111111111LL;", 4294967295LL, + CONFIG_TYPE_INT64 }, + { "v = 0o20000000000L;", 2147483648LL, CONFIG_TYPE_INT64 }, + { "v = 0q37777777777LL;", 4294967295LL, CONFIG_TYPE_INT64 }, + { "v = 0xFFFFFFFF;", -1LL, CONFIG_TYPE_INT }, + { "v = 0b11111111111111111111111111111111;", -1LL, CONFIG_TYPE_INT }, + { "v = 0o37777777777;", -1LL, CONFIG_TYPE_INT }, + { "v = 4294967295L;", 4294967295LL, CONFIG_TYPE_INT64 }, + { "v = -2147483649L;", -2147483649LL, CONFIG_TYPE_INT64 }, + { "v = 0x7FFFFFFFFFFFFFFFL;", 9223372036854775807LL, + CONFIG_TYPE_INT64 } + }; + unsigned int i; + + for(i = 0; i < sizeof(cases) / sizeof(cases[0]); ++i) + { + config_t cfg; + config_setting_t *setting; + config_init(&cfg); + TT_ASSERT_TRUE(config_read_string(&cfg, cases[i].text)); + setting = config_lookup(&cfg, "v"); + TT_ASSERT_PTR_NE(setting, NULL); + if(setting) + { + TT_ASSERT_INT_EQ(config_setting_type(setting), cases[i].type); + TT_ASSERT_INT64_EQ(config_setting_get_int64(setting), cases[i].value); + } + config_destroy(&cfg); + } + + parse_and_compare("./testdata/int64-suffix.cfg", + "./testdata/int64-suffix.txt"); +} + +/* ------------------------------------------------------------------------- */ + int main(int argc, char **argv) { int failures; @@ -782,6 +832,7 @@ int main(int argc, char **argv) TT_SUITE_TEST(LibConfigTests, IncludeReadError); TT_SUITE_TEST(LibConfigTests, ReadStream); TT_SUITE_TEST(LibConfigTests, BinaryAndHex); + TT_SUITE_TEST(LibConfigTests, NonDecimalInt64Suffix); TT_SUITE_RUN(LibConfigTests); failures = TT_SUITE_NUM_FAILURES(LibConfigTests); TT_SUITE_END(LibConfigTests);