다음을 통해 공유


AddressSanitizer 런타임

AddressSanitizer 런타임 라이브러리는 일반적인 메모리 할당 함수 및 작업을 가로채 메모리 액세스를 검사할 수 있도록 합니다. 컴파일러에서 생성할 수 있는 다양한 유형의 실행 파일을 지원하는 여러 런타임 라이브러리가 있습니다. 컴파일러 및 링커는 컴파일 시간에 옵션을 전달하는 한 적절한 런타임 라이브러리를 /fsanitize=address 자동으로 연결합니다. 링크 타임에 옵션을 사용하여 기본 동작을 재정의할 /NODEFAULTLIB 수 있습니다. 자세한 내용은 AddressSanitizer 언어, 빌드 및 디버깅 참조연결에 대한 섹션을 참조하세요.

컴파일러에서 cl /fsanitize=address섀도 바이트를 관리하고 검사 지침을 생성합니다. 프로그램에서는 이 계측을 사용하여 스택, 힙 또는 전역 범위에서 메모리 액세스를 검사. 또한 컴파일러는 스택 및 전역 변수를 설명하는 메타데이터를 생성합니다. 이 메타데이터를 사용하면 런타임에서 소스 코드의 함수 이름, 줄 및 열과 같은 정확한 오류 진단 생성할 수 있습니다. 컴파일러 검사 및 런타임 라이브러리는 런타임에 발생하는 경우 여러 유형의 메모리 안전 버그를 정확하게 진단할 수 있습니다.

Visual Studio 17.7 미리 보기 3을 기준으로 AddressSanitizer 런타임에 연결하기 위한 런타임 라이브러리 목록은 다음과 같습니다. (런타임을 정적으로 연결) 및 /MD (런타임 시 재배포를 동적으로 연결) 옵션에 대한 /MT 자세한 내용은 /MD, /MT, /LD(런타임 라이브러리 사용)를 참조하세요.

참고 항목

다음 표 {arch} 에서 중 하나 i386 또는 x86_64. 이러한 라이브러리는 아키텍처 이름에 Clang 규칙을 사용합니다. MSVC 규칙은 일반적으로 x86x64 그리고 그보다는 i386x86_64동일하지만 동일한 아키텍처를 참조합니다.

CRT 옵션 AddressSanitizer 런타임 라이브러리(.lib) 주소 런타임 이진(.dll)
/MT 또는 /MTd clang_rt.asan_dynamic-{arch}, clang_rt.asan_static_runtime_thunk-{arch} clang_rt.asan_dynamic-{arch}
/MD 또는 /MDd clang_rt.asan_dynamic-{arch}, clang_rt.asan_dynamic_runtime_thunk-{arch} clang_rt.asan_dynamic-{arch}

다음 다이어그램은 언어 런타임 라이브러리가 , /MTd/MD/MDd 컴파일러 옵션에 /MT대해 연결되는 방법을 보여줍니다.

다양한 컴파일러 옵션에 대해 런타임 라이브러리를 연결하는 방법의 다이어그램

이 이미지는 런타임 라이브러리를 연결하는 세 가지 시나리오를 보여 줍니다. 첫 번째는 /MT 또는 /MTd입니다. My_exe.exe 및 my_dll.dll 모두 정적으로 연결된 VCRuntime, 유니버설 CRT 및 C++ 런타임의 자체 복사본과 함께 표시됩니다. 시나리오에서는 my_exe.exe 및 my_dll.dll 모두 vcruntime140.dll, ucrtbase.dll 및 msvcp140.dll 공유하는 /MD를 보여 줍니다. 마지막 시나리오에서는 my_exe.exe 및 my_dll.dll 모두 런타임의 디버그 버전(vcruntime140d.dll, ucrtbased.dll 및 msvcp140d.dll 공유)을 보여 줍니다.

다음 다이어그램에서는 다양한 컴파일러 옵션에 대해 ASan 라이브러리를 연결하는 방법을 보여 줍니다.

ASan 런타임 dll이 연결된 방법의 다이어그램.

이 이미지는 ASan 런타임 라이브러리를 연결하는 네 가지 시나리오를 보여 줍니다. 시나리오는 /MT(런타임에 정적으로 연결), /MTd(디버그 런타임에 정적으로 연결), /MD(런타임 시 재배포자를 동적으로 연결), /MDd(런타임 시 디버그 재배포자를 동적으로 연결)에 대한 시나리오입니다. 모든 경우에 my_exe.exe 링크와 해당 동료는 단일 clang-rt.asan-dynamix-x86_64.dll 인스턴스에 대한 링크를 my_dll.dll.

