1 /*
2  * Copyright (C) 2022, The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "generate_cpp_analyzer.h"
18 
19 #include <string>
20 #include "aidl.h"
21 #include "aidl_language.h"
22 #include "aidl_to_common.h"
23 #include "aidl_to_cpp.h"
24 #include "code_writer.h"
25 #include "logging.h"
26 
27 using std::string;
28 using std::unique_ptr;
29 
30 namespace android {
31 namespace aidl {
32 namespace cpp {
33 namespace {
34 
35 const char kAndroidStatusVarName[] = "_aidl_ret_status";
36 const char kReturnVarName[] = "_aidl_return";
37 const char kDataVarName[] = "_aidl_data";
38 const char kReplyVarName[] = "_aidl_reply";
39 
GenerateAnalyzerTransaction(CodeWriter & out,const AidlInterface & interface,const AidlMethod & method,const AidlTypenames & typenames,const Options & options)40 void GenerateAnalyzerTransaction(CodeWriter& out, const AidlInterface& interface,
41                                  const AidlMethod& method, const AidlTypenames& typenames,
42                                  const Options& options) {
43   // Reading past the interface descriptor and reply binder status
44   out << "_aidl_ret_status = ::android::OK;\n";
45   out.Write("if (!(%s.enforceInterface(android::String16(\"%s\")))) {\n", kDataVarName,
46             interface.GetDescriptor().c_str());
47   out.Write("  %s = ::android::BAD_TYPE;\n", kAndroidStatusVarName);
48   out << "  std::cout << \"  Failure: Parcel interface does not match.\" << std::endl;\n"
49       << "  break;\n"
50       << "}\n";
51 
52   // Declare parameters
53   for (const unique_ptr<AidlArgument>& a : method.GetArguments()) {
54     out.Write("%s %s;\n", CppNameOf(a->GetType(), typenames).c_str(), BuildVarName(*a).c_str());
55   }
56   out << "::android::binder::Status binderStatus;\n";
57   // Declare and read the return value.
58   // Read past the binder status.
59   out.Write("binderStatus.readFromParcel(%s);\n", kReplyVarName);
60   if (method.GetType().GetName() != "void") {
61     out.Write("%s %s;\n", CppNameOf(method.GetType(), typenames).c_str(), kReturnVarName);
62     out.Write("bool returnError = false;\n");
63   }
64 
65   // Read Reply
66   if (method.GetType().GetName() != "void") {
67     out.Write("%s = %s.%s(%s);\n", kAndroidStatusVarName, kReplyVarName,
68               ParcelReadMethodOf(method.GetType(), typenames).c_str(),
69               ParcelReadCastOf(method.GetType(), typenames, string("&") + kReturnVarName).c_str());
70     out.Write("if (((%s) != (android::NO_ERROR))) {\n", kAndroidStatusVarName);
71     out.Indent();
72     out.Write(
73         "std::cerr << \"Failure: error in reading return value from Parcel.\" << std::endl;\n");
74     out.Write("returnError = true;\n");
75     out.Dedent();
76     out.Write("}\n");
77   }
78 
79   // Reading arguments
80   out << "do { // Single-pass loop to break if argument reading fails\n";
81   out.Indent();
82   for (const auto& a : method.GetArguments()) {
83     out.Write("%s = %s.%s(%s);\n", kAndroidStatusVarName, kDataVarName,
84               ParcelReadMethodOf(a->GetType(), typenames).c_str(),
85               ParcelReadCastOf(a->GetType(), typenames, "&" + BuildVarName(*a)).c_str());
86     out.Write("if (((%s) != (android::NO_ERROR))) {\n", kAndroidStatusVarName);
87     out.Indent();
88     out.Write("std::cerr << \"Failure: error in reading argument %s from Parcel.\" << std::endl;\n",
89               a->GetName().c_str());
90     out.Dedent();
91     out.Write("  break;\n}\n");
92   }
93   out.Dedent();
94   out << "} while(false);\n";
95 
96   if (!method.GetArguments().empty() && options.GetMinSdkVersion() >= SDK_VERSION_Tiramisu) {
97     out.Write(
98         "if (!%s.enforceNoDataAvail().isOk()) {\n  %s = android::BAD_VALUE;\n  std::cout << \"  "
99         "Failure: Parcel has too much data.\" << std::endl;\n  break;\n}\n",
100         kDataVarName, kAndroidStatusVarName);
101   }
102 
103   // Arguments
104   out.Write("std::cout << \"  arguments: \" << std::endl;\n");
105   for (const auto& a : method.GetArguments()) {
106     out.Write(
107         "std::cout << \"    %s: \" << ::android::internal::ToString(%s) "
108         "<< std::endl;\n",
109         a->GetName().c_str(), BuildVarName(*a).c_str());
110   }
111 
112   // Return Value
113   if (method.GetType().GetName() != "void") {
114     out.Write("if (returnError) {\n");
115     out.Indent();
116     out.Write("std::cout << \"  return: <error>\" << std::endl;\n");
117     out.Dedent();
118     out.Write("} else {");
119     out.Indent();
120     out.Write("std::cout << \"  return: \" << ::android::internal::ToString(%s) << std::endl;\n",
121               kReturnVarName);
122     out.Dedent();
123     out.Write("}\n");
124   } else {
125     out.Write("std::cout << \"  return: void\" << std::endl;\n");
126   }
127 }
128 
GenerateAnalyzerSource(CodeWriter & out,const AidlDefinedType & defined_type,const AidlTypenames & typenames,const Options & options)129 void GenerateAnalyzerSource(CodeWriter& out, const AidlDefinedType& defined_type,
130                             const AidlTypenames& typenames, const Options& options) {
131   auto interface = AidlCast<AidlInterface>(defined_type);
132   string q_name = GetQualifiedName(*interface, ClassNames::INTERFACE);
133 
134   string canonicalName = defined_type.GetCanonicalName();
135   string interfaceName = defined_type.GetName();
136 
137   // Includes
138   vector<string> include_list{
139       "iostream", "binder/Parcel.h", "android/binder_to_string.h",
140       HeaderFile(*interface, ClassNames::RAW, false),
141       // HeaderFile(*interface, ClassNames::INTERFACE, false),
142   };
143   for (const auto& include : include_list) {
144     out << "#include <" << include << ">\n";
145   }
146 
147   out << "namespace {\n";
148   // Function Start
149   out.Write(
150       "android::status_t analyze%s(uint32_t _aidl_code, const android::Parcel& %s, const "
151       "android::Parcel& %s) {\n",
152       q_name.c_str(), kDataVarName, kReplyVarName);
153   out.Indent();
154   out.Write("android::status_t %s;\nswitch(_aidl_code) {\n", kAndroidStatusVarName);
155   out.Indent();
156 
157   // Main Switch Statement
158   for (const auto& method : interface->GetMethods()) {
159     out.Write("case ::android::IBinder::FIRST_CALL_TRANSACTION + %d:\n{\n", (method->GetId()));
160     out.Indent();
161     out.Write("std::cout << \"%s.%s()\" << std::endl;\n", interfaceName.c_str(),
162               method->GetName().c_str());
163     GenerateAnalyzerTransaction(out, *interface, *method, typenames, options);
164     out.Dedent();
165     out << "}\n";
166     out << "break;\n";
167   }
168   out << "default:\n{\n  std::cout << \"  Transaction code \" << _aidl_code << \" not known.\" << "
169          "std::endl;\n";
170   out.Write("%s = android::UNKNOWN_TRANSACTION;\n}\n", kAndroidStatusVarName);
171   out.Dedent();
172   out.Write("}\nreturn %s;\n", kAndroidStatusVarName);
173   out << "// To prevent unused variable warnings\n";
174   out.Write("(void)%s; (void)%s; (void)%s;\n", kAndroidStatusVarName, kDataVarName, kReplyVarName);
175   out.Dedent();
176   out << "}\n\n} // namespace\n";
177 
178   out << "\n#include <Analyzer.h>\nusing android::aidl::Analyzer;\n";
179   out.Write(
180       "__attribute__((constructor)) static void addAnalyzer() {\n"
181       "  Analyzer::installAnalyzer(std::make_unique<Analyzer>(\"%s\", \"%s\", &analyze%s));\n}\n",
182       canonicalName.c_str(), interfaceName.c_str(), q_name.c_str());
183 }
184 
GenerateAnalyzerPlaceholder(CodeWriter & out,const AidlDefinedType &,const AidlTypenames &,const Options &)185 void GenerateAnalyzerPlaceholder(CodeWriter& out, const AidlDefinedType& /*defined_type*/,
186                                  const AidlTypenames& /*typenames*/, const Options& /*options*/) {
187   out << "// This file is intentionally left blank as placeholder for building an analyzer.\n";
188 }
189 
190 }  // namespace
191 
GenerateCppAnalyzer(const string & output_file,const Options & options,const AidlTypenames & typenames,const AidlDefinedType & defined_type,const IoDelegate & io_delegate)192 bool GenerateCppAnalyzer(const string& output_file, const Options& options,
193                          const AidlTypenames& typenames, const AidlDefinedType& defined_type,
194                          const IoDelegate& io_delegate) {
195   if (!ValidateOutputFilePath(output_file, options, defined_type)) {
196     return false;
197   }
198 
199   using GenFn = void (*)(CodeWriter & out, const AidlDefinedType& defined_type,
200                          const AidlTypenames& typenames, const Options& options);
201   auto gen = [&](auto file, GenFn fn) {
202     unique_ptr<CodeWriter> writer(io_delegate.GetCodeWriter(file));
203 
204     GenerateAutoGenHeader(*writer, options);
205 
206     fn(*writer, defined_type, typenames, options);
207     AIDL_FATAL_IF(!writer->Close(), defined_type) << "I/O Error!";
208     return true;
209   };
210 
211   if (AidlCast<AidlInterface>(defined_type)) {
212     return gen(output_file, &GenerateAnalyzerSource);
213   } else {
214     return gen(output_file, &GenerateAnalyzerPlaceholder);
215   }
216 }
217 
218 }  // namespace cpp
219 }  // namespace aidl
220 }  // namespace android
221