GNU bug report logs -
#76613
diff -y crashes with apparent memory corruption
Previous Next
To add a comment to this bug, you must first unarchive it, by sending
a message to control AT debbugs.gnu.org, with unarchive 76613 in the body.
You can then email your comments to 76613 AT debbugs.gnu.org in the normal way.
Toggle the display of automated, internal messages from the tracker.
Report forwarded
to
bug-diffutils <at> gnu.org
:
bug#76613
; Package
diffutils
.
(Thu, 27 Feb 2025 17:59:03 GMT)
Full text and
rfc822 format available.
Acknowledgement sent
to
"Nick Smallbone" <nick <at> smallbone.se>
:
New bug report received and forwarded. Copy sent to
bug-diffutils <at> gnu.org
.
(Thu, 27 Feb 2025 17:59:03 GMT)
Full text and
rfc822 format available.
Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):
Hi,
I'm running diffutils-3.11, downloaded from ftp.gnu.org and built with ./configure && make (no options given).
I'm seeing the problem that diff -y is crashing with various malloc-related errors. Here is an example. First I create two files a and b like so:
% seq 1 100 > a
% seq 1 100 | grep -v 50 > b
Then I run diff -y a b, which crashes with an error in free():
% diff -y a b
free(): corrupted unsorted chunks
zsh: IOT instruction src/diff -y ~/a ~/b
I haven't looked into the source to find out the problem, but I did compile a debug build and run it under Valgrind. It detected some memory corruption - here is the report:
==9602== Memcheck, a memory error detector
==9602== Copyright (C) 2002-2024, and GNU GPL'd, by Julian Seward et al.
==9602== Using Valgrind-3.24.0 and LibVEX; rerun with -h for copyright info
==9602== Command: src/diff -y /home/nick/a /home/nick/b
==9602==
==9602== Invalid write of size 8
==9602== at 0x40EC8A: find_and_hash_each_line (io.c:1017)
==9602== by 0x40FBAA: read_files (io.c:1366)
==9602== by 0x40596C: diff_2_files (analyze.c:463)
==9602== by 0x409B1F: compare_prepped_files (diff.c:1371)
==9602== by 0x40ADBF: compare_files (diff.c:1633)
==9602== by 0x408834: main (diff.c:881)
==9602== Address 0x4b12f80 is 0 bytes after a block of size 656 alloc'd
==9602== at 0x4850C7C: realloc (vg_replace_malloc.c:1801)
==9602== by 0x41A8A6: rpl_realloc (stdlib.h:2066)
==9602== by 0x41CE27: xrealloc (xmalloc.c:66)
==9602== by 0x41D196: xpalloc (xmalloc.c:271)
==9602== by 0x40EC4A: find_and_hash_each_line (io.c:1013)
==9602== by 0x40FBAA: read_files (io.c:1366)
==9602== by 0x40596C: diff_2_files (analyze.c:463)
==9602== by 0x409B1F: compare_prepped_files (diff.c:1371)
==9602== by 0x40ADBF: compare_files (diff.c:1633)
==9602== by 0x408834: main (diff.c:881)
==9602==
--9602-- VALGRIND INTERNAL ERROR: Valgrind received a signal 11 (SIGSEGV) - exiting
--9602-- si_code=1; Faulting address: 0x9622BA0; sp: 0x1002cf6e20
valgrind: the 'impossible' happened:
Killed by fatal signal
host stacktrace:
==9602== at 0x5804AE1F: ??? (in /usr/libexec/valgrind/memcheck-amd64-linux)
==9602== by 0x58004E0C: ??? (in /usr/libexec/valgrind/memcheck-amd64-linux)
==9602== by 0x58005203: ??? (in /usr/libexec/valgrind/memcheck-amd64-linux)
==9602== by 0x58097E37: ??? (in /usr/libexec/valgrind/memcheck-amd64-linux)
==9602== by 0x580E1E1A: ??? (in /usr/libexec/valgrind/memcheck-amd64-linux)
sched status:
running_tid=1
Thread 1: status = VgTs_Runnable (lwpid 9602)
==9602== at 0x4850A5F: calloc (vg_replace_malloc.c:1675)
==9602== by 0x4160B0: icalloc (ialloc.h:91)
==9602== by 0x41D239: xicalloc (xmalloc.c:304)
==9602== by 0x41D1E7: xizalloc (xmalloc.c:289)
==9602== by 0x405E39: diff_2_files (analyze.c:529)
==9602== by 0x409B1F: compare_prepped_files (diff.c:1371)
==9602== by 0x40ADBF: compare_files (diff.c:1633)
==9602== by 0x408834: main (diff.c:881)
client stack range: [0x1FFEFFD000 0x1FFF000FFF] client SP: 0x1FFEFFEDA0
valgrind stack range: [0x1002BF7000 0x1002CF6FFF] top usage: 7272 of 1048576
Nick
Information forwarded
to
bug-diffutils <at> gnu.org
:
bug#76613
; Package
diffutils
.
(Thu, 27 Feb 2025 19:14:03 GMT)
Full text and
rfc822 format available.
Message #8 received at 76613 <at> debbugs.gnu.org (full text, mbox):
Thanks for the bug report. I can reproduce it with gcc
-fsanitize=address on Ubuntu 24.10 x86-64. I plan to take a look at it soon.
Information forwarded
to
bug-diffutils <at> gnu.org
:
bug#76613
; Package
diffutils
.
(Fri, 28 Feb 2025 04:37:03 GMT)
Full text and
rfc822 format available.
Message #11 received at 76613 <at> debbugs.gnu.org (full text, mbox):
[Message part 1 (text/plain, inline)]
Hi Paul,
Paul Eggert <eggert <at> cs.ucla.edu> writes:
> Thanks for the bug report. I can reproduce it with gcc
> -fsanitize=address on Ubuntu 24.10 x86-64. I plan to take a look at it
> soon.
I see -fsanitize=address and valgrind fail this test starting at this
commit f54e901c329ba7b7d98ecae2571712f43444c2bd:
maint: use xpalloc
* bootstrap.conf (gnulib_modules): Add ialloc, to document
the now-direct dependency.
* src/diff.c (add_regexp):
* src/diff3.c (read_diff):
* src/dir.c (dir_read):
* src/io.c (slurp, find_and_hash_each_line, find_identical_ends):
* src/sdiff.c (diffarg):
Prefer xpalloc to doing it by hand.
* src/io.c: Include ialloc.h, for irealloc.
(equivs_alloc): Now idx_t, not lin, for xpalloc.
(sip): Don’t bother subtracting 2 * sizeof (word) from the
buffer_lcm upper bound, as later code works anyway now.
(slurp): Simplify buffer allocation so that xpalloc can be used.
Use irealloc for speculative reallocation, since the code could
work anyway if the irealloc fails. Use current->eof to check
for EOF, rather than the less-intuitive buffer size checks.
The previous commit passes it. Here are the relevant lines:
@@ -419,17 +411,16 @@ find_and_hash_each_line (struct file_data *current)
/* Maybe increase the size of the line table. */
if (line == alloc_lines)
{
- /* Double (alloc_lines - linbuf_base) by adding to alloc_lines. */
- if (IDX_MAX / 3 <= alloc_lines
- || IDX_MAX / sizeof *cureqs <= 2 * alloc_lines - linbuf_base
- || IDX_MAX / sizeof *linbuf <= alloc_lines - linbuf_base)
- xalloc_die ();
- alloc_lines = 2 * alloc_lines - linbuf_base;
- cureqs = xirealloc (cureqs, alloc_lines * sizeof *cureqs);
+ 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 = xirealloc (linbuf,
- (alloc_lines - linbuf_base) * sizeof *linbuf);
+ linbuf = xpalloc (linbuf, &n, 1, eqs_max - linbuf_base,
+ sizeof *linbuf);
linbuf -= linbuf_base;
+ alloc_lines = linbuf_base + n;
+ cureqs = xirealloc (cureqs, alloc_lines * sizeof *cureqs);
}
linbuf[line] = ip;
cureqs[line] = i;
@@ -445,16 +436,13 @@ find_and_hash_each_line (struct file_data *current)
so that we can compute the length of any buffered line. */
if (line == alloc_lines)
{
- /* Double (alloc_lines - linbuf_base) by adding to alloc_lines. */
- if (IDX_MAX / 3 <= alloc_lines
- || IDX_MAX / sizeof *cureqs <= 2 * alloc_lines - linbuf_base
- || IDX_MAX / sizeof *linbuf <= alloc_lines - linbuf_base)
- xalloc_die ();
- alloc_lines = 2 * alloc_lines - linbuf_base;
- linbuf += linbuf_base;
- linbuf = xirealloc (linbuf,
- (alloc_lines - linbuf_base) * sizeof *linbuf);
- linbuf -= linbuf_base;
+ /* 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 -= linbuf_base;
+ alloc_lines = n - linbuf_base;
}
linbuf[line] = p;
In the original version alloc_lines is calculated as
2 * alloc_lines - linbuf_base in both hunks. Afterwards it is
linbuf_base + n in one section and n - linbuf_base in the other.
I've attached a patch that satisfies sanitizers, but maybe I am missing
something in this code...
Collin
[0001-diff-fix-allocation-size-computation-that-could-caus.patch (text/x-patch, attachment)]
Reply sent
to
Paul Eggert <eggert <at> cs.ucla.edu>
:
You have taken responsibility.
(Sat, 01 Mar 2025 07:17:02 GMT)
Full text and
rfc822 format available.
Notification sent
to
"Nick Smallbone" <nick <at> smallbone.se>
:
bug acknowledged by developer.
(Sat, 01 Mar 2025 07:17:03 GMT)
Full text and
rfc822 format available.
Message #16 received at 76613-done <at> debbugs.gnu.org (full text, mbox):
On 2025-02-27 20:35, Collin Funk wrote:
> I've attached a patch that satisfies sanitizers
Thanks, that looks good, and I installed that one-line change along with
a NEWS file notice and a test case. And thanks to Nick for reporting
this. Closing the bug report.
Merged 76613 77265.
Request was from
Paul Eggert <eggert <at> cs.ucla.edu>
to
control <at> debbugs.gnu.org
.
(Wed, 26 Mar 2025 04:19:02 GMT)
Full text and
rfc822 format available.
bug archived.
Request was from
Debbugs Internal Request <help-debbugs <at> gnu.org>
to
internal_control <at> debbugs.gnu.org
.
(Wed, 23 Apr 2025 11:24:08 GMT)
Full text and
rfc822 format available.
This bug report was last modified 55 days ago.
Previous Next
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.