정적으로 연결하는 경우에도 ASan 런타임 DLL은 다른 C 런타임 구성 요소와 달리 런타임에 있어야 합니다.

이전 버전

Visual Studio 17.7 미리 보기 3 이전에는 정적으로 연결된(/MT 또는 /MTd) 빌드에서 DLL 종속성을 사용하지 않았습니다. 대신 AddressSanitizer 런타임이 사용자의 EXE에 정적으로 연결되었습니다. 그런 다음 DLL 프로젝트는 사용자의 EXE에서 내보내기를 로드하여 ASan 기능에 액세스합니다.

동적으로 연결된 프로젝트(/MD 또는 /MDd)는 프로젝트가 디버그 또는 릴리스에 대해 구성되었는지 여부에 따라 다른 라이브러리 및 DLL을 사용했습니다. 이러한 변경 내용 및 해당 동기에 대한 자세한 내용은 MSVC Address Sanitizer – 모든 런타임 구성에 대한 하나의 DLL을 참조 하세요.

다음 표에서는 Visual Studio 17.7 미리 보기 3 이전의 AddressSanitizer 런타임 라이브러리 연결의 이전 동작에 대해 설명합니다.

CRT 옵션 DLL 또는 EXE 디버그? ASan 라이브러리(.lib) ASan 런타임 이진(.dll)
/MT EXE 아니요 clang_rt.asan-{arch}, clang_rt.asan_cxx-{arch} None
/MT DLL 아니요 clang_rt.asan_dll_thunk-{arch} None
/MD 여기서는 아니요 clang_rt.asan_dynamic-{arch}, clang_rt.asan_dynamic_runtime_thunk-{arch} clang_rt.asan_dynamic-{arch}
/MT EXE clang_rt.asan_dbg-{arch}, clang_rt.asan_dbg_cxx-{arch} None
/MT DLL clang_rt.asan_dbg_dll_thunk-{arch} None
/MD 여기서는 clang_rt.asan_dbg_dynamic-{arch}, clang_rt.asan_dbg_dynamic_runtime_thunk-{arch} clang_rt.asan_dbg_dynamic-{arch}

다음 다이어그램에서는 Visual Studio 2022 17.7 미리 보기 3 이전의 다양한 컴파일러 옵션에 대해 ASan 라이브러리가 연결된 방법을 보여 줍니다.

Visual Studio 2022 미리 보기 3 이전에 ASan 런타임 dll이 연결된 방법의 다이어그램

이 이미지는 ASan 런타임 라이브러리를 연결하는 네 가지 시나리오를 보여 줍니다. 시나리오는 /MT(런타임에 정적으로 연결), /MTd(디버그 런타임에 정적으로 연결), /MD(런타임 시 재배포자를 동적으로 연결), /MDd(런타임 시 디버그 재배포자를 동적으로 연결)에 대한 시나리오입니다. /MT의 경우 my_exe.exe ASan 런타임의 정적으로 연결된 복사본이 있습니다. my_exe.exe ASan 런타임에 대한 링크를 my_dll.dll. /MTd의 경우 다이어그램은 정적으로 연결된 디버그 ASan 런타임을 사용한다는 점을 제외하고 동일합니다. /MD의 경우 my_exe.exe 및 my_dll.dll clang_rt.asan_dynamic-x86_64.dll 동적으로 연결된 ASan 런타임에 대한 링크입니다. /MDd의 경우 다이어그램은 clang_rt.asan_dbg_dynamic-x86_64.dll 명명된 디버그 ASan 런타임에 대한 my_exe.exe 및 my_dll.dll 링크를 제외하고 동일합니다.

함수 가로채기

AddressSanitizer는 많은 핫패치 기술을 통해 함수 가로채기를 달성합니다. 이러한 기술은 소스 코드 자체 내에서 가장 잘 문서화되어 있습니다.

런타임 라이브러리는 많은 일반적인 메모리 관리 및 메모리 조작 함수를 가로채고 있습니다. 목록은 가로채는 함수의 AddressSanitizer 목록을 참조 하세요. 할당 인터셉터는 각 할당 호출과 관련된 메타데이터 및 섀도 바이트를 관리합니다. CRT 함수를 호출 malloc 하거나 delete 호출할 때마다 인터셉터는 AddressSanitizer 섀도 메모리 영역에서 특정 값을 설정하여 해당 힙 위치에 현재 액세스할 수 있는지 여부와 할당 범위가 무엇인지 나타냅니다. 이러한 섀도 바이트를 사용하면 섀도 바이트의 컴파일러 생성 검사 로드 또는 저장소가 유효한지 여부를 확인할 수 있습니다.

