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
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
|
/* -*- Mode: C++; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
/*
* Tartan
* Copyright © 2014 Collabora Ltd.
*
* Tartan is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Tartan is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Tartan. If not, see <http://www.gnu.org/licenses/>.
*
* Authors:
* Philip Withnall <philip.withnall@collabora.co.uk>
*/
#ifndef TARTAN_GERROR_CHECKER_H
#define TARTAN_GERROR_CHECKER_H
#include "config.h"
#include <clang/AST/AST.h>
#include <clang/StaticAnalyzer/Core/BugReporter/BugType.h>
#include <clang/StaticAnalyzer/Core/Checker.h>
#include <clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h>
#include <clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h>
#include "checker.h"
#include "gir-manager.h"
namespace tartan {
using namespace clang;
using namespace ento;
class GErrorChecker : public ento::Checker<check::PreCall,
eval::Call,
check::Bind,
check::DeadSymbols>,
public tartan::Checker {
public:
explicit GErrorChecker () {};
struct GErrorChecksFilter {
DefaultBool check_overwrite_set;
DefaultBool check_overwrite_freed;
DefaultBool check_double_free;
DefaultBool check_free_cleared;
DefaultBool check_use_uninitialised;
DefaultBool check_memory_leak;
CheckName check_name_overwrite_set;
CheckName check_name_overwrite_freed;
CheckName check_name_double_free;
CheckName check_name_free_cleared;
CheckName check_name_use_uninitialised;
CheckName check_name_memory_leak;
};
GErrorChecksFilter filter;
private:
/* Cached type identifiers. */
mutable QualType _gerror_type;
/* Cached function identifiers. */
mutable IdentifierInfo *_identifier_g_set_error;
mutable IdentifierInfo *_identifier_g_set_error_literal;
mutable IdentifierInfo *_identifier_g_error_new;
mutable IdentifierInfo *_identifier_g_error_new_literal;
mutable IdentifierInfo *_identifier_g_error_new_valist;
mutable IdentifierInfo *_identifier_g_error_free;
mutable IdentifierInfo *_identifier_g_clear_error;
mutable IdentifierInfo *_identifier_g_propagate_error;
mutable IdentifierInfo *_identifier_g_propagate_prefixed_error;
bool _initialise_identifiers (const ASTContext &context) const;
/* Cached bug reports. */
mutable std::unique_ptr<BuiltinBug> _overwrite_set;
mutable std::unique_ptr<BuiltinBug> _overwrite_freed;
mutable std::unique_ptr<BuiltinBug> _double_free;
mutable std::unique_ptr<BuiltinBug> _free_cleared;
mutable std::unique_ptr<BuiltinBug> _use_uninitialised;
mutable std::unique_ptr<BuiltinBug> _memory_leak;
void _initialise_bug_reports () const;
ProgramStateRef _handle_pre_g_set_error (CheckerContext &context,
const CallEvent &call_event) const;
ProgramStateRef _handle_pre_g_error_new (CheckerContext &context,
const CallEvent &call_event) const;
ProgramStateRef _handle_pre_g_error_free (CheckerContext &context,
const CallEvent &call_event) const;
ProgramStateRef _handle_pre_g_clear_error (CheckerContext &context,
const CallEvent &call_event) const;
ProgramStateRef _handle_pre_g_propagate_error (CheckerContext &context,
const CallEvent &call_event) const;
ProgramStateRef _handle_eval_g_set_error (CheckerContext &context,
const CallExpr &call_expr) const;
ProgramStateRef _handle_eval_g_error_new (CheckerContext &context,
const CallExpr &call_expr) const;
ProgramStateRef _handle_eval_g_error_free (CheckerContext &context,
const CallExpr &call_expr) const;
ProgramStateRef _handle_eval_g_clear_error (CheckerContext &context,
const CallExpr &call_expr) const;
ProgramStateRef _handle_eval_g_propagate_error (CheckerContext &context,
const CallExpr &call_expr) const;
bool _assert_gerror_set (SVal error_location,
bool null_allowed,
ProgramStateRef state,
CheckerContext &context,
const SourceRange &source_range) const;
bool _assert_gerror_unset (SVal error_location,
bool undef_allowed,
ProgramStateRef state,
CheckerContext &context,
const SourceRange &source_range) const;
bool _assert_gerror_ptr_clear (SVal error_location,
ProgramStateRef state,
CheckerContext &context,
const SourceRange &source_range) const;
bool _assert_code_in_domain (SVal domain,
SVal code,
ProgramStateRef state,
CheckerContext &context,
const SourceRange &domain_source_range,
const SourceRange &code_source_range) const;
ProgramStateRef _gerror_new (const Expr *call_expr,
bool bind_to_call,
DefinedSVal **allocated_sval,
ProgramStateRef state,
CheckerContext &context,
const SourceRange &source_range) const;
ProgramStateRef _set_gerror (SVal error_location,
DefinedSVal new_error,
ProgramStateRef state,
CheckerContext &context,
const SourceRange &source_range) const;
ProgramStateRef _clear_gerror (SVal error_location,
ProgramStateRef state,
CheckerContext &context,
const SourceRange &source_range) const;
ProgramStateRef _gerror_free (SVal error_location,
ProgramStateRef state,
CheckerContext &context,
const SourceRange &source_range) const;
SVal _error_from_error_ptr (SVal ptr_error_location,
CheckerContext &context) const;
public:
void checkPreCall (const CallEvent &call,
CheckerContext &context) const;
bool evalCall (
#ifdef HAVE_LLVM_9_0
const CallEvent &call_event,
#else
const CallExpr *call,
#endif
CheckerContext &context) const;
void checkBind (SVal loc, SVal val, const Stmt *stmt,
CheckerContext &context) const;
void checkDeadSymbols (SymbolReaper &symbol_reaper,
CheckerContext &context) const;
const std::string get_name () const { return "gerror"; }
};
} /* namespace tartan */
#endif /* !TARTAN_GERROR_CHECKER_H */
|