summaryrefslogtreecommitdiffstats
path: root/text-utils/ul.c
diff options
context:
space:
mode:
authorTobias Stoeckmann2016-09-08 21:19:22 +0200
committerKarel Zak2016-09-29 11:49:08 +0200
commitf20b214edc6e0c422a9a8991929fb793ee543dda (patch)
tree2069785c72d4a78280c31c6cd212efb4abc99047 /text-utils/ul.c
parentlib/strutils: make left and right trims more robust (diff)
downloadkernel-qcow2-util-linux-f20b214edc6e0c422a9a8991929fb793ee543dda.tar.gz
kernel-qcow2-util-linux-f20b214edc6e0c422a9a8991929fb793ee543dda.tar.xz
kernel-qcow2-util-linux-f20b214edc6e0c422a9a8991929fb793ee543dda.zip
ul: Fix buffer overflow
The text-utility ul can run into a buffer overflow on very long lines. See this proof of concept how to reproduce the issue: $ dd if=/dev/zero bs=1M count=10 | tr '\000' '\041' > poc.txt $ echo -ne '\xe\x5f\x8\x5f\x61\x2\xf\x5f\x8\x5f' | dd of=poc.txt conv=notrunc $ ul -i poc.txt > /dev/null # output would take ages Segmentation fault $ _ The problem manifests by using alloca with "maxcol", which can be as large as INT_MAX, based on the input line. A very long line (> 8 MB) with modes must be supplied to ul, as seen in my proof of concept byte sequence above. It is rather easy to fix this issue: allocate space on the heap instead. maxcol could overflow here, but in that case no system will have enough space to handle the request, properly ending ul through an err() call. Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
Diffstat (limited to 'text-utils/ul.c')
-rw-r--r--text-utils/ul.c14
1 files changed, 4 insertions, 10 deletions
diff --git a/text-utils/ul.c b/text-utils/ul.c
index 6721974de..3fd0b6a85 100644
--- a/text-utils/ul.c
+++ b/text-utils/ul.c
@@ -402,11 +402,7 @@ static void flushln(void)
static void overstrike(void)
{
register int i;
-#ifdef __GNUC__
- register wchar_t *lbuf = __builtin_alloca((maxcol + 1) * sizeof(wchar_t));
-#else
- wchar_t lbuf[BUFSIZ];
-#endif
+ register wchar_t *lbuf = xmalloc((maxcol + 1) * sizeof(wchar_t));
register wchar_t *cp = lbuf;
int hadbold=0;
@@ -439,16 +435,13 @@ static void overstrike(void)
for (cp = lbuf; *cp; cp++)
putwchar(*cp == '_' ? ' ' : *cp);
}
+ free(lbuf);
}
static void iattr(void)
{
register int i;
-#ifdef __GNUC__
- register wchar_t *lbuf = __builtin_alloca((maxcol+1)*sizeof(wchar_t));
-#else
- wchar_t lbuf[BUFSIZ];
-#endif
+ register wchar_t *lbuf = xmalloc((maxcol + 1) * sizeof(wchar_t));
register wchar_t *cp = lbuf;
for (i = 0; i < maxcol; i++)
@@ -465,6 +458,7 @@ static void iattr(void)
*cp = 0;
fputws(lbuf, stdout);
putwchar('\n');
+ free(lbuf);
}
static void initbuf(void)