Here's a minimal example of how I'm rasing the stack-use-after-return error:
int *ptr; // global definition
// stack allocate and initialize`ptr` 
void alloc() {
  int local[10];
  ptr = &local[0];
}
// make a `return`
int ret_after_use() {
    return ptr[10];
}
int main() {
  alloc();
  int i = ret_after_use();
  ptr = &i; // error: use after return
  return 0;
}
As expected, Asan catches this problem and raises the following message (raw) -
=================================================================
==1011387==ERROR: AddressSanitizer: stack-use-after-return on address 0x7f3ada500048 at pc 0x564ebacaa22c bp 0x7ffe3f0635d0 sp 0x7ffe3f0635c8
READ of size 4 at 0x7f3ada500048 thread T0
    #0 0x564ebacaa22b in ret_after_use /home/aissy/c_cpp/understanding/UBs/stack_use_after_return.c:17:9
    #1 0x564ebacaa4c9 in main /home/aissy/c_cpp/understanding/UBs/stack_use_after_return.c:31:11
    #2 0x7f3adc23c78f in __libc_start_call_main /usr/src/debug/glibc-git/glibc/csu/../sysdeps/nptl/libc_start_call_main.h:58:16
    #3 0x7f3adc23c849 in __libc_start_main@GLIBC_2.2.5 /usr/src/debug/glibc-git/glibc/csu/../csu/libc-start.c:360:3
    #4 0x564ebabad084 in _start /home/aissy/aur/glibc-git/src/glibc/csu/../sysdeps/x86_64/start.S:115
Address 0x7f3ada500048 is located in stack of thread T0 at offset 72 in frame
    #0 0x564ebacaa04f in alloc /home/aissy/c_cpp/understanding/UBs/stack_use_after_return.c:7
  This frame has 1 object(s):
    [32, 72) 'local' (line 8) <== Memory access at offset 72 overflows this variable
HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork
      (longjmp and C++ exceptions *are* supported)
SUMMARY: AddressSanitizer: stack-use-after-return /home/aissy/c_cpp/understanding/UBs/stack_use_after_return.c:17:9 in ret_after_use
Shadow bytes around the buggy address:
  0x0fe7db497fb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0fe7db497fc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0fe7db497fd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0fe7db497fe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0fe7db497ff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0fe7db498000: f5 f5 f5 f5 f5 f5 f5 f5 f5[f5]f5 f5 f5 f5 f5 f5
  0x0fe7db498010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0fe7db498020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0fe7db498030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0fe7db498040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0fe7db498050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
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
==1011387==ABORTING
The part I'm interested about is the Shadow bytes around the buggy address: part, particularly what I'm confused about is the addresses that are being shown here to indicate redzones, use-after-free etc. I don't understand where these addresses are coming from, nor how to read from those addresses in either my C program or a debugger like GDB.
I assume the block of memory or stack these addresses are referring to is not the address to the stack (by looking at sp and bp, they are not what it seems like).
Starting with the first of stack-after-return (f5), namely 0x0ffb70398000, I want to know -
a) Where are these addresses coming from?
b) How to read from those addresses (the contents) in a debugger or my C program itself?