From c320e09f744bb5d1a6876f8c7aa5fa25b445be1e Mon Sep 17 00:00:00 2001 From: Binbin Date: Fri, 3 Apr 2026 18:16:28 +0800 Subject: [PATCH 1/3] Fix config rewrite producing negative values for unsigned memory configs rewriteConfigFormatMemory() and rewriteConfigBytesOption() used long long parameters to represent memory bytes, but configs like maxmemory are stored as unsigned long long and allow values up to ULLONG_MAX. When the value exceeds LLONG_MAX (e.g. 9223372036854775808), it overflows to negative when passed as long long, causing config rewrite to produce incorrect output like "maxmemory -8589934592gb". Change both functions to use unsigned long long, matching the actual semantics of memory byte values. This is consistent with how numericConfigGet() already handles MEMORY_CONFIG using ull2string(). Signed-off-by: Binbin --- src/config.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/config.c b/src/config.c index 48ea1c46961..a8e04dcecf4 100644 --- a/src/config.c +++ b/src/config.c @@ -1272,29 +1272,29 @@ int rewriteConfigRewriteLine(struct rewriteConfigState *state, const char *optio return 1; } -/* Write the long long 'bytes' value as a string in a way that is parsable +/* Write the unsigned long long 'bytes' value as a string in a way that is parsable * inside valkey.conf. If possible uses the GB, MB, KB notation. */ -int rewriteConfigFormatMemory(char *buf, size_t len, long long bytes) { +int rewriteConfigFormatMemory(char *buf, size_t len, unsigned long long bytes) { int gb = 1024 * 1024 * 1024; int mb = 1024 * 1024; int kb = 1024; if (bytes && (bytes % gb) == 0) { - return snprintf(buf, len, "%lldgb", bytes / gb); + return snprintf(buf, len, "%llugb", bytes / gb); } else if (bytes && (bytes % mb) == 0) { - return snprintf(buf, len, "%lldmb", bytes / mb); + return snprintf(buf, len, "%llumb", bytes / mb); } else if (bytes && (bytes % kb) == 0) { - return snprintf(buf, len, "%lldkb", bytes / kb); + return snprintf(buf, len, "%llukb", bytes / kb); } else { - return snprintf(buf, len, "%lld", bytes); + return snprintf(buf, len, "%llu", bytes); } } /* Rewrite a simple "option-name " configuration option. */ void rewriteConfigBytesOption(struct rewriteConfigState *state, const char *option, - long long value, - long long defvalue) { + unsigned long long value, + unsigned long long defvalue) { char buf[64]; int force = value != defvalue; sds line; From d5be195722435dd27d2417b311346d930058ad70 Mon Sep 17 00:00:00 2001 From: Binbin Date: Sat, 4 Apr 2026 10:17:12 +0800 Subject: [PATCH 2/3] Add a test Signed-off-by: Binbin --- tests/unit/introspection.tcl | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/tests/unit/introspection.tcl b/tests/unit/introspection.tcl index c5c456b5134..7cfaca327ff 100644 --- a/tests/unit/introspection.tcl +++ b/tests/unit/introspection.tcl @@ -1964,10 +1964,23 @@ test {CONFIG REWRITE handles alias config properly} { } } {} {external:skip} +test {CONFIG REWRITE handles large unsigned memory config values} { + start_server {tags {"introspection"}} { + r config set maxmemory 9223372036854775808 + r config set maxmemory-clients 50% + + r config rewrite + restart_server 0 true false + + assert_equal [lindex [r config get maxmemory] 1] 9223372036854775808 + assert_equal [lindex [r config get maxmemory-clients] 1] 50% + } +} {} {external:skip} + test {CONFIG hash-seed is immutable and settable at startup} { start_server {tags {"introspection"} overrides {hash-seed aabbccddeeffgghh}} { assert_error "ERR CONFIG SET failed (possibly related to argument 'hash-seed') - can't set immutable config*" { r config set hash-seed newseed } } -} {} {external:skip} \ No newline at end of file +} {} {external:skip} From 9a69ae72be70ce41dcf0d8cababe9a8cfab4dba3 Mon Sep 17 00:00:00 2001 From: Binbin Date: Sat, 4 Apr 2026 10:38:54 +0800 Subject: [PATCH 3/3] update the test to use 100% Signed-off-by: Binbin --- tests/unit/introspection.tcl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/unit/introspection.tcl b/tests/unit/introspection.tcl index 7cfaca327ff..afd9c9d8cf2 100644 --- a/tests/unit/introspection.tcl +++ b/tests/unit/introspection.tcl @@ -1967,13 +1967,13 @@ test {CONFIG REWRITE handles alias config properly} { test {CONFIG REWRITE handles large unsigned memory config values} { start_server {tags {"introspection"}} { r config set maxmemory 9223372036854775808 - r config set maxmemory-clients 50% + r config set maxmemory-clients 100% r config rewrite restart_server 0 true false assert_equal [lindex [r config get maxmemory] 1] 9223372036854775808 - assert_equal [lindex [r config get maxmemory-clients] 1] 50% + assert_equal [lindex [r config get maxmemory-clients] 1] 100% } } {} {external:skip}