public inbox for linux-bcache@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH] bcache: fix bch_hprint crash and improve output
@ 2017-09-04 21:55 Michael Lyle
  2017-09-05  2:50 ` Coly Li
  2017-09-05  4:19 ` Kent Overstreet
  0 siblings, 2 replies; 11+ messages in thread
From: Michael Lyle @ 2017-09-04 21:55 UTC (permalink / raw)
  To: colyli; +Cc: linux-bcache, Michael Lyle

Most importantly, solve a crash where %llu was used to format signed
numbers.  This would cause a buffer overflow when reading sysfs
writeback_rate_debug, as only 20 bytes were allocated for this and
%llu writes 20 characters plus a null.

Always use the units mechanism rather than having different output
paths for simplicity.

Also, correct problems with display output where 1.10 was a larger
number than 1.09, by multiplying by 10 and then dividing by 1024 instead
of dividing by 100.  (Remainders of >= 1000 would print as .10).

Minor changes: Always display the decimal point instead of trying to
omit it based on number of digits shown.  Decide what units to use
based on 1000 as a threshold, not 1024 (in other words, always print
at most 3 digits before the decimal point).

Signed-off-by: Michael Lyle <mlyle@lyle.org>
Reported-by: Dmitry Yu Okunev <dyokunev@ut.mephi.ru>
---
 drivers/md/bcache/util.c | 50 +++++++++++++++++++++++++++++++++---------------
 1 file changed, 35 insertions(+), 15 deletions(-)

diff --git a/drivers/md/bcache/util.c b/drivers/md/bcache/util.c
index 8c3a938f4bf0..176d3c2ef5f5 100644
--- a/drivers/md/bcache/util.c
+++ b/drivers/md/bcache/util.c
@@ -74,24 +74,44 @@ STRTO_H(strtouint, unsigned int)
 STRTO_H(strtoll, long long)
 STRTO_H(strtoull, unsigned long long)
 
+/**
+ * bch_hprint() - formats @v to human readable string for sysfs.
+ *
+ * @v - signed 64 bit integer
+ * @buf - the (at least 8 byte) buffer to format the result into.
+ *
+ * Returns the number of bytes used by format.
+ */
 ssize_t bch_hprint(char *buf, int64_t v)
 {
 	static const char units[] = "?kMGTPEZY";
-	char dec[4] = "";
-	int u, t = 0;
-
-	for (u = 0; v >= 1024 || v <= -1024; u++) {
-		t = v & ~(~0 << 10);
-		v >>= 10;
-	}
-
-	if (!u)
-		return sprintf(buf, "%llu", v);
-
-	if (v < 100 && v > -100)
-		snprintf(dec, sizeof(dec), ".%i", t / 100);
-
-	return sprintf(buf, "%lli%s%c", v, dec, units[u]);
+	int u = 0, t;
+
+	uint64_t q;
+
+	if (v < 0)
+		q = -v;
+	else
+		q = v;
+
+	/* For as long as the number is more than 3 digits, but at least
+	 * once, shift right / divide by 1024.  Keep the remainder for
+	 * a digit after the decimal point.
+	 */
+	do {
+		u++;
+
+		t = q & ~(~0 << 10);
+		q >>= 10;
+	} while (q >= 1000);
+
+	if (v < 0)
+		/* '-', up to 3 digits, '.', 1 digit, 1 character, null;
+		 * yields 8 bytes.
+		 */
+		return sprintf(buf, "-%llu.%i%c", q, t * 10 / 1024, units[u]);
+	else
+		return sprintf(buf, "%llu.%i%c", q, t * 10 / 1024, units[u]);
 }
 
 ssize_t bch_snprint_string_list(char *buf, size_t size, const char * const list[],
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 11+ messages in thread
* [PATCH] bcache: fix bch_hprint crash and improve output
@ 2017-09-01 20:37 Michael Lyle
  2017-09-04  6:07 ` Coly Li
  0 siblings, 1 reply; 11+ messages in thread
From: Michael Lyle @ 2017-09-01 20:37 UTC (permalink / raw)
  To: linux-bcache; +Cc: kent.overstreet, mlyle

Solve a crash where the stack is overrun when reading sysfs and
small negative values are present.  Also correct output, as before
it would output "1.10" for numbers bigger than "1.9", and negative
fractional output was incorrect.

Signed-off-by: Michael Lyle <mlyle@lyle.org>
Reported-by: Dmitry Yu Okunev <dyokunev@ut.mephi.ru>
---
 drivers/md/bcache/util.c | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/drivers/md/bcache/util.c b/drivers/md/bcache/util.c
index 8c3a938f4bf0..11957038c630 100644
--- a/drivers/md/bcache/util.c
+++ b/drivers/md/bcache/util.c
@@ -86,10 +86,14 @@ ssize_t bch_hprint(char *buf, int64_t v)
 	}
 
 	if (!u)
-		return sprintf(buf, "%llu", v);
+		return sprintf(buf, "%lli", v);
 
-	if (v < 100 && v > -100)
-		snprintf(dec, sizeof(dec), ".%i", t / 100);
+	if (t > 103) {
+		if (v > 0)
+			snprintf(dec, sizeof(dec), ".%i", t * 10 / 1024);
+		else
+			snprintf(dec, sizeof(dec), ".%i", 10 - (t * 10 / 1024));
+	}
 
 	return sprintf(buf, "%lli%s%c", v, dec, units[u]);
 }
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2017-09-05  4:56 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-09-04 21:55 [PATCH] bcache: fix bch_hprint crash and improve output Michael Lyle
2017-09-05  2:50 ` Coly Li
2017-09-05  4:19   ` Kent Overstreet
2017-09-05  4:52     ` Coly Li
2017-09-05  4:55       ` Kent Overstreet
2017-09-05  4:19 ` Kent Overstreet
2017-09-05  4:54   ` Coly Li
  -- strict thread matches above, loose matches on Subject: below --
2017-09-01 20:37 Michael Lyle
2017-09-04  6:07 ` Coly Li
2017-09-04 16:31   ` Michael Lyle
2017-09-04 16:56     ` Coly Li

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox