mirror of
https://https.git.savannah.gnu.org/git/diffutils.git
synced 2026-01-26 15:03:22 +00:00
diff: fix xpalloc-related signed integer overflow
Problem reported by Gisle Vanem <https://bugs.gnu.org/64316>. * src/io.c (find_and_hash_each_line): Rely on xpalloc to check for integer overflow instead of trying to do it ourselves incorrectly, with old code that predated the use of xpalloc. * src/system.h: Verify that LIN_MAX == IDX_MAX, since the code now relies on this. * tests/Makefile.am (TESTS): Add bug-64316. * tests/bug-64316: New file
This commit is contained in:
parent
bdc8608705
commit
359b8c3ef2
@ -288,10 +288,10 @@ struct file_data {
|
||||
/* Array of pointers to lines in the file. */
|
||||
char const **linbuf;
|
||||
|
||||
/* linbuf_base <= buffered_lines <= valid_lines <= alloc_lines.
|
||||
linebuf[linbuf_base ... buffered_lines - 1] are possibly differing.
|
||||
linebuf[linbuf_base ... valid_lines - 1] contain valid data.
|
||||
linebuf[linbuf_base ... alloc_lines - 1] are allocated. */
|
||||
/* linbuf_base <= 0 <= buffered_lines <= valid_lines <= alloc_lines.
|
||||
linbuf[0 ... buffered_lines - 1] are possibly differing.
|
||||
linbuf[linbuf_base ... valid_lines - 1] contain valid data.
|
||||
linbuf[linbuf_base ... alloc_lines - 1] are allocated. */
|
||||
lin linbuf_base, buffered_lines, valid_lines, alloc_lines;
|
||||
|
||||
/* Pointer to end of prefix of this file to ignore when hashing. */
|
||||
|
||||
12
src/io.c
12
src/io.c
@ -381,9 +381,7 @@ find_and_hash_each_line (struct file_data *current)
|
||||
/* Create a new equivalence class in this bucket. */
|
||||
i = eqs_index++;
|
||||
if (i == eqs_alloc)
|
||||
eqs = xpalloc (eqs, &eqs_alloc, 1,
|
||||
LIN_MAX < PTRDIFF_MAX ? LIN_MAX : -1,
|
||||
sizeof *eqs);
|
||||
eqs = xpalloc (eqs, &eqs_alloc, 1, -1, sizeof *eqs);
|
||||
eqs[i].next = *bucket;
|
||||
eqs[i].hash = h;
|
||||
eqs[i].line = ip;
|
||||
@ -417,13 +415,10 @@ find_and_hash_each_line (struct file_data *current)
|
||||
/* Maybe increase the size of the line table. */
|
||||
if (line == alloc_lines)
|
||||
{
|
||||
idx_t eqs_max = MIN (LIN_MAX, IDX_MAX / sizeof *cureqs);
|
||||
|
||||
/* Grow (alloc_lines - linbuf_base) by adding to alloc_lines. */
|
||||
idx_t n = alloc_lines - linbuf_base;
|
||||
linbuf += linbuf_base;
|
||||
linbuf = xpalloc (linbuf, &n, 1, eqs_max - linbuf_base,
|
||||
sizeof *linbuf);
|
||||
linbuf = xpalloc (linbuf, &n, 1, -1, sizeof *linbuf);
|
||||
linbuf -= linbuf_base;
|
||||
alloc_lines = linbuf_base + n;
|
||||
cureqs = xirealloc (cureqs, alloc_lines * sizeof *cureqs);
|
||||
@ -445,8 +440,7 @@ find_and_hash_each_line (struct file_data *current)
|
||||
/* Grow (alloc_lines - linbuf_base) by adding to alloc_lines. */
|
||||
idx_t n = alloc_lines - linbuf_base;
|
||||
linbuf += linbuf_base;
|
||||
linbuf = xpalloc (linbuf, &n, 1, MAX (0, IDX_MAX - linbuf_base),
|
||||
sizeof *linbuf);
|
||||
linbuf = xpalloc (linbuf, &n, 1, -1, sizeof *linbuf);
|
||||
linbuf -= linbuf_base;
|
||||
alloc_lines = n - linbuf_base;
|
||||
}
|
||||
|
||||
@ -129,7 +129,7 @@ typedef struct incomplete *word;
|
||||
typedef ptrdiff_t lin;
|
||||
#define LIN_MAX PTRDIFF_MAX
|
||||
#define pI "t"
|
||||
verify (LIN_MAX <= IDX_MAX);
|
||||
verify (LIN_MAX == IDX_MAX);
|
||||
|
||||
/* This section contains POSIX-compliant defaults for macros
|
||||
that are meant to be overridden by hand in config.h as needed. */
|
||||
|
||||
@ -5,6 +5,7 @@ TESTS = \
|
||||
bignum \
|
||||
binary \
|
||||
brief-vs-stat-zero-kernel-lies \
|
||||
bug-64316 \
|
||||
cmp \
|
||||
colliding-file-names \
|
||||
diff3 \
|
||||
|
||||
31
tests/bug-64316
Executable file
31
tests/bug-64316
Executable file
@ -0,0 +1,31 @@
|
||||
#!/bin/sh
|
||||
# Test for signed integer overflow bug within diff.
|
||||
# Bug reported by Gisele Vanem <http://bugs.gnu.org/64316>.
|
||||
# Compile with gcc -fsanitize=undefined to test for this bug.
|
||||
|
||||
. "${srcdir=.}/init.sh"; path_prepend_ ../src
|
||||
|
||||
fail=0
|
||||
|
||||
for f in a b; do
|
||||
printf 'c\nd\ne\nf\ng\n%s\nh\ni\nj\nk\nl\n' $f >$f || framework_failure_
|
||||
done
|
||||
|
||||
cat >exp <<'EOF' || framework_failure_
|
||||
@@ -3,7 +3,7 @@
|
||||
e
|
||||
f
|
||||
g
|
||||
-a
|
||||
+b
|
||||
h
|
||||
i
|
||||
j
|
||||
EOF
|
||||
|
||||
returns_ 1 diff -u a b >out 2>err || fail=1
|
||||
sed '1,2d' out >out1 || framework_failure_
|
||||
compare exp out1 || fail=1
|
||||
compare /dev/null err || fail=1
|
||||
|
||||
Exit $fail
|
||||
Loading…
x
Reference in New Issue
Block a user