summaryrefslogtreecommitdiff
path: root/AK/UBSanitizer.h
blob: 326972e0e0c978b30ff23ff1fba3de4858447126 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
/*
 * Copyright (c) 2021, Andreas Kling <kling@serenityos.org>
 *
 * SPDX-License-Identifier: BSD-2-Clause
 */

#pragma once

#include <AK/Atomic.h>
#include <AK/Noncopyable.h>
#include <AK/StdLibExtras.h>
#include <AK/Types.h>

namespace AK::UBSanitizer {

extern Atomic<bool> g_ubsan_is_deadly;

typedef void* ValueHandle;

class SourceLocation {
    AK_MAKE_NONCOPYABLE(SourceLocation);

public:
    char const* 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:
    char const* m_filename { nullptr };
    u32 m_line { 0 };
    u32 m_column { 0 };
};

enum TypeKind : u16 {
    Integer = 0,
    Float = 1,
    Unknown = 0xffff,
};

class TypeDescriptor {
public:
    char const* name() const { return m_name; }
    TypeKind kind() const { return (TypeKind)m_kind; }
    bool is_integer() const { return kind() == TypeKind::Integer; }
    bool is_signed() const { return m_info & 1; }
    bool is_unsigned() const { return !is_signed(); }
    size_t bit_width() const { return 1 << (m_info >> 1); }

private:
    u16 m_kind;
    u16 m_info;
    char m_name[1];
};

struct InvalidValueData {
    SourceLocation location;
    TypeDescriptor const& type;
};

struct NonnullArgData {
    SourceLocation location;
    SourceLocation attribute_location;
    int argument_index;
};

struct NonnullReturnData {
    SourceLocation attribute_location;
};

struct OverflowData {
    SourceLocation location;
    TypeDescriptor const& type;
};

struct VLABoundData {
    SourceLocation location;
    TypeDescriptor const& type;
};

struct ShiftOutOfBoundsData {
    SourceLocation location;
    TypeDescriptor const& lhs_type;
    TypeDescriptor const& rhs_type;
};

struct OutOfBoundsData {
    SourceLocation location;
    TypeDescriptor const& array_type;
    TypeDescriptor const& index_type;
};

struct TypeMismatchData {
    SourceLocation location;
    TypeDescriptor const& type;
    u8 log_alignment;
    u8 type_check_kind;
};

struct AlignmentAssumptionData {
    SourceLocation location;
    SourceLocation assumption_location;
    TypeDescriptor const& type;
};

struct UnreachableData {
    SourceLocation location;
};

struct ImplicitConversionData {
    SourceLocation location;
    TypeDescriptor const& from_type;
    TypeDescriptor const& to_type;
    /* ImplicitConversionCheckKind */ unsigned char kind;
};

struct InvalidBuiltinData {
    SourceLocation location;
    unsigned char kind;
};

struct PointerOverflowData {
    SourceLocation location;
};

struct FloatCastOverflowData {
    SourceLocation location;
    TypeDescriptor const& from_type;
    TypeDescriptor const& to_type;
};

}