mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Shuvam Pandey <shuvampandey1@gmail.com>
To: Kees Cook <kees@kernel.org>, Andrew Morton <akpm@linux-foundation.org>
Cc: Andy Shevchenko <andy@kernel.org>,
	linux-hardening@vger.kernel.org, linux-kernel@vger.kernel.org,
	Shuvam Pandey <shuvampandey1@gmail.com>
Subject: [PATCH v2] lib/string_helpers: renormalize string_get_size() after rounding carry
Date: Sun, 19 Apr 2026 21:16:11 +0545	[thread overview]
Message-ID: <20260419153111.90635-1-shuvampandey1@gmail.com> (raw)
In-Reply-To: <20260407143306.78809-1-shuvampandey1@gmail.com>

string_get_size() rounds the fractional part before formatting the
result. If that carry pushes the integer part to the unit divisor, the
helper still prints the old unit and produces strings like "1000 kB"
and "1024 KiB".

That misformatted carry case comes from the arithmetic rounding added by
commit 564b026fbd0d ("string_helpers: fix precision loss for some
inputs"). The helper already rounds those values up numerically; it
just fails to renormalize them into the next unit before formatting.

Renormalize the carried result into the next named unit so those cases
print as "1.00 MB" and "1.00 MiB" instead. Only do that when another
named unit exists, so the existing "UNK" fallback is preserved at the
top end. Extend the KUnit coverage around the first decimal and binary
boundaries, including adjacent values and non-byte block sizes that hit
the same carry path.

Fixes: 564b026fbd0d ("string_helpers: fix precision loss for some inputs")
Signed-off-by: Shuvam Pandey <shuvampandey1@gmail.com>
---
Changes in v2:
- correct the Fixes tag to 564b026fbd0d
- renormalize only when another named unit exists
- preserve the top-end UNK fallback
- add decimal and binary boundary/neighbor KUnit coverage
- add non-byte block-size cases that hit the same carry path

 lib/string_helpers.c             | 12 ++++++++++++
 lib/tests/string_helpers_kunit.c | 25 +++++++++++++++++++++++++
 2 files changed, 37 insertions(+)

diff --git a/lib/string_helpers.c b/lib/string_helpers.c
index 169eaf5834949..bcabb24fe0dbf 100644
--- a/lib/string_helpers.c
+++ b/lib/string_helpers.c
@@ -121,6 +121,18 @@ int string_get_size(u64 size, u64 blk_size, const enum string_size_units units,
 		size += 1;
 	}
 
+	/*
+	 * Renormalize into the next named unit, but preserve the top-end
+	 * UNK fallback. After promotion the value is exactly 1 of the next
+	 * unit, so keep two fractional digits for the usual 1.00 formatting.
+	 */
+	if (size >= divisor[units_base] && i + 1 < ARRAY_SIZE(units_2)) {
+		size = 1;
+		remainder = 0;
+		i++;
+		j = 2;
+	}
+
 	if (j) {
 		snprintf(tmp, sizeof(tmp), ".%03u", remainder);
 		tmp[j+1] = '\0';
diff --git a/lib/tests/string_helpers_kunit.c b/lib/tests/string_helpers_kunit.c
index c853046183d24..67822cb48fd15 100644
--- a/lib/tests/string_helpers_kunit.c
+++ b/lib/tests/string_helpers_kunit.c
@@ -558,6 +558,31 @@ static void test_get_size(struct kunit *test)
 	/* weird block sizes */
 	test_string_get_size_one(3000, 1900, "5.70 MB", "5.44 MiB");
 
+	/* rounding carry into the next unit at the first decimal boundary */
+	test_string_get_size_one(999499, 1, "999 kB", "976 KiB");
+	test_string_get_size_one(999500, 1, "1.00 MB", "976 KiB");
+	test_string_get_size_one(999999, 1, "1.00 MB", "977 KiB");
+	test_string_get_size_one(1000000, 1, "1.00 MB", "977 KiB");
+	test_string_get_size_one(1000001, 1, "1.00 MB", "977 KiB");
+
+	/* rounding carry into the next unit at the first binary boundary */
+	test_string_get_size_one(1048063, 1, "1.05 MB", "1023 KiB");
+	test_string_get_size_one(1048064, 1, "1.05 MB", "1.00 MiB");
+	test_string_get_size_one(1048575, 1, "1.05 MB", "1.00 MiB");
+	test_string_get_size_one(1048576, 1, "1.05 MB", "1.00 MiB");
+	test_string_get_size_one(1048577, 1, "1.05 MB", "1.00 MiB");
+
+	/* values already in the next binary unit stay unchanged */
+	test_string_get_size_one(2097151, 1, "2.10 MB", "2.00 MiB");
+	test_string_get_size_one(2097152, 1, "2.10 MB", "2.00 MiB");
+	test_string_get_size_one(2097153, 1, "2.10 MB", "2.00 MiB");
+
+	/* non-byte block sizes hit the same carry path */
+	test_string_get_size_one(4997, 200, "999 kB", "976 KiB");
+	test_string_get_size_one(4998, 200, "1.00 MB", "976 KiB");
+	test_string_get_size_one(9981, 105, "1.05 MB", "1023 KiB");
+	test_string_get_size_one(9982, 105, "1.05 MB", "1.00 MiB");
+
 	/* huge values */
 	test_string_get_size_one(U64_MAX, 4096, "75.6 ZB", "64.0 ZiB");
 	test_string_get_size_one(4096, U64_MAX, "75.6 ZB", "64.0 ZiB");
-- 
2.50.1 (Apple Git-155)


  parent reply	other threads:[~2026-04-19 15:31 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-04-07 14:33 [PATCH] lib/string_helpers: fix string_get_size() unit promotion after rounding Shuvam Pandey
2026-04-07 14:53 ` Andy Shevchenko
     [not found]   ` <CANAAWH+ihOpBVB5_Q4gxLs0_zO=pHb-kF53UXE-pqg1U9E9OKw@mail.gmail.com>
     [not found]     ` <adayT_7xAtOLiVlq@ashevche-desk.local>
     [not found]       ` <CANAAWHKDBoi1x=MpAyU5bQ88=ZOOrkaJNziyhcK9Ei7c8oNSHg@mail.gmail.com>
     [not found]         ` <CANAAWHKZXbFAr7=DRCrS46GDsWi88Q=v883RQrgF4+EScksP=w@mail.gmail.com>
2026-04-14  7:19           ` Andy Shevchenko
2026-04-14  8:06             ` Shuvam Pandey
2026-04-19 15:31 ` Shuvam Pandey [this message]
2026-04-20  6:56   ` [PATCH v2] lib/string_helpers: renormalize string_get_size() after rounding carry Andy Shevchenko
2026-04-21  3:04     ` James Bottomley
2026-04-21  3:38       ` Shuvam Pandey
2026-04-21  4:53         ` Andy Shevchenko
2026-04-21 10:10           ` Shuvam Pandey
2026-04-21 12:16           ` James Bottomley

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260419153111.90635-1-shuvampandey1@gmail.com \
    --to=shuvampandey1@gmail.com \
    --cc=akpm@linux-foundation.org \
    --cc=andy@kernel.org \
    --cc=kees@kernel.org \
    --cc=linux-hardening@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®