Bug 85253 - [8 Regression] asan detects heap-buffer-overflow in matmul_r4.c
Summary: [8 Regression] asan detects heap-buffer-overflow in matmul_r4.c
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: libfortran (show other bugs)
Version: 8.0.1
: P4 normal
Target Milestone: 8.0
Assignee: Thomas Koenig
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2018-04-06 11:15 UTC by Vittorio Zecca
Modified: 2018-05-04 06:06 UTC (History)
2 users (show)

See Also:
Host: x86_64-pc-linux-gnu
Target: x86_64-pc-linux-gnu
Build:
Known to work: 7.0.1
Known to fail: 8.0.1
Last reconfirmed: 2018-04-06 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Vittorio Zecca 2018-04-06 11:15:38 UTC
! In trunk 258946 asan detects heap buffer overflow in libgfortran/generated/matmul_r4.c:2035 
! "t1[l - ll + 2 + ((i - ii + 2) << 8) - 257] = a[i + 1 + (l + 1) * a_dim1];"
! l=1 ll=1 i=1 ii=1 a_dim1=2
! Generated with ~/local/gcc-258946-address/bin/gfortran p.f -g -lasan -static-libgfortran
! Initially detected with "export MALLOC_CHECK_=1" (see man mallopt) (I put it into .bashrc)
! gfortran 7.3.0 seems to be ok
      real data_d(2,2),ptr(1,2) ! and similarly for other real and integer types (complex ok)
      data data_d/1,2,3,4/
      data ptr/1,2/
      print *,MATMUL(data_d,TRANSPOSE(ptr)) !must display 7.0 10.0
      end
!./a.out
!=================================================================
!==32750==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x619000000484 at pc 0x00000041ac82 bp 0x7fff2a84aff0 sp 0x7fff2a84afe8
!WRITE of size 4 at 0x619000000484 thread T0
!    #0 0x41ac81 in matmul_r4_vanilla ../../../gcc-258946/libgfortran/generated/matmul_r4.c:2035
!    #1 0x41f348 in _gfortran_matmul_r4 ../../../gcc-258946/libgfortran/generated/matmul_r4.c:2377
!    #2 0x402efe in MAIN__ /home/vitti/1tb/vitti/test/cp2k-18361/cp2k/tests/QS/regtest-pao-2/p.f:6
!    #3 0x402fa6 in main /home/vitti/1tb/vitti/test/cp2k-18361/cp2k/tests/QS/regtest-pao-2/p.f:7
!    #4 0x147ac2eeff29 in __libc_start_main (/usr/lib64/libc.so.6+0x20f29)
!    #5 0x402bc9 in _start (/home/vitti/1tb/vitti/test/cp2k-18361/cp2k/tests/QS/regtest-pao-2/a.out+0x402bc9)
!
!0x619000000484 is located 0 bytes to the right of 1028-byte region [0x619000000080,0x619000000484)
!allocated by thread T0 here:
!    #0 0x147ac3b10040 in __interceptor_malloc ../../../../gcc/libsanitizer/asan/asan_malloc_linux.cc:86
!    #1 0x41a6db in matmul_r4_vanilla ../../../gcc-258946/libgfortran/generated/matmul_r4.c:1995
!    #2 0x41f348 in _gfortran_matmul_r4 ../../../gcc-258946/libgfortran/generated/matmul_r4.c:2377
!    #3 0x402efe in MAIN__ /home/vitti/1tb/vitti/test/cp2k-18361/cp2k/tests/QS/regtest-pao-2/p.f:6
!    #4 0x402fa6 in main /home/vitti/1tb/vitti/test/cp2k-18361/cp2k/tests/QS/regtest-pao-2/p.f:7
!    #5 0x147ac2eeff29 in __libc_start_main (/usr/lib64/libc.so.6+0x20f29)
!
!SUMMARY: AddressSanitizer: heap-buffer-overflow ../../../gcc-258946/libgfortran/generated/matmul_r4.c:2035 in matmul_r4_vanilla
!Shadow bytes around the buggy address:
!  0x0c327fff8040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
!  0x0c327fff8050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
!  0x0c327fff8060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
!  0x0c327fff8070: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
!  0x0c327fff8080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
!=>0x0c327fff8090:[04]fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
!  0x0c327fff80a0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
!  0x0c327fff80b0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
!  0x0c327fff80c0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
!  0x0c327fff80d0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
!  0x0c327fff80e0: fa fa fa fa fa fa fa fa fa fa fa fa 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
!  Freed heap region:       fd
!  Stack left redzone:      f1
!  Stack mid redzone:       f2
!  Stack right redzone:     f3
!  Stack after return:      f5
!  Stack use after scope:   f8
!  Global redzone:          f9
!  Global init order:       f6
!  Poisoned by user:        f7
!  Container overflow:      fc
!  Array cookie:            ac
!  Intra object redzone:    bb
!  ASan internal:           fe
!  Left alloca redzone:     ca
!  Right alloca redzone:    cb
!==32750==ABORTING
Comment 1 Dominique d'Humieres 2018-04-06 11:54:09 UTC
It looks to be a gcc8 regression that occurred between revision r245276 (7.0.1) and r254086 (8.0).

