Remove malloc in edify functions

And switch them to std::vector & std::unique_ptr

Bug: 32117870
Test: recovery tests passed on sailfish
Change-Id: I5a45951c4bdf895be311d6d760e52e7a1b0798c3
diff --git a/edify/edify_parser.cpp b/edify/edify_parser.cpp
index 908fcf1..f1b5628 100644
--- a/edify/edify_parser.cpp
+++ b/edify/edify_parser.cpp
@@ -27,18 +27,19 @@
 #include <errno.h>
 #include <stdio.h>
 
+#include <memory>
 #include <string>
 
 #include <android-base/file.h>
 
 #include "expr.h"
 
-static void ExprDump(int depth, const Expr* n, const std::string& script) {
+static void ExprDump(int depth, const std::unique_ptr<Expr>& n, const std::string& script) {
     printf("%*s", depth*2, "");
     printf("%s %p (%d-%d) \"%s\"\n",
-           n->name == NULL ? "(NULL)" : n->name, n->fn, n->start, n->end,
+           n->name.c_str(), n->fn, n->start, n->end,
            script.substr(n->start, n->end - n->start).c_str());
-    for (int i = 0; i < n->argc; ++i) {
+    for (size_t i = 0; i < n->argv.size(); ++i) {
         ExprDump(depth+1, n->argv[i], script);
     }
 }
@@ -57,7 +58,7 @@
         return 1;
     }
 
-    Expr* root;
+    std::unique_ptr<Expr> root;
     int error_count = 0;
     int error = parse_string(buffer.data(), &root, &error_count);
     printf("parse returned %d; %d errors encountered\n", error, error_count);
diff --git a/edify/expr.cpp b/edify/expr.cpp
index 329cf3a..2b7fd7a 100644
--- a/edify/expr.cpp
+++ b/edify/expr.cpp
@@ -40,12 +40,12 @@
     return !s.empty();
 }
 
