[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#779573: bibtool: heap buffer overflow in the bibtool tests



On 2015-03-02 16:35:51 +0100, Jerome BENOIT wrote:
> Thanks, it sounds helpful: I have just forwarded your last tow email
> to the mainstream maintainer: let wait for his feedback.

I've attached a patch for this bug.

I've also added a new test that triggers another heap buffer overflow
(this is based on my test used in bug 747519):

=================================================================
==1514==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x606000093fbc at pc 0x7f8ef3a6deec bp 0x7fffa07f6900 sp 0x7fffa07f68f8
READ of size 1 at 0x606000093fbc thread T0
    #0 0x7f8ef3a6deeb in line_breaking /home/vlefevre/software/bibtool-2.57+ds/print.c:275
    #1 0x7f8ef3a6eb65 in put_record /home/vlefevre/software/bibtool-2.57+ds/print.c:580
    #2 0x7f8ef3a5850c in print_segment /home/vlefevre/software/bibtool-2.57+ds/database.c:430
    #3 0x7f8ef3a59769 in print_db /home/vlefevre/software/bibtool-2.57+ds/database.c:654
    #4 0x7f8ef3a55b5e in main /home/vlefevre/software/bibtool-2.57+ds/main.c:619
    #5 0x7f8ef23aab44 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21b44)
    #6 0x7f8ef3a566a6 (/home/vlefevre/software/bibtool-2.57+ds/bibtool+0x116a6)

0x606000093fbc is located 0 bytes to the right of 60-byte region [0x606000093f80,0x606000093fbc)
allocated by thread T0 here:
    #0 0x7f8ef299f73f in malloc (/usr/lib/x86_64-linux-gnu/libasan.so.1+0x5473f)
    #1 0x7f8ef3a77c46 in new_string /home/vlefevre/software/bibtool-2.57+ds/symbols.c:155

SUMMARY: AddressSanitizer: heap-buffer-overflow /home/vlefevre/software/bibtool-2.57+ds/print.c:275 line_breaking
Shadow bytes around the buggy address:
  0x0c0c8000a7a0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c0c8000a7b0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c0c8000a7c0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c0c8000a7d0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c0c8000a7e0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
=>0x0c0c8000a7f0: 00 00 00 00 00 00 00[04]fa fa fa fa fd fd fd fd
  0x0c0c8000a800: fd fd fd fd fa fa fa fa fd fd fd fd fd fd fd fd
  0x0c0c8000a810: fa fa fa fa fd fd fd fd fd fd fd fd fa fa fa fa
  0x0c0c8000a820: fd fd fd fd fd fd fd fa fa fa fa fa fd fd fd fd
  0x0c0c8000a830: fd fd fd fa fa fa fa fa fd fd fd fd fd fd fd fd
  0x0c0c8000a840: fa fa fa fa fd fd fd fd fd fd fd fd fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:       fa
  Heap right redzone:      fb
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack partial redzone:   f4
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Contiguous container OOB:fc
  ASan internal:           fe
==1514==ABORTING

This corresponds to the "if ( *ptr == '\n' )" in the following print.c
excerpt:

        if ( 0 <= rsc_linelen - column )           /*                        */
          save_ptr = s + rsc_linelen - column;     /* Potential end          */
        else                                       /*                        */
          save_ptr = s;                            /*                        */
                                                   /*                        */
        for(ptr = s;                               /* Search next newline    */
            ptr <= save_ptr && *ptr != '\n';       /*  or end of region      */
            ptr++) {}                              /*                        */
                                                   /*                        */
        if ( *ptr == '\n' )                        /*                        */

Then I don't know whether save_ptr is miscomputed or the condition
ptr <= save_ptr is incorrect (possibly ptr < save_ptr).

-- 
Vincent Lefèvre <vincent@vinc17.net> - Web: <https://www.vinc17.net/>
100% accessible validated (X)HTML - Blog: <https://www.vinc17.net/blog/>
Work: CR INRIA - computer arithmetic / AriC project (LIP, ENS-Lyon)
diff -Nurd bibtool-2.57+ds~/rewrite.c bibtool-2.57+ds/rewrite.c
--- bibtool-2.57+ds~/rewrite.c	2014-04-17 08:56:32.000000000 +0200
+++ bibtool-2.57+ds/rewrite.c	2015-03-02 16:36:37.269247650 +0100
@@ -304,7 +304,7 @@
     DebugPrint2("field   = ",field);	   	   /*			     */
     (void)SParseSkip(&s);			   /*                        */
 						   /*			     */
-    if ( stackp > stacksize )			   /*                        */
+    if ( stackp >= stacksize )			   /*                        */
     { stacksize += 8;				   /*                        */
       if ( (stack=(Uchar**)realloc((char*)stack,   /*                        */
 				  stacksize*sizeof(char*)))==NULL)/*         */
#!/bin/perl -W
# =============================================================================
#  
#  This file is part of BibTool.
#  It is distributed under the GNU General Public License.
#  See the file COPYING for details.
#  
#  (c) 2011-2014 Gerd Neugebauer
#  
#  Net: gene@gerd-neugebauer.de
#  
#*=============================================================================

=head1 NAME

long_line.t - Test suite for BibTool with long line in input file.

=head1 SYNOPSIS

long_line.t 

=head1 DESCRIPTION

This module contains some test cases. Running this module as program
will run all test cases and print a summary for each. Optionally files
*.out and *.err are left if the expected result does not match the
actual result.

=head1 OPTIONS

none

=head1 AUTHOR

Gerd Neugebauer

=cut

use strict;
use BUnit;


#------------------------------------------------------------------------------
BUnit::run(name  => 'long_line',
    args         => '--select\'{@article}\'',
    expected_err =>'',
    bib	         => <<__EOF__,
\@Article{key,
  AUTHOR = {Aa Bbbbbbbb, Ccccccc and Dddddd, Eeeeee and Fffff, Gggggg},
  TITLE = {Some title}
}
__EOF__
    expected_out => <<__EOF__);

\@Article{	  key,
  author	= {Aa Bbbbbbbb, Ccccccc and Dddddd, Eeeeee and Fffff,
		  Gggggg},
  title		= {Some title}
}
__EOF__


1;
#------------------------------------------------------------------------------
# Local Variables: 
# mode: perl
# End: 

Reply to: