- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello all,
When compiling with -fsanitize=address using ifx (oneAPI 2025.3.0), standard Fortran 2003 pointer bounds-remapping (ptr(bounds) => target) from a 1D target array to a multi-dimensional pointer triggers a fatal stack-buffer-overflow false positive. The overflow is reported inside the remapped pointer's target array even though the runtime dimensions used for the remap never exceed the actual allocated size. Replacing the bounds-remap with an equivalent c_f_pointer call (same address, same shape) makes the report disappear with no other code change.
Environment:
Compiler: ifx from Intel oneAPI 2025.3.0
OS: Linux
Flags: -O0 -g -traceback -fsanitize=address
Minimal Reproducible Example
program ifx_asan_bug
use iso_c_binding, only: c_loc, c_f_pointer
implicit none
real*8, allocatable, target :: mem(:)
real*8, pointer, contiguous :: ptr(:,:,:)
! Allocate 1D memory
allocate(mem(1000))
mem = 0.0d0
print *, "Testing c_f_pointer workaround..."
! This maps the 1D array to the 3D pointer safely, bypassing the compiler's
! internal descriptor bounds-check.
call c_f_pointer(c_loc(mem(1)), ptr, [10, 10, 10])
print *, "SUCCESS: c_f_pointer remapping passed."
print *, "------------------------------------------------"
print *, "Testing standard pointer assignment..."
! Remap 1D array to 3D pointer using standard F2003 syntax.
! In ifx with -fsanitize=address, this triggers a stack-buffer-overflow
! on the 1D array descriptor.
ptr(1:10, 1:10, 1:10) => mem(1:)
print *, "SUCCESS: Standard remapping passed."
end program ifx_asan_bugCompile:
ifx -O0 -g -traceback -fsanitize=address ifx_asan_bug.f90 -o ifx_asan_bug.xOutput:
Testing c_f_pointer workaround...
SUCCESS: c_f_pointer remapping passed.
------------------------------------------------
Testing standard pointer assignment...
=================================================================
==36459==ERROR: AddressSanitizer: global-buffer-overflow on address 0x0000005eadb8 at pc 0x000000523d66 bp 0x7ffe1f0d6890 sp 0x7ffe1f0d6888
READ of size 8 at 0x0000005eadb8 thread T0
#0 0x000000523d65 in MAIN /home/jgreen/tests/fsanitize-improvements/pointer_bounds_remapping_example/ifx_asan_bug.f90:23:5
#1 0x00000043316c in main (/home/jgreen/tests/fsanitize-improvements/pointer_bounds_remapping_example/ifx_asan_bug.x+0x43316c) (BuildId: 263c23038304fd146bba55c82c7cc5ba801890e8)
#2 0x13b8b0c2a1c9 in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16
#3 0x13b8b0c2a28a in __libc_start_main csu/../csu/libc-start.c:360:3
#4 0x000000433084 in _start (/home/jgreen/tests/fsanitize-improvements/pointer_bounds_remapping_example/ifx_asan_bug.x+0x433084) (BuildId: 263c23038304fd146bba55c82c7cc5ba801890e8)
0x0000005eadb8 is located 40 bytes before global variable 'var_53' defined in 'ifx_asan_bug.f90' (0x0000005eade0) of size 12
0x0000005eadb8 is located 16 bytes after global variable 'ifx_asan_bug::MEM' defined in '/home/jgreen/tests/fsanitize-improvements/pointer_bounds_remapping_example/ifx_asan_bug.f90:5' (0x0000005ead60) of size 72
SUMMARY: AddressSanitizer: global-buffer-overflow /home/jgreen/tests/fsanitize-improvements/pointer_bounds_remapping_example/ifx_asan_bug.f90:23:5 in MAIN
Shadow bytes around the buggy address:
0x0000005eab00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0000005eab80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0000005eac00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0000005eac80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0000005ead00: 00 00 00 00 00 00 00 f9 f9 f9 f9 f9 00 00 00 00
=>0x0000005ead80: 00 00 00 00 00 f9 f9[f9]f9 f9 f9 f9 00 04 f9 f9
0x0000005eae00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0000005eae80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0000005eaf00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0000005eaf80: 00 00 00 00 00 00 00 00 00 00 f9 f9 f9 f9 f9 f9
0x0000005eb000: f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9
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
==36459==ABORTING
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Nice reproducer. I think the ASan output points to something more specific than an overflow of the allocated array.
The bounds remap itself appears conforming: the target is rank one, and 10*10*10 is exactly equal to size(mem). One detail is that the posted trace reports a global-buffer-overflow, not a stack-buffer-overflow.
More importantly, ASan reports an 8-byte read 16 bytes past the 72-byte global MEM object. That object matches the size of an Intel rank-1 allocatable-array descriptor; it is not the 8000-byte allocated data region.
The failing address is: `0x5eadb8` - `0x5ead60` = `0x58` = 88 bytes
In Intel's documented descriptor layout, a rank-1 descriptor ends at byte 71. Dimension 2 occupies bytes 72 through 95, and offset 88 is specifically its lower-bound field. This strongly suggests that the code generated for the rank remap is reading dimension-2 metadata from the rank-1 source descriptor while constructing the rank-3 ptr descriptor.
I would therefore describe this as a compiler-generated descriptor over-read exposed by ASan, rather than only an ASan false positive. The c_f_pointer version avoids the source-descriptor remapping path, which is consistent with why it does not trigger, although it also trusts the supplied shape, so an explicit product(shape) <= size(mem) check is still useful.
Could you retry this with ifx 2025.3.2 and 2026.1.1? It would also be useful to compare:
- ptr(...) => mem versus mem(:) and mem(1:)
- allocatable mem(:) versus a fixed-size target mem(1000)
- rank-2 and rank-4 remaps
- with and without CONTIGUOUS
- -O0 versus -O1
I would also make the failing remap a standalone reproducer, without calling c_f_pointer first, and use real(c_double) to remove unrelated kind/interoperability questions.
If this still reproduces with the current compiler, it looks worthy of an ifx compiler defect ticket. The generated assembly around the failing assignment may also show a load from MEM+88, which would confirm the descriptor over-read.
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page