clang
20.0.0git
lib
StaticAnalyzer
Checkers
CastSizeChecker.cpp
Go to the documentation of this file.
1
//=== CastSizeChecker.cpp ---------------------------------------*- C++ -*-===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
//
9
// CastSizeChecker checks when casting a malloc'ed symbolic region to type T,
10
// whether the size of the symbolic region is a multiple of the size of T.
11
//
12
//===----------------------------------------------------------------------===//
13
14
#include "
clang/AST/CharUnits.h
"
15
#include "
clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h
"
16
#include "
clang/StaticAnalyzer/Core/BugReporter/BugType.h
"
17
#include "
clang/StaticAnalyzer/Core/Checker.h
"
18
#include "
clang/StaticAnalyzer/Core/CheckerManager.h
"
19
#include "
clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
"
20
#include "
clang/StaticAnalyzer/Core/PathSensitive/DynamicExtent.h
"
21
22
using namespace
clang
;
23
using namespace
ento;
24
25
namespace
{
26
class
CastSizeChecker :
public
Checker
< check::PreStmt<CastExpr> > {
27
const
BugType
BT{
this
,
"Cast region with wrong size."
};
28
29
public
:
30
void
checkPreStmt(
const
CastExpr
*CE,
CheckerContext
&
C
)
const
;
31
};
32
}
33
34
/// Check if we are casting to a struct with a flexible array at the end.
35
/// \code
36
/// struct foo {
37
/// size_t len;
38
/// struct bar data[];
39
/// };
40
/// \endcode
41
/// or
42
/// \code
43
/// struct foo {
44
/// size_t len;
45
/// struct bar data[0];
46
/// }
47
/// \endcode
48
/// In these cases it is also valid to allocate size of struct foo + a multiple
49
/// of struct bar.
50
static
bool
evenFlexibleArraySize
(
ASTContext
&Ctx,
CharUnits
RegionSize,
51
CharUnits
TypeSize,
QualType
ToPointeeTy) {
52
const
RecordType
*RT = ToPointeeTy->
getAs
<
RecordType
>();
53
if
(!RT)
54
return
false
;
55
56
const
RecordDecl
*RD = RT->
getDecl
();
57
RecordDecl::field_iterator
Iter
(RD->
field_begin
());
58
RecordDecl::field_iterator
End(RD->
field_end
());
59
const
FieldDecl
*
Last
=
nullptr
;
60
for
(;
Iter
!= End; ++
Iter
)
61
Last
= *
Iter
;
62
assert(
Last
&&
"empty structs should already be handled"
);
63
64
const
Type
*ElemType =
Last
->getType()->getArrayElementTypeNoTypeQual();
65
CharUnits
FlexSize;
66
if
(
const
ConstantArrayType
*ArrayTy =
67
Ctx.
getAsConstantArrayType
(
Last
->getType())) {
68
FlexSize = Ctx.
getTypeSizeInChars
(ElemType);
69
if
(ArrayTy->getSize() == 1 && TypeSize > FlexSize)
70
TypeSize -= FlexSize;
71
else
if
(!ArrayTy->isZeroSize())
72
return
false
;
73
}
else
if
(RD->