| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,76 @@ | ||
| //===-- ubsan_monitor.cc ----------------------------------------*- C++ -*-===// | ||
| // | ||
| // The LLVM Compiler Infrastructure | ||
| // | ||
| // This file is distributed under the University of Illinois Open Source | ||
| // License. See LICENSE.TXT for details. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // Hooks which allow a monitor process to inspect UBSan's diagnostics. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #include "ubsan_monitor.h" | ||
|
|
||
| using namespace __ubsan; | ||
|
|
||
| UndefinedBehaviorReport::UndefinedBehaviorReport(const char *IssueKind, | ||
| Location &Loc, | ||
| InternalScopedString &Msg) | ||
| : IssueKind(IssueKind), Loc(Loc), Buffer(Msg.length() + 1) { | ||
| // We have the common sanitizer reporting lock, so it's safe to register a | ||
| // new UB report. | ||
| RegisterUndefinedBehaviorReport(this); | ||
|
|
||
| // Make a copy of the diagnostic. | ||
| Buffer.append("%s", Msg.data()); | ||
|
|
||
| // Let the monitor know that a report is available. | ||
| __ubsan_on_report(); | ||
| } | ||
|
|
||
| static UndefinedBehaviorReport *CurrentUBR; | ||
|
|
||
| void __ubsan::RegisterUndefinedBehaviorReport(UndefinedBehaviorReport *UBR) { | ||
| CurrentUBR = UBR; | ||
| } | ||
|
|
||
| SANITIZER_WEAK_DEFAULT_IMPL | ||
| void __ubsan::__ubsan_on_report(void) {} | ||
|
|
||
| void __ubsan::__ubsan_get_current_report_data(const char **OutIssueKind, | ||
| const char **OutMessage, | ||
| const char **OutFilename, | ||
| unsigned *OutLine, | ||
| unsigned *OutCol, | ||
| char **OutMemoryAddr) { | ||
| if (!OutIssueKind || !OutMessage || !OutFilename || !OutLine || !OutCol || | ||
| !OutMemoryAddr) | ||
| UNREACHABLE("Invalid arguments passed to __ubsan_get_current_report_data"); | ||
|
|
||
| InternalScopedString &Buf = CurrentUBR->Buffer; | ||
|
|
||
| // Ensure that the first character of the diagnostic text can't start with a | ||
| // lowercase letter. | ||
| char FirstChar = Buf.data()[0]; | ||
| if (FirstChar >= 'a' && FirstChar <= 'z') | ||
| Buf.data()[0] = FirstChar - 'a' + 'A'; | ||
|
|
||
| *OutIssueKind = CurrentUBR->IssueKind; | ||
| *OutMessage = Buf.data(); | ||
| if (!CurrentUBR->Loc.isSourceLocation()) { | ||
| *OutFilename = "<unknown>"; | ||
| *OutLine = *OutCol = 0; | ||
| } else { | ||
| SourceLocation SL = CurrentUBR->Loc.getSourceLocation(); | ||
| *OutFilename = SL.getFilename(); | ||
| *OutLine = SL.getLine(); | ||
| *OutCol = SL.getColumn(); | ||
| } | ||
|
|
||
| if (CurrentUBR->Loc.isMemoryLocation()) | ||
| *OutMemoryAddr = (char *)CurrentUBR->Loc.getMemoryLocation(); | ||
| else | ||
| *OutMemoryAddr = nullptr; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,49 @@ | ||
| //===-- ubsan_monitor.h -----------------------------------------*- C++ -*-===// | ||
| // | ||
| // The LLVM Compiler Infrastructure | ||
| // | ||
| // This file is distributed under the University of Illinois Open Source | ||
| // License. See LICENSE.TXT for details. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // Hooks which allow a monitor process to inspect UBSan's diagnostics. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #ifndef UBSAN_MONITOR_H | ||
| #define UBSAN_MONITOR_H | ||
|
|
||
| #include "ubsan_diag.h" | ||
| #include "ubsan_value.h" | ||
|
|
||
| namespace __ubsan { | ||
|
|
||
| struct UndefinedBehaviorReport { | ||
| const char *IssueKind; | ||
| Location &Loc; | ||
| InternalScopedString Buffer; | ||
|
|
||
| UndefinedBehaviorReport(const char *IssueKind, Location &Loc, | ||
| InternalScopedString &Msg); | ||
| }; | ||
|
|
||
| SANITIZER_INTERFACE_ATTRIBUTE void | ||
| RegisterUndefinedBehaviorReport(UndefinedBehaviorReport *UBR); | ||
|
|
||
| /// Called after a report is prepared. This serves to alert monitor processes | ||
| /// that a UB report is available. | ||
| extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __ubsan_on_report(void); | ||
|
|
||
| /// Used by the monitor process to extract information from a UB report. The | ||
| /// data is only available until the next time __ubsan_on_report is called. The | ||
| /// caller is responsible for copying and preserving the data if needed. | ||
| extern "C" SANITIZER_INTERFACE_ATTRIBUTE void | ||
| __ubsan_get_current_report_data(const char **OutIssueKind, | ||
| const char **OutMessage, | ||
| const char **OutFilename, unsigned *OutLine, | ||
| unsigned *OutCol, char **OutMemoryAddr); | ||
|
|
||
| } // end namespace __ubsan | ||
|
|
||
| #endif // UBSAN_MONITOR_H |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| // RUN: %clangxx -w -fsanitize=bool %s -o %t | ||
| // RUN: %run %t 2>&1 | FileCheck %s | ||
|
|
||
| #include <iostream> | ||
|
|
||
| extern "C" { | ||
| void __ubsan_get_current_report_data(const char **OutIssueKind, | ||
| const char **OutMessage, | ||
| const char **OutFilename, | ||
| unsigned *OutLine, unsigned *OutCol, | ||
| char **OutMemoryAddr); | ||
|
|
||
| // Override the weak definition of __ubsan_on_report from the runtime, just | ||
| // for testing purposes. | ||
| void __ubsan_on_report(void) { | ||
| const char *IssueKind, *Message, *Filename; | ||
| unsigned Line, Col; | ||
| char *Addr; | ||
| __ubsan_get_current_report_data(&IssueKind, &Message, &Filename, &Line, &Col, | ||
| &Addr); | ||
|
|
||
| std::cout << "Issue: " << IssueKind << "\n" | ||
| << "Location: " << Filename << ":" << Line << ":" << Col << "\n" | ||
| << "Message: " << Message << std::endl; | ||
|
|
||
| (void)Addr; | ||
| } | ||
| } | ||
|
|
||
| int main() { | ||
| char C = 3; | ||
| bool B = *(bool *)&C; | ||
| // CHECK: Issue: invalid-bool-load | ||
| // CHECK-NEXT: Location: {{.*}}monitor.cpp:[[@LINE-2]]:12 | ||
| // CHECK-NEXT: Message: Load of value 3, which is not a valid value for type 'bool' | ||
| return 0; | ||
| } |