가로채기가 성공하도록 보장되지는 않습니다. 함수 프롤로그가 너무 짧 jmp 아서 쓸 수 없는 경우 가로채기가 실패할 수 있습니다. 가로채기 실패가 발생하면 프로그램은 a debugbreak 를 throw하고 중지합니다. 디버거를 연결하면 가로채기 문제의 원인이 명확해집니다. 이 문제가 있는 경우 버그를 보고합니다.

참고 항목

사용자는 필요에 따라 환경 변수 ASAN_WIN_CONTINUE_ON_INTERCEPTION_FAILURE 를 모든 값으로 설정하여 실패한 가로채기를 계속 시도할 수 있습니다. 가로채기 실패를 계속하면 해당 함수에 대한 버그 보고서가 누락될 수 있습니다.

사용자 지정 할당자 및 AddressSanitizer 런타임

AddressSanitizer 런타임은 일반적인 할당자 인터페이스 , mallocdelete//HeapFreeHeapAlloc/newfree(통해RtlAllocateHeap/RtlFreeHeap)에 대한 인터셉터를 제공합니다. 많은 프로그램에서 한 가지 이유 또는 다른 이유로 사용자 지정 할당자를 사용합니다. 예를 들어 사용 중인 프로그램이나 인터페이스를 사용하는 dlmallocstd::allocator 솔루션이 있습니다 VirtualAlloc(). 컴파일러는 사용자 지정 할당자에 섀도 메모리 관리 호출을 자동으로 추가할 수 없습니다. 제공된 수동 중독 인터페이스를 사용하는 것은 사용자의 책임입니다. 이 API를 사용하면 이러한 할당자가 기존 AddressSanitizer 런타임 및 섀도 바이 트 규칙을 사용하여 제대로 작동할 수 있습니다.

수동 AddressSanitizer 중독 인터페이스

계몽을 위한 인터페이스는 간단하지만 사용자에게 맞춤 제한을 적용합니다. 사용자는 이러한 프로토타입을 가져와서 가져올 수 있습니다 sanitizer/asan_interface.h. 인터페이스 함수 프로토타입은 다음과 같습니다.

void __asan_poison_memory_region(void const volatile *addr, size_t size);
void __asan_unpoison_memory_region(void const volatile *addr, size_t size);

편의 를 위해 AddressSanitizer 인터페이스 헤더 파일 은 래퍼 매크로를 제공합니다. 이러한 매크로는 컴파일 중에 AddressSanitizer 기능을 사용할 수 있는지 여부를 검사. 필요하지 않은 경우 소스 코드에서 중독 함수 호출을 생략할 수 있습니다. 이러한 매크로는 위의 함수를 직접 호출하는 것보다 선호되어야 합니다.

#define ASAN_POISON_MEMORY_REGION(addr, size)
#define ASAN_UNPOISON_MEMORY_REGION(addr, size)

AddressSanitizer 중독에 대한 맞춤 요구 사항

섀도 바이트의 수동 중독은 맞춤 요구 사항을 고려해야 합니다. 필요한 경우 섀도 바이트가 섀도 메모리의 바이트 경계에서 끝나도록 사용자가 패딩을 추가해야 합니다. AddressSanitizer 섀도 메모리의 각 비트는 애플리케이션 메모리의 단일 바이트 상태를 인코딩합니다. 이 인코딩은 패딩을 포함하여 각 할당의 총 크기가 8바이트 경계에 맞춰야 한다는 것을 의미합니다. 맞춤 요구 사항이 충족되지 않으면 잘못된 버그 보고가 발생할 수 있습니다. 잘못된 보고는 누락된 보고서(거짓 부정) 또는 오류가 아닌 보고서(가양성)로 나타날 수 있습니다.

맞춤 요구 사항 및 잠재적인 문제에 대한 그림은 제공된 ASan 맞춤 예제를 참조하세요. 하나는 수동 섀도 메모리 중독으로 잘못 될 수있는 것을 보여주는 작은 프로그램입니다. 두 번째는 인터페이스를 사용하여 수동 중독을 구현하는 예제입니다 std::allocator .

런타임 옵션

MSVC(Microsoft C/C++)는 llvm-project 리포지토리의 Clang AddressSanitizer 런타임을 기반으로 런타임을 사용합니다. 이 때문에 대부분의 런타임 옵션은 두 버전 간에 공유됩니다. 공용 Clang 런타임 옵션의 전체 목록은 여기에서 확인할 수 있습니다. 다음 섹션에서는 몇 가지 차이점을 설명합니다. 예상대로 작동하지 않는 옵션을 검색하는 경우 버그를 보고합니다.

