1 /*
2 * Copyright (C) 2009 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 "edify/expr.h"
18
19 #include <stdarg.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <unistd.h>
24
25 #include <memory>
26 #include <string>
27 #include <unordered_map>
28 #include <vector>
29
30 #include <android-base/parseint.h>
31 #include <android-base/stringprintf.h>
32 #include <android-base/strings.h>
33
34 #include "otautil/error_code.h"
35
36 // Functions should:
37 //
38 // - return a malloc()'d string
39 // - if Evaluate() on any argument returns nullptr, return nullptr.
40
BooleanString(const std::string & s)41 static bool BooleanString(const std::string& s) {
42 return !s.empty();
43 }
44
Evaluate(State * state,const std::unique_ptr<Expr> & expr,std::string * result)45 bool Evaluate(State* state, const std::unique_ptr<Expr>& expr, std::string* result) {
46 if (result == nullptr) {
47 return false;
48 }
49
50 std::unique_ptr<Value> v(expr->fn(expr->name.c_str(), state, expr->argv));
51 if (!v) {
52 return false;
53 }
54 if (v->type != Value::Type::STRING) {
55 ErrorAbort(state, kArgsParsingFailure, "expecting string, got value type %d", v->type);
56 return false;
57 }
58
59 *result = v->data;
60 return true;
61 }
62
EvaluateValue(State * state,const std::unique_ptr<Expr> & expr)63 Value* EvaluateValue(State* state, const std::unique_ptr<Expr>& expr) {
64 return expr->fn(expr->name.c_str(), state, expr->argv);
65 }
66
StringValue(const char * str)67 Value* StringValue(const char* str) {
68 if (str == nullptr) {
69 return nullptr;
70 }
71 return new Value(Value::Type::STRING, str);
72 }
73
StringValue(const std::string & str)74 Value* StringValue(const std::string& str) {
75 return StringValue(str.c_str());
76 }
77
ConcatFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)78 Value* ConcatFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
79 if (argv.empty()) {
80 return StringValue("");
81 }
82 std::string result;
83 for (size_t i = 0; i < argv.size(); ++i) {
84 std::string str;
85 if (!Evaluate(state, argv[i], &str)) {
86 return nullptr;
87 }
88 result += str;
89 }
90
91 return StringValue(result);
92 }
93
IfElseFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)94 Value* IfElseFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
95 if (argv.size() != 2 && argv.size() != 3) {
96 state->errmsg = "ifelse expects 2 or 3 arguments";
97 return nullptr;
98 }
99
100 std::string cond;
101 if (!Evaluate(state, argv[0], &cond)) {
102 return nullptr;
103 }
104
105 if (!cond.empty()) {
106 return EvaluateValue(state, argv[1]);
107 } else if (argv.size() == 3) {
108 return EvaluateValue(state, argv[2]);
109 }
110
111 return StringValue("");
112 }
113
AbortFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)114 Value* AbortFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
115 std::string msg;
116 if (!argv.empty() && Evaluate(state, argv[0], &msg)) {
117 state->errmsg += msg;
118 } else {
119 state->errmsg += "called abort()";
120 }
121 return nullptr;
122 }
123
AssertFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)124 Value* AssertFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
125 for (size_t i = 0; i < argv.size(); ++i) {
126 std::string result;
127 if (!Evaluate(state, argv[i], &result)) {
128 return nullptr;
129 }
130 if (result.empty()) {
131 int len = argv[i]->end - argv[i]->start;
132 state->errmsg = "assert failed: " + state->script.substr(argv[i]->start, len);
133 return nullptr;
134 }
135 }
136 return StringValue("");
137 }
138
SleepFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)139 Value* SleepFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
140 std::string val;
141 if (!Evaluate(state, argv[0], &val)) {
142 return nullptr;
143 }
144
145 int v;
146 if (!android::base::ParseInt(val.c_str(), &v, 0)) {
147 return nullptr;
148 }
149 sleep(v);
150
151 return StringValue(val);
152 }
153
StdoutFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)154 Value* StdoutFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
155 for (size_t i = 0; i < argv.size(); ++i) {
156 std::string v;
157 if (!Evaluate(state, argv[i], &v)) {
158 return nullptr;
159 }
160 fputs(v.c_str(), stdout);
161 }
162 return StringValue("");
163 }
164
LogicalAndFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)165 Value* LogicalAndFn(const char* name, State* state,
166 const std::vector<std::unique_ptr<Expr>>& argv) {
167 std::string left;
168 if (!Evaluate(state, argv[0], &left)) {
169 return nullptr;
170 }
171 if (BooleanString(left)) {
172 return EvaluateValue(state, argv[1]);
173 } else {
174 return StringValue("");
175 }
176 }
177
LogicalOrFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)178 Value* LogicalOrFn(const char* name, State* state,
179 const std::vector<std::unique_ptr<Expr>>& argv) {
180 std::string left;
181 if (!Evaluate(state, argv[0], &left)) {
182 return nullptr;
183 }
184 if (!BooleanString(left)) {
185 return EvaluateValue(state, argv[1]);
186 } else {
187 return StringValue(left);
188 }
189 }
190
LogicalNotFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)191 Value* LogicalNotFn(const char* name, State* state,
192 const std::vector<std::unique_ptr<Expr>>& argv) {
193 std::string val;
194 if (!Evaluate(state, argv[0], &val)) {
195 return nullptr;
196 }
197
198 return StringValue(BooleanString(val) ? "" : "t");
199 }
200
SubstringFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)201 Value* SubstringFn(const char* name, State* state,
202 const std::vector<std::unique_ptr<Expr>>& argv) {
203 std::string needle;
204 if (!Evaluate(state, argv[0], &needle)) {
205 return nullptr;
206 }
207
208 std::string haystack;
209 if (!Evaluate(state, argv[1], &haystack)) {
210 return nullptr;
211 }
212
213 std::string result = (haystack.find(needle) != std::string::npos) ? "t" : "";
214 return StringValue(result);
215 }
216
EqualityFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)217 Value* EqualityFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
218 std::string left;
219 if (!Evaluate(state, argv[0], &left)) {
220 return nullptr;
221 }
222 std::string right;
223 if (!Evaluate(state, argv[1], &right)) {
224 return nullptr;
225 }
226
227 const char* result = (left == right) ? "t" : "";
228 return StringValue(result);
229 }
230
InequalityFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)231 Value* InequalityFn(const char* name, State* state,
232 const std::vector<std::unique_ptr<Expr>>& argv) {
233 std::string left;
234 if (!Evaluate(state, argv[0], &left)) {
235 return nullptr;
236 }
237 std::string right;
238 if (!Evaluate(state, argv[1], &right)) {
239 return nullptr;
240 }
241
242 const char* result = (left != right) ? "t" : "";
243 return StringValue(result);
244 }
245
SequenceFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)246 Value* SequenceFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
247 std::unique_ptr<Value> left(EvaluateValue(state, argv[0]));
248 if (!left) {
249 return nullptr;
250 }
251 return EvaluateValue(state, argv[1]);
252 }
253
LessThanIntFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)254 Value* LessThanIntFn(const char* name, State* state,
255 const std::vector<std::unique_ptr<Expr>>& argv) {
256 if (argv.size() != 2) {
257 state->errmsg = "less_than_int expects 2 arguments";
258 return nullptr;
259 }
260
261 std::vector<std::string> args;
262 if (!ReadArgs(state, argv, &args)) {
263 return nullptr;
264 }
265
266 // Parse up to at least long long or 64-bit integers.
267 int64_t l_int;
268 if (!android::base::ParseInt(args[0].c_str(), &l_int)) {
269 state->errmsg = "failed to parse int in " + args[0];
270 return nullptr;
271 }
272
273 int64_t r_int;
274 if (!android::base::ParseInt(args[1].c_str(), &r_int)) {
275 state->errmsg = "failed to parse int in " + args[1];
276 return nullptr;
277 }
278
279 return StringValue(l_int < r_int ? "t" : "");
280 }
281
GreaterThanIntFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)282 Value* GreaterThanIntFn(const char* name, State* state,
283 const std::vector<std::unique_ptr<Expr>>& argv) {
284 if (argv.size() != 2) {
285 state->errmsg = "greater_than_int expects 2 arguments";
286 return nullptr;
287 }
288
289 std::vector<std::string> args;
290 if (!ReadArgs(state, argv, &args)) {
291 return nullptr;
292 }
293
294 // Parse up to at least long long or 64-bit integers.
295 int64_t l_int;
296 if (!android::base::ParseInt(args[0].c_str(), &l_int)) {
297 state->errmsg = "failed to parse int in " + args[0];
298 return nullptr;
299 }
300
301 int64_t r_int;
302 if (!android::base::ParseInt(args[1].c_str(), &r_int)) {
303 state->errmsg = "failed to parse int in " + args[1];
304 return nullptr;
305 }
306
307 return StringValue(l_int > r_int ? "t" : "");
308 }
309
Literal(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)310 Value* Literal(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
311 return StringValue(name);
312 }
313
314 // -----------------------------------------------------------------
315 // the function table
316 // -----------------------------------------------------------------
317
318 static std::unordered_map<std::string, Function> fn_table;
319
RegisterFunction(const std::string & name,Function fn)320 void RegisterFunction(const std::string& name, Function fn) {
321 fn_table[name] = fn;
322 }
323
FindFunction(const std::string & name)324 Function FindFunction(const std::string& name) {
325 if (fn_table.find(name) == fn_table.end()) {
326 return nullptr;
327 } else {
328 return fn_table[name];
329 }
330 }
331
RegisterBuiltins()332 void RegisterBuiltins() {
333 RegisterFunction("ifelse", IfElseFn);
334 RegisterFunction("abort", AbortFn);
335 RegisterFunction("assert", AssertFn);
336 RegisterFunction("concat", ConcatFn);
337 RegisterFunction("is_substring", SubstringFn);
338 RegisterFunction("stdout", StdoutFn);
339 RegisterFunction("sleep", SleepFn);
340
341 RegisterFunction("less_than_int", LessThanIntFn);
342 RegisterFunction("greater_than_int", GreaterThanIntFn);
343 }
344
345
346 // -----------------------------------------------------------------
347 // convenience methods for functions
348 // -----------------------------------------------------------------
349
350 // Evaluate the expressions in argv, and put the results of strings in args. If any expression
351 // evaluates to nullptr, return false. Return true on success.
ReadArgs(State * state,const std::vector<std::unique_ptr<Expr>> & argv,std::vector<std::string> * args)352 bool ReadArgs(State* state, const std::vector<std::unique_ptr<Expr>>& argv,
353 std::vector<std::string>* args) {
354 return ReadArgs(state, argv, args, 0, argv.size());
355 }
356
ReadArgs(State * state,const std::vector<std::unique_ptr<Expr>> & argv,std::vector<std::string> * args,size_t start,size_t len)357 bool ReadArgs(State* state, const std::vector<std::unique_ptr<Expr>>& argv,
358 std::vector<std::string>* args, size_t start, size_t len) {
359 if (args == nullptr) {
360 return false;
361 }
362 if (start + len > argv.size()) {
363 return false;
364 }
365 for (size_t i = start; i < start + len; ++i) {
366 std::string var;
367 if (!Evaluate(state, argv[i], &var)) {
368 args->clear();
369 return false;
370 }
371 args->push_back(var);
372 }
373 return true;
374 }
375
376 // Evaluate the expressions in argv, and put the results of Value* in args. If any expression
377 // evaluate to nullptr, return false. Return true on success.
ReadValueArgs(State * state,const std::vector<std::unique_ptr<Expr>> & argv,std::vector<std::unique_ptr<Value>> * args)378 bool ReadValueArgs(State* state, const std::vector<std::unique_ptr<Expr>>& argv,
379 std::vector<std::unique_ptr<Value>>* args) {
380 return ReadValueArgs(state, argv, args, 0, argv.size());
381 }
382
ReadValueArgs(State * state,const std::vector<std::unique_ptr<Expr>> & argv,std::vector<std::unique_ptr<Value>> * args,size_t start,size_t len)383 bool ReadValueArgs(State* state, const std::vector<std::unique_ptr<Expr>>& argv,
384 std::vector<std::unique_ptr<Value>>* args, size_t start, size_t len) {
385 if (args == nullptr) {
386 return false;
387 }
388 if (len == 0 || start + len > argv.size()) {
389 return false;
390 }
391 for (size_t i = start; i < start + len; ++i) {
392 std::unique_ptr<Value> v(EvaluateValue(state, argv[i]));
393 if (!v) {
394 args->clear();
395 return false;
396 }
397 args->push_back(std::move(v));
398 }
399 return true;
400 }
401
402 // Use printf-style arguments to compose an error message to put into
403 // *state. Returns nullptr.
ErrorAbort(State * state,const char * format,...)404 Value* ErrorAbort(State* state, const char* format, ...) {
405 va_list ap;
406 va_start(ap, format);
407 android::base::StringAppendV(&state->errmsg, format, ap);
408 va_end(ap);
409 return nullptr;
410 }
411
ErrorAbort(State * state,CauseCode cause_code,const char * format,...)412 Value* ErrorAbort(State* state, CauseCode cause_code, const char* format, ...) {
413 std::string err_message;
414 va_list ap;
415 va_start(ap, format);
416 android::base::StringAppendV(&err_message, format, ap);
417 va_end(ap);
418 // Ensure that there's exactly one line break at the end of the error message.
419 state->errmsg = android::base::Trim(err_message) + "\n";
420 state->cause_code = cause_code;
421 return nullptr;
422 }
423
State(const std::string & script,UpdaterInterface * interface)424 State::State(const std::string& script, UpdaterInterface* interface)
425 : script(script), updater(interface), error_code(kNoError), cause_code(kNoCause) {}
426