I've made the following commit to FreeBSD's humanize_number which has
diverged quite a lot from NetBSD's, but it looks like we've shared this
bug since 2004 or so.
The error occurs due to this loop:
for (i = 0; bytes >= max - 50 && i < maxscale; i++)
'i' then gets used as a scale passed to SCALE2PREFIX(), but maxscale
would be more correctly named numscale so if i == 7 it's out of bounds.
-- Brooks
P.S. IMO the real cause of this off-by-one error is the failure to use a
proper array of prefixes. FreeBSD makes it worse by adding Ki, Mi, etc
so the prefixes strings are all three characters per suffix making the
code unreadable.
----- Forwarded message from Brooks Davis <brooks%FreeBSD.org@localhost> -----
Date: Thu, 13 Apr 2017 15:49:33 +0000 (UTC)
From: Brooks Davis <brooks%FreeBSD.org@localhost>
To: src-committers%freebsd.org@localhost, svn-src-all%freebsd.org@localhost,
svn-src-head%freebsd.org@localhost
Subject: svn commit: r316766 - head/lib/libutil
Author: brooks
Date: Thu Apr 13 15:49:32 2017
New Revision: 316766
URL: https://svnweb.freebsd.org/changeset/base/316766
Log:
Correct an out of bounds read with HN_AUTOSCALE and very large numbers.
The maximum scale is 6 (K, M, G, T, P, E) (B is 0).
Overly large explict scales were checked correctly, but for sufficently
large numbers HN_AUTOSCALE would get to 7 resulting in an out of bounds
read.
Found with humanize_number_test and CHERI bounds checking.
Reviewed by: emaste
Obtained from: CheriBSD
MFC after: 1 week
Sponsored by: DARPA, AFRL
Differential Revision: https://reviews.freebsd.org/D10376
Modified:
head/lib/libutil/humanize_number.c
Modified: head/lib/libutil/humanize_number.c
==============================================================================
--- head/lib/libutil/humanize_number.c Thu Apr 13 15:47:58 2017 (r316765)
+++ head/lib/libutil/humanize_number.c Thu Apr 13 15:49:32 2017 (r316766)
@@ -43,7 +43,7 @@ __FBSDID("$FreeBSD$");
#include <locale.h>
#include <libutil.h>
-static const int maxscale = 7;
+static const int maxscale = 6;
int
humanize_number(char *buf, size_t len, int64_t quotient,
@@ -64,7 +64,7 @@ humanize_number(char *buf, size_t len, i
return (-1);
if (scale < 0)
return (-1);
- else if (scale >= maxscale &&
+ else if (scale > maxscale &&
((scale & ~(HN_AUTOSCALE|HN_GETSCALE)) != 0))
return (-1);
if ((flags & HN_DIVISOR_1000) && (flags & HN_IEC_PREFIXES))
----- End forwarded message -----
Attachment:
signature.asc
Description: PGP signature