지원되지 않는 AddressSanitizer 옵션

  • detect_container_overflow
  • unmap_shadow_on_exit

참고 항목

AddressSanitizer 런타임 옵션은 halt_on_error 예상대로 작동하지 않습니다. Clang 및 MSVC 런타임 라이브러리 모두에서 대부분의 메모리 손상 오류를 포함하여 많은 오류 유형이 계속 불가능으로 간주됩니다.

자세한 내용은 Clang 12.0과의 차이점 섹션을 참조하세요.

MSVC 관련 AddressSanitizer 런타임 옵션

  • windows_hook_legacy_allocators부울, 인터셉션 GlobalAllocLocalAlloc 할당자를 사용하지 않도록 설정합니다false.

    참고 항목

    이 문서를 작성할 때 공용 llvm-project 런타임에서는 이 옵션을 windows_hook_legacy_allocators 사용할 수 없습니다. 이 옵션은 결국 퍼블릭 프로젝트에 다시 기여할 수 있습니다. 그러나 코드 검토 및 커뮤니티 동의에 따라 달라집니다.

    AddressSanitizer가 실험적이었던 동안 이전에 옵트인 기능이었던 옵션은 windows_hook_rtl_allocators이제 기본적으로 사용하도록 설정됩니다. Visual Studio 2022 버전 17.4.6 이전 버전에서는 기본 옵션 값이 false있습니다. Visual Studio 2022 버전 17.4.6 이상 버전에서는 이 옵션이 windows_hook_rtl_allocators 기본값으로 지정 true됩니다.

  • iat_overwrite 문자열로, 기본적으로 설정됩니다 "error" . 다른 가능한 값은 다음과 같습니다 "protect""ignore". 일부 모듈은 특정 함수의 구현을 import address table 사용자 지정하기 위해 다른 모듈을 덮어쓸 수 있습니다. 예를 들어 드라이버는 일반적으로 특정 하드웨어에 대한 사용자 지정 구현을 제공합니다. 이 iat_overwrite 옵션은 특정 memoryapi.h 함수에 대한 덮어쓰기에서 AddressSanitizer 런타임의 보호를 관리합니다. 런타임은 현재 보호를 위한 함수 VirtualProtectVirtualQuery 해당 함수를 추적VirtualAlloc합니다. 이 옵션은 Visual Studio 2022 버전 17.5 미리 보기 1 이상 버전에서 사용할 수 있습니다. 다음 iat_overwrite 값은 보호된 함수를 덮어쓸 때 런타임이 어떻게 반응하는지 제어합니다.

    • 기본값으로 "error" 설정하면 런타임은 덮어쓰기가 검색될 때마다 오류를 보고합니다.
    • 설정 "protect"하면 런타임에서 덮어쓴 정의를 사용하지 않도록 시도하고 계속 진행합니다. 사실상 함수의 원래 memoryapi 정의는 무한 재귀를 방지하기 위해 런타임 내부에서 사용됩니다. 프로세스의 다른 모듈은 여전히 덮어쓴 정의를 사용합니다.
    • 설정 "ignore"하면 런타임에서 덮어쓴 함수를 수정하지 않고 실행을 진행합니다.
  • windows_fast_fail_on_error 부울(기본적으로 false)은 오류 보고서를 인쇄한 후 프로세스가 __fastfail(71)로 종료되도록 설정 true 됩니다.

참고 항목

abort_on_error 값이 true로 설정되면 Windows에서 프로그램이 exit(3)로 종료됩니다. 현재 동작을 변경하지 않기 위해 이 새 옵션을 대신 도입하기로 결정했습니다. abort_on_error windows_fast_fail_on_error 모두 true이면 프로그램이 __fastfail 종료됩니다.

가로채는 함수의 AddressSanitizer 목록(Windows)

AddressSanitizer 런타임은 많은 함수를 핫패치하여 런타임 시 메모리 안전 검사 사용하도록 설정합니다. 다음은 AddressSanitizer 런타임이 모니터링하는 함수의 전체 목록이 아닙니다.

기본 인터셉터

선택적 인터셉터

여기에 나열된 인터셉터는 AddressSanitizer 런타임 옵션을 사용하는 경우에만 설치됩니다. false 레거시 할당자 가로채기를 사용하지 않도록 설정합니다windows_hook_legacy_allocators. set ASAN_OPTIONS=windows_hook_legacy_allocators=false

참고 항목

AddressSanitizer 개요
AddressSanitizer 알려진 문제
AddressSanitizer 빌드 및 언어 참조
AddressSanitizer 섀도 바이트
AddressSanitizer 클라우드 또는 분산 테스트
AddressSanitizer 디버거 통합
AddressSanitizer 오류 예제