From: Jim Meyering Date: Sat, 28 Aug 2010 15:45:29 +0000 (+0200) Subject: tac: avoid double free X-Git-Tag: v8.6~57 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=777024889c0043004962834f4d9353cfa6847dd6;p=platform%2Fupstream%2Fcoreutils.git tac: avoid double free * src/tac.c (main): Reading a line longer than 16KiB would cause tac to realloc its primary buffer. Then, just before exit, tac would mistakenly free the original (now free'd) buffer. This bug was introduced by commit be6c13e7, "maint: always free a buffer, to avoid even semblance of a leak". * NEWS (Bug fixes): Mention it. * tests/misc/tac (double-free): New test, to exercise this. Reported by Salvo Tomaselli in . --- diff --git a/NEWS b/NEWS index 93a1f96..3eb28b1 100644 --- a/NEWS +++ b/NEWS @@ -11,6 +11,9 @@ GNU coreutils NEWS -*- outline -*- du -H and -L now consistently count pointed-to files instead of symbolic links, and correctly diagnose dangling symlinks. + tac would perform a double-free when given an input line longer than 16KiB. + [bug introduced in coreutils-8.3] + ** New features cp now accepts the --attributes-only option to not copy file data, diff --git a/src/tac.c b/src/tac.c index cec9736..859e006 100644 --- a/src/tac.c +++ b/src/tac.c @@ -633,7 +633,6 @@ main (int argc, char **argv) if (! (read_size < half_buffer_size && half_buffer_size < G_buffer_size)) xalloc_die (); G_buffer = xmalloc (G_buffer_size); - void *buf = G_buffer; if (sentinel_length) { strcpy (G_buffer, separator); @@ -666,6 +665,9 @@ main (int argc, char **argv) error (0, errno, "-"); ok = false; } - free (buf); + + size_t offset = sentinel_length ? sentinel_length : 1; + free (G_buffer - offset); + exit (ok ? EXIT_SUCCESS : EXIT_FAILURE); } diff --git a/tests/misc/tac b/tests/misc/tac index 7631049..4130c00 100755 --- a/tests/misc/tac +++ b/tests/misc/tac @@ -24,6 +24,9 @@ my $prog = 'tac'; my $bad_dir = 'no/such/dir'; +# This must be longer than 16KiB to trigger the double free in coreutils-8.5. +my $long_line = 'o' x (16 * 1024 + 1); + my @Tests = ( ['segfault', '-r', {IN=>"a\n"}, {IN=>"b\n"}, {OUT=>"a\nb\n"}], @@ -67,6 +70,9 @@ my @Tests = {ERR_SUBST => "s,`$bad_dir': .*,...,"}, {ERR => "$prog: cannot create temporary file in ...\n"}, {EXIT => 1}], + + # coreutils-8.5's tac would double-free its primary buffer. + ['double-free', {IN=>$long_line}, {OUT=>$long_line}], ); @Tests = triple_test \@Tests;