https://gcc.gnu.org/bugzilla/show_bug.cgi?id=112730

            Bug ID: 112730
           Summary: Wrong code generated with Address Sanitizer for a call
                    to a callback in contained subroutine, mapping not
                    executable
           Product: gcc
           Version: 13.2.1
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: sanitizer
          Assignee: unassigned at gcc dot gnu.org
          Reporter: trnka at scm dot com
                CC: dodji at gcc dot gnu.org, dvyukov at gcc dot gnu.org,
                    jakub at gcc dot gnu.org, kcc at gcc dot gnu.org, marxin at 
gcc dot gnu.org
  Target Milestone: ---

Created attachment 56696
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=56696&action=edit
Testcase reproducing the issue

The attached testcase works fine when compiled without sanitizers, prints a
single dot and OK. When compiled with -fsanitize=address, it segfaults
attempting the call to traverse_callback() inside traverse(). The problem seems
to occur on GCC 9 through 14, at least.

#0  0x0000155552500030 in ?? ()
#1  0x00000000004016b2 in json_traverse::traverse (p=0x602000000070) at
test-json_traverse-minimal.f90:65
#2  0x00000000004017e1 in json_value_module::json_traverse (
    json=<error reading variable: Cannot access memory at address 0x0>,
p=0x602000000070, traverse_callback=0x0)
    at test-json_traverse-minimal.f90:55
#3  0x0000000000401609 in json_value_module::json_check_all_for_duplicate_keys
(json=..., p=0x602000000070)
    at test-json_traverse-minimal.f90:80
#4  0x00000000004019a2 in test_json_traverse () at
test-json_traverse-minimal.f90:111

The location in RIP seems to contain some sort of a trampoline:

(gdb) disass $rip,+40
Dump of assembler code from 0x155552500030 to 0x155552500058:
=> 0x0000155552500030:  mov    $0x401244,%r11d
   0x0000155552500036:  movabs $0x155552500030,%r10
   0x0000155552500040:  rex.WB jmp *%r11
   0x0000155552500043:  nop
…

Here, $0x401244 is indeed the address of the callback which should get
executed:

(gdb) disass 0x00401244
Dump of assembler code for function
json_check_all_for_duplicate_keys::duplicate_key_func:
   0x0000000000401244 <+0>:     push   %rbp
   0x0000000000401245 <+1>:     mov    %rsp,%rbp
   0x0000000000401248 <+4>:     push   %r14
…

The segfault is probably because the mapping containing the trampoline is not
executable:

(gdb) info proc mappings
process 41564
Mapped address spaces:

          Start Addr           End Addr       Size     Offset  Perms  objfile
…
      0x1555523f7000     0x155552f00000   0xb09000        0x0  rw-p   
…

Reply via email to