-bool Evaluate(State* state, Expr* expr, std::string* result) {
+bool Evaluate(State* state, const std::unique_ptr<Expr>& expr, std::string* result) {
     if (result == nullptr) {
         return false;
     }
 
-    std::unique_ptr<Value> v(expr->fn(expr->name, state, expr->argc, expr->argv));
+    std::unique_ptr<Value> v(expr->fn(expr->name.c_str(), state, expr->argv));
     if (!v) {
         return false;
     }
@@ -58,8 +58,8 @@
     return true;
 }
 
-Value* EvaluateValue(State* state, Expr* expr) {
-    return expr->fn(expr->name, state, expr->argc, expr->argv);
+Value* EvaluateValue(State* state, const std::unique_ptr<Expr>& expr) {
+    return expr->fn(expr->name.c_str(), state, expr->argv);
 }
 
 Value* StringValue(const char* str) {
@@ -73,12 +73,12 @@
     return StringValue(str.c_str());
 }
 
-Value* ConcatFn(const char* name, State* state, int argc, Expr* argv[]) {
-    if (argc == 0) {
+Value* ConcatFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
+    if (argv.empty()) {
         return StringValue("");
     }
     std::string result;
-    for (int i = 0; i < argc; ++i) {
+    for (size_t i = 0; i < argv.size(); ++i) {
         std::string str;
         if (!Evaluate(state, argv[i], &str)) {
             return nullptr;
@@ -89,8 +89,8 @@
     return StringValue(result);
 }
 
-Value* IfElseFn(const char* name, State* state, int argc, Expr* argv[]) {
-    if (argc != 2 && argc != 3) {
+Value* IfElseFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
+    if (argv.size() != 2 && argv.size() != 3) {
         state->errmsg = "ifelse expects 2 or 3 arguments";
         return nullptr;
     }
@@ -102,16 +102,16 @@
 
     if (!cond.empty()) {
         return EvaluateValue(state, argv[1]);
-    } else if (argc == 3) {
+    } else if (argv.size() == 3) {
         return EvaluateValue(state, argv[2]);
     }
 
     return StringValue("");
 }
 
-Value* AbortFn(const char* name, State* state, int argc, Expr* argv[]) {
+Value* AbortFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
     std::string msg;
-    if (argc > 0 && Evaluate(state, argv[0], &msg)) {
+    if (!argv.empty() && Evaluate(state, argv[0], &msg)) {
         state->errmsg = msg;
     } else {
         state->errmsg = "called abort()";
@@ -119,8 +119,8 @@
     return nullptr;
 }
 
-Value* AssertFn(const char* name, State* state, int argc, Expr* argv[]) {
-    for (int i = 0; i < argc; ++i) {
+Value* AssertFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
+    for (size_t i = 0; i < argv.size(); ++i) {
         std::string result;
         if (!Evaluate(state, argv[i], &result)) {
             return nullptr;
@@ -134,7 +134,7 @@
     return StringValue("");
 }
 
-Value* SleepFn(const char* name, State* state, int argc, Expr* argv[]) {
+Value* SleepFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
     std::string val;
     if (!Evaluate(state, argv[0], &val)) {
         return nullptr;
@@ -149,8 +149,8 @@
     return StringValue(val);
 }
 
-Value* StdoutFn(const char* name, State* state, int argc, Expr* argv[]) {
-    for (int i = 0; i < argc; ++i) {
+Value* StdoutFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
+    for (size_t i = 0; i < argv.size(); ++i) {
         std::string v;
         if (!Evaluate(state, argv[i], &v)) {
             return nullptr;
@@ -161,7 +161,7 @@
 }
 
 Value* LogicalAndFn(const char* name, State* state,
-                   int argc, Expr* argv[]) {
+                    const std::vector<std::unique_ptr<Expr>>& argv) {
     std::string left;
     if (!Evaluate(state, argv[0], &left)) {
         return nullptr;
@@ -174,7 +174,7 @@
 }
 
 Value* LogicalOrFn(const char* name, State* state,
-                   int argc, Expr* argv[]) {
+                   const std::vector<std::unique_ptr<Expr>>& argv) {
     std::string left;
     if (!Evaluate(state, argv[0], &left)) {
         return nullptr;
@@ -187,7 +187,7 @@
 }
 
 Value* LogicalNotFn(const char* name, State* state,
-                    int argc, Expr* argv[]) {
+                    const std::vector<std::unique_ptr<Expr>>& argv) {
     std::string val;
     if (!Evaluate(state, argv[0], &val)) {
         return nullptr;
@@ -197,7 +197,7 @@
 }
 
 Value* SubstringFn(const char* name, State* state,
-                   int argc, Expr* argv[]) {
+                   const std::vector<std::unique_ptr<Expr>>& argv) {
     std::string needle;
     if (!Evaluate(state, argv[0], &needle)) {
         return nullptr;
@@ -212,7 +212,7 @@
     return StringValue(result);
 }
 
-Value* EqualityFn(const char* name, State* state, int argc, Expr* argv[]) {
+Value* EqualityFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
     std::string left;
     if (!Evaluate(state, argv[0], &left)) {
         return nullptr;
@@ -226,7 +226,8 @@
     return StringValue(result);
 }
 
-Value* InequalityFn(const char* name, State* state, int argc, Expr* argv[]) {
+Value* InequalityFn(const char* name, State* state,
+                    const std::vector<std::unique_ptr<Expr>>& argv) {
     std::string left;
     if (!Evaluate(state, argv[0], &left)) {
         return nullptr;
@@ -240,7 +241,7 @@
     return StringValue(result);
 }
 
-Value* SequenceFn(const char* name, State* state, int argc, Expr* argv[]) {
+Value* SequenceFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
     std::unique_ptr<Value> left(EvaluateValue(state, argv[0]));
     if (!left) {
         return nullptr;
@@ -248,14 +249,15 @@
     return EvaluateValue(state, argv[1]);
 }
 
-Value* LessThanIntFn(const char* name, State* state, int argc, Expr* argv[]) {
-    if (argc != 2) {
+Value* LessThanIntFn(const char* name, State* state,
+                     const std::vector<std::unique_ptr<Expr>>& argv) {
+    if (argv.size() != 2) {
         state->errmsg = "less_than_int expects 2 arguments";
         return nullptr;
     }
 
     std::vector<std::string> args;
-    if (!ReadArgs(state, 2, argv, &args)) {
+    if (!ReadArgs(state, argv, &args)) {
         return nullptr;
     }
 
@@ -276,20 +278,34 @@
 }
 
 Value* GreaterThanIntFn(const char* name, State* state,
-                        int argc, Expr* argv[]) {
-    if (argc != 2) {
+                        const std::vector<std::unique_ptr<Expr>>& argv) {
+    if (argv.size() != 2) {
         state->errmsg = "greater_than_int expects 2 arguments";
         return nullptr;
     }
 
-    Expr* temp[2];
-    temp[0] = argv[1];
-    temp[1] = argv[0];
+    std::vector<std::string> args;
+    if (!ReadArgs(state, argv, &args)) {
+        return nullptr;
+    }
 
-    return LessThanIntFn(name, state, 2, temp);
+    // Parse up to at least long long or 64-bit integers.
+    int64_t l_int;
+    if (!android::base::ParseInt(args[0].c_str(), &l_int)) {
+        state->errmsg = "failed to parse int in " + args[0];
+        return nullptr;
+    }
+
+    int64_t r_int;
+    if (!android::base::ParseInt(args[1].c_str(), &r_int)) {
+        state->errmsg = "failed to parse int in " + args[1];
+        return nullptr;
+    }
+
+    return StringValue(l_int > r_int ? "t" : "");
 }
 
-Value* Literal(const char* name, State* state, int argc, Expr* argv[]) {
+Value* Literal(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
     return StringValue(name);
 }
 
@@ -329,14 +345,22 @@
 //   convenience methods for functions
 // -----------------------------------------------------------------
 
-// Evaluate the expressions in argv, and put the results of strings in
-// args. If any expression evaluates to nullptr, free the rest and return
-// false. Return true on success.
-bool ReadArgs(State* state, int argc, Expr* argv[], std::vector<std::string>* args) {
+// Evaluate the expressions in argv, and put the results of strings in args. If any expression
+// evaluates to nullptr, return false. Return true on success.
+bool ReadArgs(State* state, const std::vector<std::unique_ptr<Expr>>& argv,
+              std::vector<std::string>* args) {
+    return ReadArgs(state, argv, args, 0, argv.size());
+}
+
+bool ReadArgs(State* state, const std::vector<std::unique_ptr<Expr>>& argv,
+              std::vector<std::string>* args, size_t start, size_t len) {
     if (args == nullptr) {
         return false;
     }
-    for (int i = 0; i < argc; ++i) {
+    if (len == 0 || start + len > argv.size()) {
+        return false;
+    }
+    for (size_t i = start; i < start + len; ++i) {
         std::string var;
         if (!Evaluate(state, argv[i], &var)) {
             args->clear();
@@ -347,15 +371,22 @@
     return true;
 }
 
-// Evaluate the expressions in argv, and put the results of Value* in
-// args. If any expression evaluate to nullptr, free the rest and return
-// false. Return true on success.
-bool ReadValueArgs(State* state, int argc, Expr* argv[],
+// Evaluate the expressions in argv, and put the results of Value* in args. If any expression
+// evaluate to nullptr, return false. Return true on success.
+bool ReadValueArgs(State* state, const std::vector<std::unique_ptr<Expr>>& argv,
                    std::vector<std::unique_ptr<Value>>* args) {
+    return ReadValueArgs(state, argv, args, 0, argv.size());
+}
+
+bool ReadValueArgs(State* state, const std::vector<std::unique_ptr<Expr>>& argv,
+                   std::vector<std::unique_ptr<Value>>* args, size_t start, size_t len) {
     if (args == nullptr) {
         return false;
     }
-    for (int i = 0; i < argc; ++i) {
+    if (len == 0 || start + len > argv.size()) {
+        return false;
+    }
+    for (size_t i = start; i < start + len; ++i) {
         std::unique_ptr<Value> v(EvaluateValue(state, argv[i]));
         if (!v) {
             args->clear();
diff --git a/edify/expr.h b/edify/expr.h
index 911adbc..4838d20 100644
--- a/edify/expr.h
+++ b/edify/expr.h
@@ -18,7 +18,10 @@
 #define _EXPRESSION_H
 
 #include <unistd.h>
+
+#include <memory>
 #include <string>
+#include <vector>
 
 #include "error_code.h"
 
@@ -65,47 +68,49 @@
 
 struct Expr;
 
-using Function = Value* (*)(const char* name, State* state, int argc, Expr* argv[]);
+using Function = Value* (*)(const char* name, State* state,
+                            const std::vector<std::unique_ptr<Expr>>& argv);
 
 struct Expr {
-    Function fn;
-    const char* name;
-    int argc;
-    Expr** argv;
-    int start, end;
+  Function fn;
+  std::string name;
+  std::vector<std::unique_ptr<Expr>> argv;
+  int start, end;
+
+  Expr(Function fn, const std::string& name, int start, int end) :
+    fn(fn),
+    name(name),
+    start(start),
+    end(end) {}
 };
 
-// Take one of the Expr*s passed to the function as an argument,
-// evaluate it, return the resulting Value.  The caller takes
-// ownership of the returned Value.
-Value* EvaluateValue(State* state, Expr* expr);
+// Evaluate the input expr, return the resulting Value.
+Value* EvaluateValue(State* state, const std::unique_ptr<Expr>& expr);
 
-// Take one of the Expr*s passed to the function as an argument,
-// evaluate it, assert that it is a string, and update the result
-// parameter. This function returns true if the evaluation succeeds.
-// This is a convenience function for older functions that want to
-// deal only with strings.
-bool Evaluate(State* state, Expr* expr, std::string* result);
+// Evaluate the input expr, assert that it is a string, and update the result parameter. This
+// function returns true if the evaluation succeeds. This is a convenience function for older
+// functions that want to deal only with strings.
+bool Evaluate(State* state, const std::unique_ptr<Expr>& expr, std::string* result);
 
 // Glue to make an Expr out of a literal.
-Value* Literal(const char* name, State* state, int argc, Expr* argv[]);
+Value* Literal(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv);
 
 // Functions corresponding to various syntactic sugar operators.
 // ("concat" is also available as a builtin function, to concatenate
 // more than two strings.)
-Value* ConcatFn(const char* name, State* state, int argc, Expr* argv[]);
-Value* LogicalAndFn(const char* name, State* state, int argc, Expr* argv[]);
-Value* LogicalOrFn(const char* name, State* state, int argc, Expr* argv[]);
-Value* LogicalNotFn(const char* name, State* state, int argc, Expr* argv[]);
-Value* SubstringFn(const char* name, State* state, int argc, Expr* argv[]);
-Value* EqualityFn(const char* name, State* state, int argc, Expr* argv[]);
-Value* InequalityFn(const char* name, State* state, int argc, Expr* argv[]);
-Value* SequenceFn(const char* name, State* state, int argc, Expr* argv[]);
+Value* ConcatFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv);
+Value* LogicalAndFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv);
+Value* LogicalOrFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv);
+Value* LogicalNotFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv);
+Value* SubstringFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv);
+Value* EqualityFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv);
+Value* InequalityFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv);
+Value* SequenceFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv);
 
 // Global builtins, registered by RegisterBuiltins().
-Value* IfElseFn(const char* name, State* state, int argc, Expr* argv[]);
-Value* AssertFn(const char* name, State* state, int argc, Expr* argv[]);
-Value* AbortFn(const char* name, State* state, int argc, Expr* argv[]);
+Value* IfElseFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv);
+Value* AssertFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv);
+Value* AbortFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv);
 
 // Register a new function.  The same Function may be registered under
 // multiple names, but a given name should only be used once.
@@ -120,15 +125,19 @@
 
 // --- convenience functions for use in functions ---
 
-// Evaluate the expressions in argv, and put the results of strings in
-// args. If any expression evaluates to nullptr, free the rest and return
-// false. Return true on success.
-bool ReadArgs(State* state, int argc, Expr* argv[], std::vector<std::string>* args);
+// Evaluate the expressions in argv, and put the results of strings in args. If any expression
+// evaluates to nullptr, return false. Return true on success.
+bool ReadArgs(State* state, const std::vector<std::unique_ptr<Expr>>& argv,
+              std::vector<std::string>* args);
+bool ReadArgs(State* state, const std::vector<std::unique_ptr<Expr>>& argv,
+              std::vector<std::string>* args, size_t start, size_t len);
 
-// Evaluate the expressions in argv, and put the results of Value* in
-// args. If any expression evaluate to nullptr, free the rest and return
-// false. Return true on success.
-bool ReadValueArgs(State* state, int argc, Expr* argv[], std::vector<std::unique_ptr<Value>>* args);
+// Evaluate the expressions in argv, and put the results of Value* in args. If any
+// expression evaluate to nullptr, return false. Return true on success.
+bool ReadValueArgs(State* state, const std::vector<std::unique_ptr<Expr>>& argv,
+                   std::vector<std::unique_ptr<Value>>* args);
+bool ReadValueArgs(State* state, const std::vector<std::unique_ptr<Expr>>& argv,
+                   std::vector<std::unique_ptr<Value>>* args, size_t start, size_t len);
 
 // Use printf-style arguments to compose an error message to put into
 // *state.  Returns NULL.
@@ -145,6 +154,6 @@
 
 Value* StringValue(const std::string& str);
 
-int parse_string(const char* str, Expr** root, int* error_count);
+int parse_string(const char* str, std::unique_ptr<Expr>* root, int* error_count);
 
 #endif  // _EXPRESSION_H
diff --git a/edify/parser.yy b/edify/parser.yy
index 58a8dec..97205fe 100644
--- a/edify/parser.yy
+++ b/edify/parser.yy
@@ -19,6 +19,10 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include <memory>
+#include <string>
+#include <vector>
+
 #include "expr.h"
 #include "yydefs.h"
 #include "parser.h"
@@ -26,8 +30,8 @@
 extern int gLine;
 extern int gColumn;
 
-void yyerror(Expr** root, int* error_count, const char* s);
-int yyparse(Expr** root, int* error_count);
+void yyerror(std::unique_ptr<Expr>* root, int* error_count, const char* s);
+int yyparse(std::unique_ptr<Expr>* root, int* error_count);
 
 struct yy_buffer_state;
 void yy_switch_to_buffer(struct yy_buffer_state* new_buffer);
@@ -38,17 +42,11 @@
 static Expr* Build(Function fn, YYLTYPE loc, size_t count, ...) {
     va_list v;
     va_start(v, count);
-    Expr* e = static_cast<Expr*>(malloc(sizeof(Expr)));
-    e->fn = fn;
-    e->name = "(operator)";
-    e->argc = count;
-    e->argv = static_cast<Expr**>(malloc(count * sizeof(Expr*)));
+    Expr* e = new Expr(fn, "(operator)", loc.start, loc.end);
     for (size_t i = 0; i < count; ++i) {
-        e->argv[i] = va_arg(v, Expr*);
+        e->argv.emplace_back(va_arg(v, Expr*));
     }
     va_end(v);
-    e->start = loc.start;
-    e->end = loc.end;
     return e;
 }
 
@@ -59,10 +57,7 @@
 %union {
     char* str;
     Expr* expr;
-    struct {
-        int argc;
-        Expr** argv;
-    } args;
+    std::vector<std::unique_ptr<Expr>>* args;
 }
 
 %token AND OR SUBSTR SUPERSTR EQ NE IF THEN ELSE ENDIF
@@ -70,7 +65,10 @@
 %type <expr> expr
 %type <args> arglist
 
-%parse-param {Expr** root}
+%destructor { delete $$; } expr
+%destructor { delete $$; } arglist
+
+%parse-param {std::unique_ptr<Expr>* root}
 %parse-param {int* error_count}
 %error-verbose
 
@@ -85,17 +83,11 @@
 
 %%
 
-input:  expr           { *root = $1; }
+input:  expr           { root->reset($1); }
 ;
 
 expr:  STRING {
-    $$ = static_cast<Expr*>(malloc(sizeof(Expr)));
-    $$->fn = Literal;
-    $$->name = $1;
-    $$->argc = 0;
-    $$->argv = NULL;
-    $$->start = @$.start;
-    $$->end = @$.end;
+    $$ = new Expr(Literal, $1, @$.start, @$.end);
 }
 |  '(' expr ')'                      { $$ = $2; $$->start=@$.start; $$->end=@$.end; }
 |  expr ';'                          { $$ = $1; $$->start=@1.start; $$->end=@1.end; }
@@ -110,41 +102,32 @@
 |  IF expr THEN expr ENDIF           { $$ = Build(IfElseFn, @$, 2, $2, $4); }
 |  IF expr THEN expr ELSE expr ENDIF { $$ = Build(IfElseFn, @$, 3, $2, $4, $6); }
 | STRING '(' arglist ')' {
-    $$ = static_cast<Expr*>(malloc(sizeof(Expr)));
-    $$->fn = FindFunction($1);
-    if ($$->fn == nullptr) {
-        char buffer[256];
-        snprintf(buffer, sizeof(buffer), "unknown function \"%s\"", $1);
-        yyerror(root, error_count, buffer);
+    Function fn = FindFunction($1);
+    if (fn == nullptr) {
+        std::string msg = "unknown function \"" + std::string($1) + "\"";
+        yyerror(root, error_count, msg.c_str());
         YYERROR;
     }
-    $$->name = $1;
-    $$->argc = $3.argc;
-    $$->argv = $3.argv;
-    $$->start = @$.start;
-    $$->end = @$.end;
+    $$ = new Expr(fn, $1, @$.start, @$.end);
+    $$->argv = std::move(*$3);
 }
 ;
 
 arglist:    /* empty */ {
-    $$.argc = 0;
-    $$.argv = NULL;
+    $$ = new std::vector<std::unique_ptr<Expr>>;
 }
 | expr {
-    $$.argc = 1;
-    $$.argv = static_cast<Expr**>(malloc(sizeof(Expr*)));
-    $$.argv[0] = $1;
+    $$ = new std::vector<std::unique_ptr<Expr>>;
+    $$->emplace_back($1);
 }
 | arglist ',' expr {
-    $$.argc = $1.argc + 1;
-    $$.argv = static_cast<Expr**>(realloc($$.argv, $$.argc * sizeof(Expr*)));
-    $$.argv[$$.argc-1] = $3;
+    $$->push_back(std::unique_ptr<Expr>($3));
 }
 ;
 
 %%
 
-void yyerror(Expr** root, int* error_count, const char* s) {
+void yyerror(std::unique_ptr<Expr>* root, int* error_count, const char* s) {
   if (strlen(s) == 0) {
     s = "syntax error";
   }
@@ -152,7 +135,7 @@
   ++*error_count;
 }
 
-int parse_string(const char* str, Expr** root, int* error_count) {
+int parse_string(const char* str, std::unique_ptr<Expr>* root, int* error_count) {
     yy_switch_to_buffer(yy_scan_string(str));
     return yyparse(root, error_count);
 }