I see

==28006==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x619000000984 at pc 0x000105e887a3 bp 0x7ffeea337be0 sp 0x7ffeea337bd8
WRITE of size 4 at 0x619000000984 thread T0
    #0 0x105e887a2 in matmul_r4_avx matmul_r4.c:365
...
Comment 2 Thomas Koenig 2018-04-06 14:35:42 UTC
Probably my memory saving patch.

I'll investigate.
Comment 3 Thomas Koenig 2018-04-06 15:04:23 UTC
Yep, looking at the code, it seems that in this special
case, we need one more row in the temporary buffer.

This seems to cure it.

Index: m4/matmul_internal.m4
===================================================================
--- m4/matmul_internal.m4       (Revision 259152)
+++ m4/matmul_internal.m4       (Arbeitskopie)
@@ -234,7 +234,7 @@ sinclude(`matmul_asm_'rtype_code`.m4')dnl
 
       /* Adjust size of t1 to what is needed.  */
       index_type t1_dim;
-      t1_dim = (a_dim1-1) * 256 + b_dim1;
+      t1_dim = (a_dim1- (ycount > 1)) * 256 + b_dim1;
       if (t1_dim > 65536)
        t1_dim = 65536;
Comment 4 Vittorio Zecca 2018-04-06 15:35:44 UTC
After applying the fix in comment #3 the asan message disappeared.
Comment 5 Thomas Koenig 2018-04-06 18:49:52 UTC
Author: tkoenig
Date: Fri Apr  6 18:49:21 2018
New Revision: 259188

URL: https://gcc.gnu.org/viewcvs?rev=259188&root=gcc&view=rev
Log:
2018-04-06  Thomas Koenig  <tkoenig@gcc.gnu.org>

	PR libfortran/85253
	* m4/matmul_internal.m4: If ycount == 1, add one more row to
	the internal buffer.
	* generated/matmul_c10.c: Regenerated.
	* generated/matmul_c16.c: Regenerated.
	* generated/matmul_c4.c: Regenerated.
	* generated/matmul_c8.c: Regenerated.
	* generated/matmul_i1.c: Regenerated.
	* generated/matmul_i16.c: Regenerated.
	* generated/matmul_i2.c: Regenerated.
	* generated/matmul_i4.c: Regenerated.
	* generated/matmul_i8.c: Regenerated.
	* generated/matmul_r10.c: Regenerated.
	* generated/matmul_r16.c: Regenerated.
	* generated/matmul_r4.c: Regenerated.
	* generated/matmul_r8.c: Regenerated.
	* generated/matmulavx128_c10.c: Regenerated.
	* generated/matmulavx128_c16.c: Regenerated.
	* generated/matmulavx128_c4.c: Regenerated.
	* generated/matmulavx128_c8.c: Regenerated.
	* generated/matmulavx128_i1.c: Regenerated.
	* generated/matmulavx128_i16.c: Regenerated.
	* generated/matmulavx128_i2.c: Regenerated.
	* generated/matmulavx128_i4.c: Regenerated.
	* generated/matmulavx128_i8.c: Regenerated.
	* generated/matmulavx128_r10.c: Regenerated.
	* generated/matmulavx128_r16.c: Regenerated.
	* generated/matmulavx128_r4.c: Regenerated.
	* generated/matmulavx128_r8.c: Regenerated.


Modified:
    trunk/libgfortran/ChangeLog
    trunk/libgfortran/generated/matmul_c10.c
    trunk/libgfortran/generated/matmul_c16.c
    trunk/libgfortran/generated/matmul_c4.c
    trunk/libgfortran/generated/matmul_c8.c
    trunk/libgfortran/generated/matmul_i1.c
    trunk/libgfortran/generated/matmul_i16.c
    trunk/libgfortran/generated/matmul_i2.c
    trunk/libgfortran/generated/matmul_i4.c
    trunk/libgfortran/generated/matmul_i8.c
    trunk/libgfortran/generated/matmul_r10.c
    trunk/libgfortran/generated/matmul_r16.c
    trunk/libgfortran/generated/matmul_r4.c
    trunk/libgfortran/generated/matmul_r8.c
    trunk/libgfortran/generated/matmulavx128_c10.c
    trunk/libgfortran/generated/matmulavx128_c16.c
    trunk/libgfortran/generated/matmulavx128_c4.c
    trunk/libgfortran/generated/matmulavx128_c8.c
    trunk/libgfortran/generated/matmulavx128_i1.c
    trunk/libgfortran/generated/matmulavx128_i16.c
    trunk/libgfortran/generated/matmulavx128_i2.c
    trunk/libgfortran/generated/matmulavx128_i4.c
    trunk/libgfortran/generated/matmulavx128_i8.c
    trunk/libgfortran/generated/matmulavx128_r10.c
    trunk/libgfortran/generated/matmulavx128_r16.c
    trunk/libgfortran/generated/matmulavx128_r4.c
    trunk/libgfortran/generated/matmulavx128_r8.c
    trunk/libgfortran/m4/matmul_internal.m4
Comment 6 Thomas Koenig 2018-04-06 18:51:00 UTC
Fixed, closing.

Thanks for the bug report!
Comment 7 Vittorio Zecca 2018-04-06 21:59:24 UTC
You are welcome, very fast fix, keep up the good work!
Comment 8 Vittorio Zecca 2018-05-04 06:06:14 UTC
Compiling and running under both 8.0.1 and 8.1.0
with MALLOC_CHECK_=1 (see man mallopt)

I get the following (notice "free(): invalid pointer" from mallopt)

/usr/bin/gfortran -g -O0 gfbug144.f 
[vitti f95]$./a.out
free(): invalid pointer

Program received signal SIGABRT: Process abort signal.

Backtrace for this error:
#0  0x1461bb3fffcf in ???
	at /usr/src/debug/glibc-2.27-37-g39071a5539/signal/../sysdeps/unix/sysv/linux/x86_64/sigaction.c:0
#1  0x1461bb3fff4b in __GI_raise
	at ../sysdeps/unix/sysv/linux/raise.c:51
#2  0x1461bb3ea590 in __GI_abort
	at /usr/src/debug/glibc-2.27-37-g39071a5539/stdlib/abort.c:79
#3  0x1461bb442b0a in __libc_message
	at ../sysdeps/posix/libc_fatal.c:181
#4  0x1461bb44903b in malloc_printerr
	at /usr/src/debug/glibc-2.27-37-g39071a5539/malloc/malloc.c:5350
#5  0x1461bb44cdfd in free_check
	at /usr/src/debug/glibc-2.27-37-g39071a5539/malloc/hooks.c:274
#6  0x400920 in MAIN__
	at /home/vitti/f95/gfbug144.f:11
#7  0x4009c4 in main
	at /home/vitti/f95/gfbug144.f:12
Aborted (core dumped)

with valgrind:

valgrind ./a.out
==30798== Memcheck, a memory error detector
==30798== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==30798== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==30798== Command: ./a.out
==30798== 
==30798== Invalid write of size 4
==30798==    at 0x4F0E903: matmul_i4_vanilla (matmul_i4.c:2035)
==30798==    by 0x400920: MAIN__ (gfbug144.f:11)
==30798==    by 0x4009C4: main (gfbug144.f:12)
==30798==  Address 0x6079ec4 is 0 bytes after a block of size 1,028 alloc'd
==30798==    at 0x4C2DBAB: malloc (vg_replace_malloc.c:299)
==30798==    by 0x4F0D24A: matmul_i4_vanilla (matmul_i4.c:1995)
==30798==    by 0x400920: MAIN__ (gfbug144.f:11)
==30798==    by 0x4009C4: main (gfbug144.f:12)
==30798== 
==30798== Invalid read of size 4
==30798==    at 0x4F10EE6: matmul_i4_vanilla (matmul_i4.c:2197)
==30798==    by 0x400920: MAIN__ (gfbug144.f:11)
==30798==    by 0x4009C4: main (gfbug144.f:12)
==30798==  Address 0x6079ec4 is 0 bytes after a block of size 1,028 alloc'd
==30798==    at 0x4C2DBAB: malloc (vg_replace_malloc.c:299)
==30798==    by 0x4F0D24A: matmul_i4_vanilla (matmul_i4.c:1995)
==30798==    by 0x400920: MAIN__ (gfbug144.f:11)
==30798==    by 0x4009C4: main (gfbug144.f:12)
==30798== 
==30798== Conditional jump or move depends on uninitialised value(s)
==30798==    at 0x506872E: write_decimal.constprop.10 (write.c:808)
==30798==    by 0x5068B13: write_integer (write.c:1351)
==30798==    by 0x5069AED: list_formatted_write_scalar (write.c:1865)
==30798==    by 0x506A834: _gfortrani_list_formatted_write (write.c:1943)
==30798==    by 0x400966: MAIN__ (gfbug144.f:11)
==30798==    by 0x4009C4: main (gfbug144.f:12)
==30798== 
           7          10
==30798== 
==30798== HEAP SUMMARY:
==30798==     in use at exit: 0 bytes in 0 blocks
==30798==   total heap usage: 22 allocs, 22 frees, 14,548 bytes allocated
==30798== 
==30798== All heap blocks were freed -- no leaks are possible
==30798== 
==30798== For counts of detected and suppressed errors, rerun with: -v
==30798== Use --track-origins=yes to see where uninitialised values come from
==30798== ERROR SUMMARY: 4 errors from 3 contexts (suppressed: 0 from 0)