Note: This bug is displayed in read-only format because the product is no longer active in Red Hat Bugzilla.
RHEL Engineering is moving the tracking of its product development work on RHEL 6 through RHEL 9 to Red Hat Jira (issues.redhat.com). If you're a Red Hat customer, please continue to file support cases via the Red Hat customer portal. If you're not, please head to the "RHEL project" in Red Hat Jira and file new tickets here. Individual Bugzilla bugs in the statuses "NEW", "ASSIGNED", and "POST" are being migrated throughout September 2023. Bugs of Red Hat partners with an assigned Engineering Partner Manager (EPM) are migrated in late September as per pre-agreed dates. Bugs against components "kernel", "kernel-rt", and "kpatch" are only migrated if still in "NEW" or "ASSIGNED". If you cannot log in to RH Jira, please consult article #7032570. That failing, please send an e-mail to the RH Jira admins at rh-issues@redhat.com to troubleshoot your issue as a user management inquiry. The email creates a ServiceNow ticket with Red Hat. Individual Bugzilla bugs that are migrated will be moved to status "CLOSED", resolution "MIGRATED", and set with "MigratedToJIRA" in "Keywords". The link to the successor Jira issue will be found under "Links", have a little "two-footprint" icon next to it, and direct you to the "RHEL project" in Red Hat Jira (issue links are of type "https://issues.redhat.com/browse/RHEL-XXXX", where "X" is a digit). This same link will be available in a blue banner at the top of the page informing you that that bug has been migrated.

Bug 2230598

Summary: compiler bug on aarm64: Memory allocation failure in xrealloc
Product: Red Hat Enterprise Linux 9 Reporter: Paulo Andrade <pandrade>
Component: gccAssignee: Marek Polacek <mpolacek>
gcc sub component: system-version QA Contact: qe-baseos-tools-bugs
Status: CLOSED NOTABUG Docs Contact:
Severity: medium    
Priority: medium CC: ahajkova, fweimer, jakub, ohudlick, sipoyare
Version: 9.2Flags: pm-rhel: mirror+
Target Milestone: rc   
Target Release: ---   
Hardware: aarch64   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: If docs needed, set a value
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2023-08-09 19:17:58 UTC Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:
Attachments:
Description Flags
simple.c
none
simple.f none

Description Paulo Andrade 2023-08-09 17:13:27 UTC
Created attachment 1982609 [details]
simple.c

Reproducer:

$ gcc -c simple.c
$ gfortran -g -O0 simple.f -o simple simple.o
$ ./simple
Operating system error: Cannot allocate memory
Memory allocation failure in xrealloc

Several minor changes to simple.c workaround the problem, but should be
just hiding the problem.

$ rpm -q gcc libgfortran
gcc-11.3.1-4.3.el9.aarch64
libgfortran-11.3.1-4.3.el9.aarch64

...
Catchpoint 2 (call to syscall mmap), __GI___mmap64 (offset=0, fd=-1, flags=34, prot=3, len=281470681747456, addr=0x0)
    at ../sysdeps/unix/sysv/linux/mmap64.c:59
59	  return (void *) MMAP_CALL (mmap, addr, len, prot, flags, fd, offset);
(gdb) bt full
#0  __GI___mmap64 (offset=0, fd=-1, flags=34, prot=3, len=281470681747456, addr=0x0) at ../sysdeps/unix/sysv/linux/mmap64.c:59
        sc_ret = 0
#1  __GI___mmap64 (addr=addr@entry=0x0, len=len@entry=281470681747456, prot=3, flags=flags@entry=34, fd=fd@entry=-1, offset=offset@entry=0)
    at ../sysdeps/unix/sysv/linux/mmap64.c:47
        sc_ret = <optimized out>
        _sys_result = <optimized out>
        _x5tmp = <optimized out>
        _x4tmp = <optimized out>
        _x3tmp = <optimized out>
        _x2tmp = <optimized out>
        _x1tmp = <optimized out>
        _x0tmp = <optimized out>
        _x0 = <optimized out>
        _x1 = <optimized out>
        _x2 = <optimized out>
        _x3 = <optimized out>
        _x4 = <optimized out>
        _x5 = <optimized out>
        _x8 = <optimized out>
