1f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// Copyright (c) 2016 The Chromium Authors. All rights reserved.
2f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// found in the LICENSE file.
4f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
5f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#include "CheckIPCVisitor.h"
6f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
7f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochusing namespace clang;
8f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
9f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochnamespace chrome_checker {
10f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
11f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochnamespace {
12f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
13f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochconst char kWriteParamBadType[] =
14f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    "[chromium-ipc] IPC::WriteParam() is called on blacklisted type '%0'%1.";
15f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
16f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochconst char kTupleBadType[] =
17f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    "[chromium-ipc] IPC tuple references banned type '%0'%1.";
18f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
19f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochconst char kWriteParamBadSignature[] =
20f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    "[chromium-ipc] IPC::WriteParam() is expected to have two arguments.";
21f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
22f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochconst char kNoteSeeHere[] =
23f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    "see here";
24f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
25f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}  // namespace
26f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
27f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochCheckIPCVisitor::CheckIPCVisitor(CompilerInstance& compiler)
28f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  : compiler_(compiler), context_(nullptr) {
29f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  auto& diagnostics = compiler_.getDiagnostics();
30f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  error_write_param_bad_type_ = diagnostics.getCustomDiagID(
31f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      DiagnosticsEngine::Error, kWriteParamBadType);
32f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  error_tuple_bad_type_ = diagnostics.getCustomDiagID(
33f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      DiagnosticsEngine::Error, kTupleBadType);
34f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  error_write_param_bad_signature_ = diagnostics.getCustomDiagID(
35f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      DiagnosticsEngine::Error, kWriteParamBadSignature);
36f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  note_see_here_ = diagnostics.getCustomDiagID(
37f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      DiagnosticsEngine::Note, kNoteSeeHere);
38f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
39f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  blacklisted_typedefs_ = llvm::StringSet<>({
40f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      "intmax_t",
41f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      "uintmax_t",
42f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      "intptr_t",
43f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      "uintptr_t",
44f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      "wint_t",
45f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      "size_t",
46f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      "rsize_t",
47f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      "ssize_t",
48f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      "ptrdiff_t",
49f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      "dev_t",
50f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      "off_t",
51f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      "clock_t",
52f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      "time_t",
53f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      "suseconds_t"
54f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  });
55f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
56f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
57f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochvoid CheckIPCVisitor::BeginDecl(Decl* decl) {
58f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  decl_stack_.push_back(decl);
59f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
60f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
61f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochvoid CheckIPCVisitor::EndDecl() {
62f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  decl_stack_.pop_back();
63f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
64f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
65f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochvoid CheckIPCVisitor::VisitTemplateSpecializationType(
66f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    TemplateSpecializationType* spec) {
67f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  ValidateCheckedTuple(spec);
68f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
69f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
70f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochvoid CheckIPCVisitor::VisitCallExpr(CallExpr* call_expr) {
71f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  ValidateWriteParam(call_expr);
72f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
73f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
74f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochbool CheckIPCVisitor::ValidateWriteParam(const CallExpr* call_expr) {
75f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  const FunctionDecl* callee_decl = call_expr->getDirectCallee();
76f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (!callee_decl ||
77f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      callee_decl->getQualifiedNameAsString() != "IPC::WriteParam") {
78f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return true;
79f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
80f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
81f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  return ValidateWriteParamSignature(call_expr) &&
82f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      ValidateWriteParamArgument(call_expr->getArg(1));
83f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
84f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
85f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// Checks that IPC::WriteParam() has expected signature.
86f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochbool CheckIPCVisitor::ValidateWriteParamSignature(
87f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    const CallExpr* call_expr) {
88f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (call_expr->getNumArgs() != 2) {
89f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    compiler_.getDiagnostics().Report(
90f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        call_expr->getExprLoc(), error_write_param_bad_signature_);
91f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return false;
92f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
93f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  return true;
94f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
95f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
96f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// Checks that IPC::WriteParam() argument type is allowed.
97f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// See CheckType() for specifics.
98f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochbool CheckIPCVisitor::ValidateWriteParamArgument(const Expr* arg_expr) {
99f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (auto* parent_fn_decl = GetParentDecl<FunctionDecl>()) {
100f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    auto template_kind = parent_fn_decl->getTemplatedKind();
101f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    if (template_kind != FunctionDecl::TK_NonTemplate &&
102f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        template_kind != FunctionDecl::TK_FunctionTemplate) {
103f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      // Skip all specializations - we don't check WriteParam() on dependent
104f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      // types (typedef info gets lost), and we checked all non-dependent uses
105f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      // earlier (when we checked the template itself).
106f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      return true;
107f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    }
108f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
109f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
110f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  QualType arg_type;
111f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
112f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  arg_expr = arg_expr->IgnoreImplicit();
113f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (auto* cast_expr = dyn_cast<ExplicitCastExpr>(arg_expr)) {
114f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    arg_type = cast_expr->getTypeAsWritten();
115f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  } else {
116f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    arg_type = arg_expr->getType();
117f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
118f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
119f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  CheckDetails details;
120f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (CheckType(arg_type, &details)) {
121f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return true;
122f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
123f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
124f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  ReportCheckError(details,
125f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                   arg_expr->getExprLoc(),
126f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                   error_write_param_bad_type_);
127f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
128f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  return false;
129f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
130f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
131f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// Checks that IPC::CheckedTuple<> is specialized with allowed types.
132f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// See CheckType() above for specifics.
133f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochbool CheckIPCVisitor::ValidateCheckedTuple(
134f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    const TemplateSpecializationType* spec) {
135f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  TemplateDecl* decl = spec->getTemplateName().getAsTemplateDecl();
136f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (!decl || decl->getQualifiedNameAsString() != "IPC::CheckedTuple") {
137f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return true;
138f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
139f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
140f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  bool valid = true;
141f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  for (unsigned i = 0; i != spec->getNumArgs(); ++i) {
142f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    const TemplateArgument& arg = spec->getArg(i);
143f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    CheckDetails details;
144f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    if (CheckTemplateArgument(arg, &details)) {
145f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      continue;
146f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    }
147f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
148f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    valid = false;
149f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
150f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    auto* parent_decl = GetParentDecl<Decl>();
151f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    ReportCheckError(
152f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        details,
153f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        parent_decl ? parent_decl->getLocStart() : SourceLocation(),
154f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        error_tuple_bad_type_);
155f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
156f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
157f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  return valid;
158f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
159f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
160f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochtemplate <typename T>
161f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochconst T* CheckIPCVisitor::GetParentDecl() const {
162f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  for (auto i = decl_stack_.rbegin(); i != decl_stack_.rend(); ++i) {
163f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    if (auto* parent = dyn_cast_or_null<T>(*i)) {
164f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      return parent;
165f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    }
166f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
167f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  return nullptr;
168f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
169f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
170f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
171f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochbool CheckIPCVisitor::IsBlacklistedType(QualType type) const {
172f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  return context_->hasSameUnqualifiedType(type, context_->LongTy) ||
173f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      context_->hasSameUnqualifiedType(type, context_->UnsignedLongTy);
174f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
175f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
176f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochbool CheckIPCVisitor::IsBlacklistedTypedef(const TypedefNameDecl* tdef) const {
177f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  return blacklisted_typedefs_.find(tdef->getName()) !=
178f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      blacklisted_typedefs_.end();
179f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
180f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
181f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// Checks that integer type is allowed (not blacklisted).
182f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochbool CheckIPCVisitor::CheckIntegerType(QualType type,
183f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                       CheckDetails* details) const {
184f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  bool seen_typedef = false;
185f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  while (true) {
186f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    details->exit_type = type;
187f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
188f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    if (auto* tdef = dyn_cast<TypedefType>(type)) {
189f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      if (IsBlacklistedTypedef(tdef->getDecl())) {
190f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        return false;
191f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      }
192f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      details->typedefs.push_back(tdef);
193f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      seen_typedef = true;
194f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    }
195f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
196f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    QualType desugared_type =
197f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        type->getLocallyUnqualifiedSingleStepDesugaredType();
198f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    if (desugared_type == type) {
199f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      break;
200f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    }
201f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
202f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    type = desugared_type;
203f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
204f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
205f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  return seen_typedef || !IsBlacklistedType(type);
206f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
207f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
208f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// Checks that |type| is allowed (not blacklisted), recursively visiting
209f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// template specializations.
210f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochbool CheckIPCVisitor::CheckType(QualType type, CheckDetails* details) const {
211f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (type->isReferenceType()) {
212f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    type = type->getPointeeType();
213f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
214f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  type = type.getLocalUnqualifiedType();
215f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
216f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (details->entry_type.isNull()) {
217f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    details->entry_type = type;
218f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
219f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
220f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (type->isIntegerType()) {
221f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return CheckIntegerType(type, details);
222f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
223f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
224f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  while (true) {
225f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    if (auto* spec = dyn_cast<TemplateSpecializationType>(type)) {
226f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      for (const TemplateArgument& arg: *spec) {
227f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        if (!CheckTemplateArgument(arg, details)) {
228f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          return false;
229f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        }
230f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      }
231f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      return true;
232f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    }
233f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
234f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    if (auto* record = dyn_cast<RecordType>(type)) {
235f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      if (auto* spec = dyn_cast<ClassTemplateSpecializationDecl>(
236f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch              record->getDecl())) {
237f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        const TemplateArgumentList& args = spec->getTemplateArgs();
238f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        for (unsigned i = 0; i != args.size(); ++i) {
239f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          if (!CheckTemplateArgument(args[i], details)) {
240f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch            return false;
241f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          }
242f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        }
243f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      }
244f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      return true;
245f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    }
246f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
247f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    if (auto* tdef = dyn_cast<TypedefType>(type)) {
248f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      details->typedefs.push_back(tdef);
249f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    }
250f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
251f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    QualType desugared_type =
252f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        type->getLocallyUnqualifiedSingleStepDesugaredType();
253f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    if (desugared_type == type) {
254f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      break;
255f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    }
256f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
257f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    type = desugared_type;
258f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
259f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
260f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  return true;
261f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
262f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
263f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochbool CheckIPCVisitor::CheckTemplateArgument(const TemplateArgument& arg,
264f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                            CheckDetails* details) const {
265f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  return arg.getKind() != TemplateArgument::Type ||
266f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      CheckType(arg.getAsType(), details);
267f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
268f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
269f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochvoid CheckIPCVisitor::ReportCheckError(const CheckDetails& details,
270f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                       SourceLocation loc,
271f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                       unsigned error) {
272f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DiagnosticsEngine& diagnostics = compiler_.getDiagnostics();
273f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
274f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  std::string entry_type = details.entry_type.getAsString();
275f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  std::string exit_type = details.exit_type.getAsString();
276f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
277f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  std::string via;
278f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (entry_type != exit_type) {
279f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    via = " via '" + entry_type + "'";
280f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
281f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  diagnostics.Report(loc, error) << exit_type << via;
282f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
283f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  for (const TypedefType* tdef: details.typedefs) {
284f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    diagnostics.Report(tdef->getDecl()->getLocation(), note_see_here_);
285f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
286f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
287f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
288f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}  // namespace chrome_checker
289