chapel-lang / chapel

a Productive Parallel Programming Language
https://chapel-lang.org
Other
1.78k stars 418 forks source link

ASAN failure from catching type alias of an Error class #22720

Open jeremiah-corrado opened 1 year ago

jeremiah-corrado commented 1 year ago

Summary of Problem

The following program fails to compile with address sanitization enabled:

class E1: Error { }
type E2 = E1;

proc throwingProc() throws {
    throw new E2();
}

try {
    throwingProc();
} catch e: E2 {
    writeln(e);
}

The error appears to be originating from the fact that E2 (a type alias for E1) is being used in a catch statement. Using a type alias for an error class does not appear to create problems in other contexts (such as instantiating or passing to a procedure), but only produces this error when catch e: E2 is used.

Full compilation error message... ``` ================================================================= ==14151==ERROR: AddressSanitizer: heap-use-after-free on address 0x612000646e78 at pc 0x000000587aba bp 0x7fff89d24d70 sp 0x7fff89d24d68 READ of size 8 at 0x612000646e78 thread T0 #0 0x587ab9 in CatchStmt::isCatchall() const ($CHPL_HOME/bin/linux64-x86_64/chpl+0x587ab9) #1 0xb5148a in (anonymous namespace)::ErrorCheckingVisitor::exitTryStmt(TryStmt*) ($CHPL_HOME/bin/linux64-x86_64/chpl+0xb5148a) #2 0x6d9926 in TryStmt::accept(AstVisitor*) ($CHPL_HOME/bin/linux64-x86_64/chpl+0x6d9926) #3 0x6ade28 in BlockStmt::accept(AstVisitor*) ($CHPL_HOME/bin/linux64-x86_64/chpl+0x6ade28) #4 0xb6139c in lowerErrorHandling() ($CHPL_HOME/bin/linux64-x86_64/chpl+0xb6139c) #5 0x92dec5 in runPasses(PhaseTracker&) ($CHPL_HOME/bin/linux64-x86_64/chpl+0x92dec5) #6 0x426f75 in main ($CHPL_HOME/bin/linux64-x86_64/chpl+0x426f75) #7 0x7f215c0a529c in __libc_start_main (/lib64/libc.so.6+0x3529c) #8 0x438d49 in _start ($CHPL_HOME/bin/linux64-x86_64/chpl+0x438d49) 0x612000646e78 is located 56 bytes inside of 264-byte region [0x612000646e40,0x612000646f48) freed by thread T0 here: #0 0x7f215d92fbb8 in operator delete(void*, unsigned long) (/usr/lib64/libasan.so.4+0xdebb8) #1 0x51b6d1 in cleanAst() ($CHPL_HOME/bin/linux64-x86_64/chpl+0x51b6d1) previously allocated by thread T0 here: #0 0x7f215d92e830 in operator new(unsigned long) (/usr/lib64/libasan.so.4+0xdd830) #1 0xb2bb8d in (anonymous namespace)::Converter::convertVariable(chpl::uast::Variable const*, bool) ($CHPL_HOME/bin/linux64-x86_64/chpl+0xb2bb8d) #2 0x1cb9657 ($CHPL_HOME/bin/linux64-x86_64/chpl+0x1cb9657) SUMMARY: AddressSanitizer: heap-use-after-free ($CHPL_HOME/bin/linux64-x86_64/chpl+0x587ab9) in CatchStmt::isCatchall() const Shadow bytes around the buggy address: 0x0c24800c0d70: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c24800c0d80: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c24800c0d90: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c24800c0da0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c24800c0db0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa =>0x0c24800c0dc0: fa fa fa fa fa fa fa fa fd fd fd fd fd fd fd[fd] 0x0c24800c0dd0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd 0x0c24800c0de0: fd fd fd fd fd fd fd fd fd fa fa fa fa fa fa fa 0x0c24800c0df0: fa fa fa fa fa fa fa fa 00 00 00 00 00 00 00 00 0x0c24800c0e00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x0c24800c0e10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 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 ==14151==ABORTING ```
printchplenv... ``` CHPL_HOST_PLATFORM: linux64 CHPL_HOST_COMPILER: gnu CHPL_HOST_CC: gcc CHPL_HOST_CXX: g++ CHPL_HOST_ARCH: x86_64 CHPL_TARGET_PLATFORM: linux64 CHPL_TARGET_COMPILER: gnu CHPL_TARGET_CC: gcc CHPL_TARGET_CXX: g++ CHPL_TARGET_LD: g++ CHPL_TARGET_ARCH: x86_64 CHPL_TARGET_CPU: native CHPL_LOCALE_MODEL: flat CHPL_COMM: none * CHPL_TASKS: fifo * CHPL_LAUNCHER: none CHPL_TIMERS: generic CHPL_UNWIND: none CHPL_HOST_MEM: cstdlib * CHPL_MEM: cstdlib * CHPL_ATOMICS: cstdlib CHPL_GMP: none * CHPL_HWLOC: none CHPL_RE2: none * CHPL_LLVM: none * CHPL_LLVM_SUPPORT: system CHPL_LLVM_CONFIG: <...> * CHPL_LLVM_VERSION: 14 CHPL_AUX_FILESYS: none CHPL_LIB_PIC: none CHPL_SANITIZE: address * CHPL_SANITIZE_EXE: address ```

This same code also fails when compiling with --verify with an internal compiler error:.

Discussion

It is not clear whether we should support type aliases of classes being used in a catch statement; however this did come up recently when CodepointSplittingError was renamed and had to be deprecated (see: https://github.com/chapel-lang/chapel/pull/22678). The deprecation strategy was to make CodepointSplittingError a deprecated type-alias for the new error class. Functionally, this works correctly; however, it is not passing address sanitization so we may need to rethink the deprecation strategy, or address what appears to be a bug summarized in the above code.

vasslitvinov commented 1 year ago

I see the --verify error is the first one fix. Maybe fixing it will also resolve the asan failure.