#2  0x0000fffff7c4e16c in sysmalloc (nb=nb@entry=281470681743888, av=av@entry=0xfffff7d5daf8 <main_arena>) at malloc.c:2424
        mm = <optimized out>
        old_top = <optimized out>
        old_size = <optimized out>
        old_end = <optimized out>
        size = 281470681747456
        brk = <optimized out>
        correction = <optimized out>
        snd_brk = <optimized out>
        front_misalign = <optimized out>
        end_misalign = <optimized out>
        aligned_brk = <optimized out>
        p = <optimized out>
        remainder = <optimized out>
        remainder_size = <optimized out>
        pagesize = 4096
        tried_mmap = true
        __PRETTY_FUNCTION__ = "sysmalloc"
#3  0x0000fffff7c4efa0 in _int_malloc (av=av@entry=0xfffff7d5daf8 <main_arena>, bytes=bytes@entry=281470681743873) at malloc.c:4274
        p = <optimized out>
        iters = <optimized out>
        nb = 281470681743888
        idx = 127
        bin = <optimized out>
        victim = <optimized out>
        size = <optimized out>
        victim_index = <optimized out>
        remainder = <optimized out>
        remainder_size = <optimized out>
        block = <optimized out>
        bit = <optimized out>
        map = <optimized out>
        fwd = <optimized out>
        bck = <optimized out>
        tcache_unsorted_count = 0
        tcache_nb = <optimized out>
        tc_idx = 17591917608991
        return_cached = <optimized out>
        __PRETTY_FUNCTION__ = "_int_malloc"
#4  0x0000fffff7c4f344 in _int_realloc (av=0xfffff7d5daf8 <main_arena>, oldp=0x421c20, oldsize=528, nb=281470681743888) at malloc.c:4745
        newp = <optimized out>
        newsize = <optimized out>
        newmem = <optimized out>
        next = 0x421e30
        remainder = <optimized out>
        remainder_size = <optimized out>
        __PRETTY_FUNCTION__ = "_int_realloc"
        nextsize = <optimized out>
#5  0x0000fffff7c506e4 in __GI___libc_realloc (oldmem=0x421c30, bytes=281470681743872) at malloc.c:3352
        ar_ptr = 0xfffff7d5daf8 <main_arena>
        nb = 281470681743888
        newp = <optimized out>
        oldp = 0x421c20
        oldsize = 528
        __PRETTY_FUNCTION__ = "__libc_realloc"
#6  0x0000fffff7e592e4 in _gfortrani_xrealloc (ptr=<optimized out>, size=size@entry=281470681743872) at ../../../libgfortran/runtime/memory.c:92
        newp = <optimized out>
#7  0x0000fffff7f57c5c in _gfortrani_fbuf_alloc (u=0x421870, len=281470681743366) at ../../../libgfortran/io/fbuf.c:123
        newlen = 281470681743872
        dest = <optimized out>
#8  0x0000fffff7f4a304 in _gfortrani_write_block (dtp=dtp@entry=0xffffffffea78, length=<optimized out>) at ../../../libgfortran/io/transfer.c:855
        dest = <optimized out>
#9  0x0000fffff7f525d8 in write_character (dtp=dtp@entry=0xffffffffea78, source=source@entry=0xffffffffecf0 "World!", kind=kind@entry=1, 
    length=length@entry=281470681743366, mode=mode@entry=1) at ../../../libgfortran/io/write.c:1416
        extra = <optimized out>
        p = <optimized out>
        d = <optimized out>
#10 0x0000fffff7f56b6c in list_formatted_write_scalar (dtp=dtp@entry=0xffffffffea78, type=type@entry=BT_CHARACTER, p=0xffffffffecf0, kind=kind@entry=1, 
    size=size@entry=281470681743366) at ../../../libgfortran/io/write.c:1900
No locals.
#11 0x0000fffff7f579e4 in _gfortrani_list_formatted_write (dtp=0xffffffffea78, type=BT_CHARACTER, p=<optimized out>, kind=1, size=281470681743366, nelems=1)
    at ../../../libgfortran/io/write.c:1972
        elem = 0
        tmp = <optimized out>
        stride = 281470681743366
#12 0x000000000040098c in simple (one=1, two=2, ts1=..., 
    ts2=<error reading variable: value requires 281470681743366 bytes, which is more than max-value-size>, three=3, four=4, five=5, _ts1=7, 
    _ts2=281470681743366) at simple.f:5
No locals.
#13 0x0000000000400c44 in main () at simple.c:27
        teststring1 = "Hello, \000P\355\377\377\377\377\000\000`\227\276\367\377\377\000", <incomplete sequence \310>
        teststring2 = "World!\000\000@\344\376\367\377\377", '\000' <repeats 18 times>, "\060\000\000\000\000\000\000\000\377\377\377\377\000\000\000\000\000"
        one = 1
        two = 2
        three = 3
        four = 4
        five = 5
        six = 6
        clen1 = <optimized out>
        clen2 = <optimized out>
        flen1 = 7
        flen2 = 6
        B3 = {clen = 1, flen = 65535, teststring = 0x0}
        B4 = {clen = 0, flen = 0, teststring = 0x2f8 <error: Cannot access memory at address 0x2f8>}
