summaryrefslogtreecommitdiff
path: root/AK/UBSanitizer.h
diff options
context:
space:
mode:
authorAndrew Kaster <akaster@serenityos.org>2021-11-22 22:59:16 -0700
committerBrian Gianforcaro <b.gianfo@gmail.com>2021-12-15 10:30:32 -0800
commitdb33cdbc2f79781e4e62d301887f370d2abac8d7 (patch)
tree16b2a8daa24893e7ad71ac27dbec2de9400ccf83 /AK/UBSanitizer.h
parent3e9fb9f23cdfe5522be3055c63771642fed26630 (diff)
downloadserenity-db33cdbc2f79781e4e62d301887f370d2abac8d7.zip
AK+LibSanitizer: Add method to zero out a UBSAN SourceLocation
This is the same strategy that LLVM's compiler-rt uses to make sure that each UBSAN error is only reported once, when UBSAN is *not* deadly. Otherwise, each time we head through a UB codepath, we will log the same error over and over. That behavior just adds noise to the logs and makes it nearly impossible to run binaires that have some common code path with flagged UB in them. compiler-rt goes the extra step to make sure the "clear" action is atomic, but we don't really have that many multi-threaded apps gettting tested with UBSAN yet, so we can add that later.
Diffstat (limited to 'AK/UBSanitizer.h')
-rw-r--r--AK/UBSanitizer.h36
1 files changed, 33 insertions, 3 deletions
diff --git a/AK/UBSanitizer.h b/AK/UBSanitizer.h
index d2a17bd565..7601a4e593 100644
--- a/AK/UBSanitizer.h
+++ b/AK/UBSanitizer.h
@@ -6,6 +6,8 @@
#pragma once
+#include "AK/Noncopyable.h"
+#include "AK/StdLibExtras.h"
#include <AK/Types.h>
namespace AK::UBSanitizer {
@@ -15,15 +17,43 @@ extern bool g_ubsan_is_deadly;
typedef void* ValueHandle;
class SourceLocation {
+ AK_MAKE_NONCOPYABLE(SourceLocation);
+
public:
const char* filename() const { return m_filename; }
u32 line() const { return m_line; }
u32 column() const { return m_column; }
+ // Replace the location information in the .data segment with one that won't be logged in the future
+ // Using this method prevents log spam when sanitizers are not deadly by not logging the exact same
+ // code paths multiple times.
+ SourceLocation permanently_clear() { return move(*this); }
+
+ bool needs_logging() const { return !(m_filename == nullptr); }
+
+ SourceLocation() = default;
+ SourceLocation(SourceLocation&& other)
+ : m_filename(other.m_filename)
+ , m_line(other.m_line)
+ , m_column(other.m_column)
+ {
+ other = {};
+ }
+
+ SourceLocation& operator=(SourceLocation&& other)
+ {
+ if (this != &other) {
+ m_filename = exchange(other.m_filename, nullptr);
+ m_line = exchange(other.m_line, 0);
+ m_column = exchange(other.m_column, 0);
+ }
+ return *this;
+ }
+
private:
- const char* m_filename;
- u32 m_line;
- u32 m_column;
+ const char* m_filename { nullptr };
+ u32 m_line { 0 };
+ u32 m_column { 0 };
};
enum TypeKind : u16 {