...

Comment 1 Paulo Andrade 2023-08-09 17:14:38 UTC
Created attachment 1982610 [details]
simple.f

Comment 2 Florian Weimer 2023-08-09 18:35:31 UTC
This really looks like a user error to me. With GCC 13 I get:

$ gfortran -Wall -O2 -flto simple.?
[…]
simple.c:26:15: warning: type of ‘simple_’ does not match original declaration [-Wlto-type-mismatch]
   26 |   extern void simple_(int* one, int* two, char* A, char *B, int* three, int* four, int* five, unsigned _A_len, unsigned _B_len);
      |               ^
simple.f:1:23: note: type mismatch in parameter 8
    1 |       SUBROUTINE SIMPLE(ONE,TWO,TS1,TS2,THREE,FOUR,FIVE)
      |                       ^
simple.f:1:23: note: type ‘long int’ should match type ‘unsigned int’
simple.f:1:23: note: ‘simple’ was previously declared here
simple.f:1:23: note: code may be misoptimized unless ‘-fno-strict-aliasing’ is used

Fixing simple.c as indicated to:

  extern void simple_(int* one, int* two, char* A, char *B, int* three, int* four, int* five, long _A_len, long _B_len);

This results in a working binary:

 FORTRAN Teststrings:Hello, World!
 FORTRAN Teststrings length:           7           6
           1           2           3           4           5

Comment 3 Paulo Andrade 2023-08-09 19:05:48 UTC
The problem is that the system compiler "works" with several minor changes,
like just commenting the line:

  fstring B3, B4;

in simple.c, or changing the types of fstring from unsigned int to unsigned
long, the warning from gcc 13 now, and several other tests, so, it might
be a genuine bug, as several minor changes the sources causes it work.

Comment 4 Jakub Jelinek 2023-08-09 19:17:58 UTC
As documented in https://gcc.gnu.org/gcc-8/changes.html#fortran , the Fortran ABI has changed in GCC 8.
In particular for this,
"Character variables longer than HUGE(0) elements are now possible on 64-bit targets. Note that this changes the procedure call ABI for all procedures with character arguments on 64-bit targets, as the type of the hidden character length argument has changed. The hidden character length argument is now of type INTEGER(C_SIZE_T)."
So, using unsigned for character lengths is incorrect on 64-bit architectures like aarch64.  On some architectures you can be lucky and have the upper 32 bits of the 64-bit argument zero and it will appear to "work", but that is clearly not the case here.

Comment 5 Florian Weimer 2023-08-09 19:23:18 UTC
For AArch64, the PCS says:

“
C.16 	If the size of the argument is less than 8 bytes then the size of the argument is set to 8 bytes. The effect is as if the argument was copied to the least significant bits of a 64-bit register and the remaining bits filled with unspecified values.
”

<https://github.com/ARM-software/abi-aa/blob/main/aapcs64/aapcs64.rst#682parameter-passing-rules>

So it's indeed not expected to work, and you just get random uninitialized memory (which is why tiny changes make a difference).

Comment 6 Jakub Jelinek 2023-08-09 19:28:10 UTC
In particular, it was the https://gcc.gnu.org/PR78534 https://gcc.gnu.org/r8-5772 change.

Comment 7 Paulo Andrade 2023-08-09 19:35:42 UTC
(In reply to Jakub Jelinek from comment #4)
> As documented in https://gcc.gnu.org/gcc-8/changes.html#fortran , the
> Fortran ABI has changed in GCC 8.
> In particular for this,
> "Character variables longer than HUGE(0) elements are now possible on 64-bit
> targets. Note that this changes the procedure call ABI for all procedures
> with character arguments on 64-bit targets, as the type of the hidden
> character length argument has changed. The hidden character length argument
> is now of type INTEGER(C_SIZE_T)."
> So, using unsigned for character lengths is incorrect on 64-bit
> architectures like aarch64.  On some architectures you can be lucky and have
> the upper 32 bits of the 64-bit argument zero and it will appear to "work",
> but that is clearly not the case here.

Thanks. Heuristically this was a guess:
(gdb) p (int)281470681747456
$1 = 4096
and the linked document makes it clear.