diff options
-rw-r--r-- | asn1_decoder.cpp | 253 | ||||
-rw-r--r-- | asn1_decoder.h | 45 | ||||
-rw-r--r-- | edify/edify_parser.cpp | 9 | ||||
-rw-r--r-- | edify/expr.cpp | 119 | ||||
-rw-r--r-- | edify/expr.h | 83 | ||||
-rw-r--r-- | edify/parser.yy | 71 | ||||
-rw-r--r-- | tests/component/edify_test.cpp | 5 | ||||
-rw-r--r-- | tests/component/updater_test.cpp | 3 | ||||
-rw-r--r-- | tests/unit/asn1_decoder_test.cpp | 397 | ||||
-rw-r--r-- | updater/blockimg.cpp | 66 | ||||
-rw-r--r-- | updater/install.cpp | 242 | ||||
-rw-r--r-- | updater/updater.cpp | 2 | ||||
-rw-r--r-- | verifier.cpp | 76 |
13 files changed, 704 insertions, 667 deletions
diff --git a/asn1_decoder.cpp b/asn1_decoder.cpp index ca4ee5267..a9dfccc58 100644 --- a/asn1_decoder.cpp +++ b/asn1_decoder.cpp @@ -14,178 +14,145 @@ * limitations under the License. */ -#include <malloc.h> -#include <stdint.h> -#include <string.h> - #include "asn1_decoder.h" +#include <stdint.h> -typedef struct asn1_context { - size_t length; - const uint8_t* p; - int app_type; -} asn1_context_t; - - -static const int kMaskConstructed = 0xE0; -static const int kMaskTag = 0x7F; -static const int kMaskAppType = 0x1F; - -static const int kTagOctetString = 0x04; -static const int kTagOid = 0x06; -static const int kTagSequence = 0x30; -static const int kTagSet = 0x31; -static const int kTagConstructed = 0xA0; - -asn1_context_t* asn1_context_new(const uint8_t* buffer, size_t length) { - asn1_context_t* ctx = (asn1_context_t*) calloc(1, sizeof(asn1_context_t)); - if (ctx == NULL) { - return NULL; - } - ctx->p = buffer; - ctx->length = length; - return ctx; -} - -void asn1_context_free(asn1_context_t* ctx) { - free(ctx); +int asn1_context::peek_byte() const { + if (length_ <= 0) { + return -1; + } + return *p_; } -static inline int peek_byte(asn1_context_t* ctx) { - if (ctx->length <= 0) { - return -1; - } - return *ctx->p; -} +int asn1_context::get_byte() { + if (length_ <= 0) { + return -1; + } -static inline int get_byte(asn1_context_t* ctx) { - if (ctx->length <= 0) { - return -1; - } - int byte = *ctx->p; - ctx->p++; - ctx->length--; - return byte; + int byte = *p_; + p_++; + length_--; + return byte; } -static inline bool skip_bytes(asn1_context_t* ctx, size_t num_skip) { - if (ctx->length < num_skip) { - return false; - } - ctx->p += num_skip; - ctx->length -= num_skip; - return true; +bool asn1_context::skip_bytes(size_t num_skip) { + if (length_ < num_skip) { + return false; + } + p_ += num_skip; + length_ -= num_skip; + return true; } -static bool decode_length(asn1_context_t* ctx, size_t* out_len) { - int num_octets = get_byte(ctx); - if (num_octets == -1) { - return false; - } - if ((num_octets & 0x80) == 0x00) { - *out_len = num_octets; - return 1; - } - num_octets &= kMaskTag; - if ((size_t)num_octets >= sizeof(size_t)) { - return false; - } - size_t length = 0; - for (int i = 0; i < num_octets; ++i) { - int byte = get_byte(ctx); - if (byte == -1) { - return false; - } - length <<= 8; - length += byte; - } - *out_len = length; +bool asn1_context::decode_length(size_t* out_len) { + int num_octets = get_byte(); + if (num_octets == -1) { + return false; + } + if ((num_octets & 0x80) == 0x00) { + *out_len = num_octets; return true; + } + num_octets &= kMaskTag; + if (static_cast<size_t>(num_octets) >= sizeof(size_t)) { + return false; + } + size_t length = 0; + for (int i = 0; i < num_octets; ++i) { + int byte = get_byte(); + if (byte == -1) { + return false; + } + length <<= 8; + length += byte; + } + *out_len = length; + return true; } /** * Returns the constructed type and advances the pointer. E.g. A0 -> 0 */ -asn1_context_t* asn1_constructed_get(asn1_context_t* ctx) { - int type = get_byte(ctx); - if (type == -1 || (type & kMaskConstructed) != kTagConstructed) { - return NULL; - } - size_t length; - if (!decode_length(ctx, &length) || length > ctx->length) { - return NULL; - } - asn1_context_t* app_ctx = asn1_context_new(ctx->p, length); - app_ctx->app_type = type & kMaskAppType; - return app_ctx; +asn1_context* asn1_context::asn1_constructed_get() { + int type = get_byte(); + if (type == -1 || (type & kMaskConstructed) != kTagConstructed) { + return nullptr; + } + size_t length; + if (!decode_length(&length) || length > length_) { + return nullptr; + } + asn1_context* app_ctx = new asn1_context(p_, length); + app_ctx->app_type_ = type & kMaskAppType; + return app_ctx; } -bool asn1_constructed_skip_all(asn1_context_t* ctx) { - int byte = peek_byte(ctx); - while (byte != -1 && (byte & kMaskConstructed) == kTagConstructed) { - skip_bytes(ctx, 1); - size_t length; - if (!decode_length(ctx, &length) || !skip_bytes(ctx, length)) { - return false; - } - byte = peek_byte(ctx); +bool asn1_context::asn1_constructed_skip_all() { + int byte = peek_byte(); + while (byte != -1 && (byte & kMaskConstructed) == kTagConstructed) { + skip_bytes(1); + size_t length; + if (!decode_length(&length) || !skip_bytes(length)) { + return false; } - return byte != -1; + byte = peek_byte(); + } + return byte != -1; } -int asn1_constructed_type(asn1_context_t* ctx) { - return ctx->app_type; +int asn1_context::asn1_constructed_type() const { + return app_type_; } -asn1_context_t* asn1_sequence_get(asn1_context_t* ctx) { - if ((get_byte(ctx) & kMaskTag) != kTagSequence) { - return NULL; - } - size_t length; - if (!decode_length(ctx, &length) || length > ctx->length) { - return NULL; - } - return asn1_context_new(ctx->p, length); +asn1_context* asn1_context::asn1_sequence_get() { + if ((get_byte() & kMaskTag) != kTagSequence) { + return nullptr; + } + size_t length; + if (!decode_length(&length) || length > length_) { + return nullptr; + } + return new asn1_context(p_, length); } -asn1_context_t* asn1_set_get(asn1_context_t* ctx) { - if ((get_byte(ctx) & kMaskTag) != kTagSet) { - return NULL; - } - size_t length; - if (!decode_length(ctx, &length) || length > ctx->length) { - return NULL; - } - return asn1_context_new(ctx->p, length); +asn1_context* asn1_context::asn1_set_get() { + if ((get_byte() & kMaskTag) != kTagSet) { + return nullptr; + } + size_t length; + if (!decode_length(&length) || length > length_) { + return nullptr; + } + return new asn1_context(p_, length); } -bool asn1_sequence_next(asn1_context_t* ctx) { - size_t length; - if (get_byte(ctx) == -1 || !decode_length(ctx, &length) || !skip_bytes(ctx, length)) { - return false; - } - return true; +bool asn1_context::asn1_sequence_next() { + size_t length; + if (get_byte() == -1 || !decode_length(&length) || !skip_bytes(length)) { + return false; + } + return true; } -bool asn1_oid_get(asn1_context_t* ctx, const uint8_t** oid, size_t* length) { - if (get_byte(ctx) != kTagOid) { - return false; - } - if (!decode_length(ctx, length) || *length == 0 || *length > ctx->length) { - return false; - } - *oid = ctx->p; - return true; +bool asn1_context::asn1_oid_get(const uint8_t** oid, size_t* length) { + if (get_byte() != kTagOid) { + return false; + } + if (!decode_length(length) || *length == 0 || *length > length_) { + return false; + } + *oid = p_; + return true; } -bool asn1_octet_string_get(asn1_context_t* ctx, const uint8_t** octet_string, size_t* length) { - if (get_byte(ctx) != kTagOctetString) { - return false; - } - if (!decode_length(ctx, length) || *length == 0 || *length > ctx->length) { - return false; - } - *octet_string = ctx->p; - return true; +bool asn1_context::asn1_octet_string_get(const uint8_t** octet_string, size_t* length) { + if (get_byte() != kTagOctetString) { + return false; + } + if (!decode_length(length) || *length == 0 || *length > length_) { + return false; + } + *octet_string = p_; + return true; } diff --git a/asn1_decoder.h b/asn1_decoder.h index fbd118f90..3e992115a 100644 --- a/asn1_decoder.h +++ b/asn1_decoder.h @@ -14,23 +14,42 @@ * limitations under the License. */ - #ifndef ASN1_DECODER_H_ #define ASN1_DECODER_H_ #include <stdint.h> -typedef struct asn1_context asn1_context_t; - -asn1_context_t* asn1_context_new(const uint8_t* buffer, size_t length); -void asn1_context_free(asn1_context_t* ctx); -asn1_context_t* asn1_constructed_get(asn1_context_t* ctx); -bool asn1_constructed_skip_all(asn1_context_t* ctx); -int asn1_constructed_type(asn1_context_t* ctx); -asn1_context_t* asn1_sequence_get(asn1_context_t* ctx); -asn1_context_t* asn1_set_get(asn1_context_t* ctx); -bool asn1_sequence_next(asn1_context_t* seq); -bool asn1_oid_get(asn1_context_t* ctx, const uint8_t** oid, size_t* length); -bool asn1_octet_string_get(asn1_context_t* ctx, const uint8_t** octet_string, size_t* length); +class asn1_context { + public: + asn1_context(const uint8_t* buffer, size_t length) : p_(buffer), length_(length), app_type_(0) {} + int asn1_constructed_type() const; + asn1_context* asn1_constructed_get(); + bool asn1_constructed_skip_all(); + asn1_context* asn1_sequence_get(); + asn1_context* asn1_set_get(); + bool asn1_sequence_next(); + bool asn1_oid_get(const uint8_t** oid, size_t* length); + bool asn1_octet_string_get(const uint8_t** octet_string, size_t* length); + + private: + static constexpr int kMaskConstructed = 0xE0; + static constexpr int kMaskTag = 0x7F; + static constexpr int kMaskAppType = 0x1F; + + static constexpr int kTagOctetString = 0x04; + static constexpr int kTagOid = 0x06; + static constexpr int kTagSequence = 0x30; + static constexpr int kTagSet = 0x31; + static constexpr int kTagConstructed = 0xA0; + + int peek_byte() const; + int get_byte(); + bool skip_bytes(size_t num_skip); + bool decode_length(size_t* out_len); + + const uint8_t* p_; + size_t length_; + int app_type_; +}; #endif /* ASN1_DECODER_H_ */ diff --git a/edify/edify_parser.cpp b/edify/edify_parser.cpp index 908fcf13b..f1b56284c 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 @@ int main(int argc, char** argv) { 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 329cf3acd..2b7fd7a6a 100644 --- a/edify/expr.cpp +++ b/edify/expr.cpp @@ -40,12 +40,12 @@ static bool BooleanString(const std::string& s) { 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 @@ bool Evaluate(State* state, Expr* expr, std::string* result) { 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 @@ Value* StringValue(const std::string& str) { 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 @@ Value* ConcatFn(const char* name, State* state, int argc, Expr* argv[]) { 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 @@ Value* IfElseFn(const char* name, State* state, int argc, Expr* argv[]) { 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 @@ Value* AbortFn(const char* name, State* state, int argc, Expr* argv[]) { 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 @@ Value* AssertFn(const char* name, State* state, int argc, Expr* argv[]) { 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 @@ Value* SleepFn(const char* name, State* state, int argc, Expr* argv[]) { 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* StdoutFn(const char* name, State* state, int argc, Expr* argv[]) { } 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* LogicalAndFn(const char* name, State* state, } 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* LogicalOrFn(const char* name, State* state, } 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* LogicalNotFn(const char* name, State* state, } 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 @@ Value* SubstringFn(const char* name, State* state, 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 @@ Value* EqualityFn(const char* name, State* state, int argc, Expr* argv[]) { 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 @@ Value* InequalityFn(const char* name, State* state, int argc, Expr* argv[]) { 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 @@ Value* SequenceFn(const char* name, State* state, int argc, Expr* argv[]) { 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* LessThanIntFn(const char* name, State* state, int argc, Expr* argv[]) { } 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; + } + + // 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 LessThanIntFn(name, state, 2, temp); + 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 @@ void RegisterBuiltins() { // 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 @@ bool ReadArgs(State* state, int argc, Expr* argv[], std::vector<std::string>* ar 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 911adbc82..4838d20c0 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 Value { 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 @@ Function FindFunction(const std::string& name); // --- 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 char* str); 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 58a8dec65..97205fe3b 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 @@ struct yy_buffer_state* yy_scan_string(const char* yystr); 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 @@ static Expr* Build(Function fn, YYLTYPE loc, size_t count, ...) { %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 @@ static Expr* Build(Function fn, YYLTYPE loc, size_t count, ...) { %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 @@ static Expr* Build(Function fn, YYLTYPE loc, size_t count, ...) { %% -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 @@ expr: STRING { | 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 @@ void yyerror(Expr** root, int* error_count, const char* s) { ++*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); } diff --git a/tests/component/edify_test.cpp b/tests/component/edify_test.cpp index 287e40cc6..61a1e6b64 100644 --- a/tests/component/edify_test.cpp +++ b/tests/component/edify_test.cpp @@ -14,6 +14,7 @@ * limitations under the License. */ +#include <memory> #include <string> #include <gtest/gtest.h> @@ -21,7 +22,7 @@ #include "edify/expr.h" static void expect(const char* expr_str, const char* expected) { - Expr* e; + std::unique_ptr<Expr> e; int error_count = 0; EXPECT_EQ(0, parse_string(expr_str, &e, &error_count)); EXPECT_EQ(0, error_count); @@ -152,7 +153,7 @@ TEST_F(EdifyTest, big_string) { TEST_F(EdifyTest, unknown_function) { // unknown function const char* script1 = "unknown_function()"; - Expr* expr; + std::unique_ptr<Expr> expr; int error_count = 0; EXPECT_EQ(1, parse_string(script1, &expr, &error_count)); EXPECT_EQ(1, error_count); diff --git a/tests/component/updater_test.cpp b/tests/component/updater_test.cpp index 4f8349e2f..ef121a973 100644 --- a/tests/component/updater_test.cpp +++ b/tests/component/updater_test.cpp @@ -19,6 +19,7 @@ #include <sys/types.h> #include <unistd.h> +#include <memory> #include <string> #include <vector> @@ -46,7 +47,7 @@ struct selabel_handle *sehandle = nullptr; static void expect(const char* expected, const char* expr_str, CauseCode cause_code, UpdaterInfo* info = nullptr) { - Expr* e; + std::unique_ptr<Expr> e; int error_count = 0; ASSERT_EQ(0, parse_string(expr_str, &e, &error_count)); ASSERT_EQ(0, error_count); diff --git a/tests/unit/asn1_decoder_test.cpp b/tests/unit/asn1_decoder_test.cpp index 997639d8a..b334a655b 100644 --- a/tests/unit/asn1_decoder_test.cpp +++ b/tests/unit/asn1_decoder_test.cpp @@ -14,225 +14,188 @@ * limitations under the License. */ -#define LOG_TAG "asn1_decoder_test" +#include <stdint.h> + +#include <memory> -#include <cutils/log.h> #include <gtest/gtest.h> -#include <stdint.h> -#include <unistd.h> #include "asn1_decoder.h" -namespace android { - -class Asn1DecoderTest : public testing::Test { -}; - -TEST_F(Asn1DecoderTest, Empty_Failure) { - uint8_t empty[] = { }; - asn1_context_t* ctx = asn1_context_new(empty, sizeof(empty)); - - EXPECT_EQ(NULL, asn1_constructed_get(ctx)); - EXPECT_FALSE(asn1_constructed_skip_all(ctx)); - EXPECT_EQ(0, asn1_constructed_type(ctx)); - EXPECT_EQ(NULL, asn1_sequence_get(ctx)); - EXPECT_EQ(NULL, asn1_set_get(ctx)); - EXPECT_FALSE(asn1_sequence_next(ctx)); - - const uint8_t* junk; - size_t length; - EXPECT_FALSE(asn1_oid_get(ctx, &junk, &length)); - EXPECT_FALSE(asn1_octet_string_get(ctx, &junk, &length)); - - asn1_context_free(ctx); -} - -TEST_F(Asn1DecoderTest, ConstructedGet_TruncatedLength_Failure) { - uint8_t truncated[] = { 0xA0, 0x82, }; - asn1_context_t* ctx = asn1_context_new(truncated, sizeof(truncated)); - EXPECT_EQ(NULL, asn1_constructed_get(ctx)); - asn1_context_free(ctx); -} - -TEST_F(Asn1DecoderTest, ConstructedGet_LengthTooBig_Failure) { - uint8_t truncated[] = { 0xA0, 0x8a, 0xA5, 0x5A, 0xA5, 0x5A, - 0xA5, 0x5A, 0xA5, 0x5A, 0xA5, 0x5A, }; - asn1_context_t* ctx = asn1_context_new(truncated, sizeof(truncated)); - EXPECT_EQ(NULL, asn1_constructed_get(ctx)); - asn1_context_free(ctx); -} - -TEST_F(Asn1DecoderTest, ConstructedGet_TooSmallForChild_Failure) { - uint8_t data[] = { 0xA5, 0x02, 0x06, 0x01, 0x01, }; - asn1_context_t* ctx = asn1_context_new(data, sizeof(data)); - asn1_context_t* ptr = asn1_constructed_get(ctx); - ASSERT_NE((asn1_context_t*)NULL, ptr); - EXPECT_EQ(5, asn1_constructed_type(ptr)); - const uint8_t* oid; - size_t length; - EXPECT_FALSE(asn1_oid_get(ptr, &oid, &length)); - asn1_context_free(ptr); - asn1_context_free(ctx); -} - -TEST_F(Asn1DecoderTest, ConstructedGet_Success) { - uint8_t data[] = { 0xA5, 0x03, 0x06, 0x01, 0x01, }; - asn1_context_t* ctx = asn1_context_new(data, sizeof(data)); - asn1_context_t* ptr = asn1_constructed_get(ctx); - ASSERT_NE((asn1_context_t*)NULL, ptr); - EXPECT_EQ(5, asn1_constructed_type(ptr)); - const uint8_t* oid; - size_t length; - ASSERT_TRUE(asn1_oid_get(ptr, &oid, &length)); - EXPECT_EQ(1U, length); - EXPECT_EQ(0x01U, *oid); - asn1_context_free(ptr); - asn1_context_free(ctx); -} - -TEST_F(Asn1DecoderTest, ConstructedSkipAll_TruncatedLength_Failure) { - uint8_t truncated[] = { 0xA2, 0x82, }; - asn1_context_t* ctx = asn1_context_new(truncated, sizeof(truncated)); - EXPECT_FALSE(asn1_constructed_skip_all(ctx)); - asn1_context_free(ctx); -} - -TEST_F(Asn1DecoderTest, ConstructedSkipAll_Success) { - uint8_t data[] = { 0xA0, 0x03, 0x02, 0x01, 0x01, - 0xA1, 0x03, 0x02, 0x01, 0x01, - 0x06, 0x01, 0xA5, }; - asn1_context_t* ctx = asn1_context_new(data, sizeof(data)); - ASSERT_TRUE(asn1_constructed_skip_all(ctx)); - const uint8_t* oid; - size_t length; - ASSERT_TRUE(asn1_oid_get(ctx, &oid, &length)); - EXPECT_EQ(1U, length); - EXPECT_EQ(0xA5U, *oid); - asn1_context_free(ctx); -} - -TEST_F(Asn1DecoderTest, SequenceGet_TruncatedLength_Failure) { - uint8_t truncated[] = { 0x30, 0x82, }; - asn1_context_t* ctx = asn1_context_new(truncated, sizeof(truncated)); - EXPECT_EQ(NULL, asn1_sequence_get(ctx)); - asn1_context_free(ctx); -} - -TEST_F(Asn1DecoderTest, SequenceGet_TooSmallForChild_Failure) { - uint8_t data[] = { 0x30, 0x02, 0x06, 0x01, 0x01, }; - asn1_context_t* ctx = asn1_context_new(data, sizeof(data)); - asn1_context_t* ptr = asn1_sequence_get(ctx); - ASSERT_NE((asn1_context_t*)NULL, ptr); - const uint8_t* oid; - size_t length; - EXPECT_FALSE(asn1_oid_get(ptr, &oid, &length)); - asn1_context_free(ptr); - asn1_context_free(ctx); -} - -TEST_F(Asn1DecoderTest, SequenceGet_Success) { - uint8_t data[] = { 0x30, 0x03, 0x06, 0x01, 0x01, }; - asn1_context_t* ctx = asn1_context_new(data, sizeof(data)); - asn1_context_t* ptr = asn1_sequence_get(ctx); - ASSERT_NE((asn1_context_t*)NULL, ptr); - const uint8_t* oid; - size_t length; - ASSERT_TRUE(asn1_oid_get(ptr, &oid, &length)); - EXPECT_EQ(1U, length); - EXPECT_EQ(0x01U, *oid); - asn1_context_free(ptr); - asn1_context_free(ctx); -} - -TEST_F(Asn1DecoderTest, SetGet_TruncatedLength_Failure) { - uint8_t truncated[] = { 0x31, 0x82, }; - asn1_context_t* ctx = asn1_context_new(truncated, sizeof(truncated)); - EXPECT_EQ(NULL, asn1_set_get(ctx)); - asn1_context_free(ctx); -} - -TEST_F(Asn1DecoderTest, SetGet_TooSmallForChild_Failure) { - uint8_t data[] = { 0x31, 0x02, 0x06, 0x01, 0x01, }; - asn1_context_t* ctx = asn1_context_new(data, sizeof(data)); - asn1_context_t* ptr = asn1_set_get(ctx); - ASSERT_NE((asn1_context_t*)NULL, ptr); - const uint8_t* oid; - size_t length; - EXPECT_FALSE(asn1_oid_get(ptr, &oid, &length)); - asn1_context_free(ptr); - asn1_context_free(ctx); -} - -TEST_F(Asn1DecoderTest, SetGet_Success) { - uint8_t data[] = { 0x31, 0x03, 0x06, 0x01, 0xBA, }; - asn1_context_t* ctx = asn1_context_new(data, sizeof(data)); - asn1_context_t* ptr = asn1_set_get(ctx); - ASSERT_NE((asn1_context_t*)NULL, ptr); - const uint8_t* oid; - size_t length; - ASSERT_TRUE(asn1_oid_get(ptr, &oid, &length)); - EXPECT_EQ(1U, length); - EXPECT_EQ(0xBAU, *oid); - asn1_context_free(ptr); - asn1_context_free(ctx); -} - -TEST_F(Asn1DecoderTest, OidGet_LengthZero_Failure) { - uint8_t data[] = { 0x06, 0x00, 0x01, }; - asn1_context_t* ctx = asn1_context_new(data, sizeof(data)); - const uint8_t* oid; - size_t length; - EXPECT_FALSE(asn1_oid_get(ctx, &oid, &length)); - asn1_context_free(ctx); -} - -TEST_F(Asn1DecoderTest, OidGet_TooSmall_Failure) { - uint8_t data[] = { 0x06, 0x01, }; - asn1_context_t* ctx = asn1_context_new(data, sizeof(data)); - const uint8_t* oid; - size_t length; - EXPECT_FALSE(asn1_oid_get(ctx, &oid, &length)); - asn1_context_free(ctx); -} - -TEST_F(Asn1DecoderTest, OidGet_Success) { - uint8_t data[] = { 0x06, 0x01, 0x99, }; - asn1_context_t* ctx = asn1_context_new(data, sizeof(data)); - const uint8_t* oid; - size_t length; - ASSERT_TRUE(asn1_oid_get(ctx, &oid, &length)); - EXPECT_EQ(1U, length); - EXPECT_EQ(0x99U, *oid); - asn1_context_free(ctx); -} - -TEST_F(Asn1DecoderTest, OctetStringGet_LengthZero_Failure) { - uint8_t data[] = { 0x04, 0x00, 0x55, }; - asn1_context_t* ctx = asn1_context_new(data, sizeof(data)); - const uint8_t* string; - size_t length; - ASSERT_FALSE(asn1_octet_string_get(ctx, &string, &length)); - asn1_context_free(ctx); -} - -TEST_F(Asn1DecoderTest, OctetStringGet_TooSmall_Failure) { - uint8_t data[] = { 0x04, 0x01, }; - asn1_context_t* ctx = asn1_context_new(data, sizeof(data)); - const uint8_t* string; - size_t length; - ASSERT_FALSE(asn1_octet_string_get(ctx, &string, &length)); - asn1_context_free(ctx); -} - -TEST_F(Asn1DecoderTest, OctetStringGet_Success) { - uint8_t data[] = { 0x04, 0x01, 0xAA, }; - asn1_context_t* ctx = asn1_context_new(data, sizeof(data)); - const uint8_t* string; - size_t length; - ASSERT_TRUE(asn1_octet_string_get(ctx, &string, &length)); - EXPECT_EQ(1U, length); - EXPECT_EQ(0xAAU, *string); - asn1_context_free(ctx); -} - -} // namespace android +TEST(Asn1DecoderTest, Empty_Failure) { + uint8_t empty[] = {}; + asn1_context ctx(empty, sizeof(empty)); + + ASSERT_EQ(nullptr, ctx.asn1_constructed_get()); + ASSERT_FALSE(ctx.asn1_constructed_skip_all()); + ASSERT_EQ(0, ctx.asn1_constructed_type()); + ASSERT_EQ(nullptr, ctx.asn1_sequence_get()); + ASSERT_EQ(nullptr, ctx.asn1_set_get()); + ASSERT_FALSE(ctx.asn1_sequence_next()); + + const uint8_t* junk; + size_t length; + ASSERT_FALSE(ctx.asn1_oid_get(&junk, &length)); + ASSERT_FALSE(ctx.asn1_octet_string_get(&junk, &length)); +} + +TEST(Asn1DecoderTest, ConstructedGet_TruncatedLength_Failure) { + uint8_t truncated[] = { 0xA0, 0x82 }; + asn1_context ctx(truncated, sizeof(truncated)); + ASSERT_EQ(nullptr, ctx.asn1_constructed_get()); +} + +TEST(Asn1DecoderTest, ConstructedGet_LengthTooBig_Failure) { + uint8_t truncated[] = { 0xA0, 0x8a, 0xA5, 0x5A, 0xA5, 0x5A, 0xA5, 0x5A, 0xA5, 0x5A, 0xA5, 0x5A }; + asn1_context ctx(truncated, sizeof(truncated)); + ASSERT_EQ(nullptr, ctx.asn1_constructed_get()); +} + +TEST(Asn1DecoderTest, ConstructedGet_TooSmallForChild_Failure) { + uint8_t data[] = { 0xA5, 0x02, 0x06, 0x01, 0x01 }; + asn1_context ctx(data, sizeof(data)); + std::unique_ptr<asn1_context> ptr(ctx.asn1_constructed_get()); + ASSERT_NE(nullptr, ptr); + ASSERT_EQ(5, ptr->asn1_constructed_type()); + const uint8_t* oid; + size_t length; + ASSERT_FALSE(ptr->asn1_oid_get(&oid, &length)); +} + +TEST(Asn1DecoderTest, ConstructedGet_Success) { + uint8_t data[] = { 0xA5, 0x03, 0x06, 0x01, 0x01 }; + asn1_context ctx(data, sizeof(data)); + std::unique_ptr<asn1_context> ptr(ctx.asn1_constructed_get()); + ASSERT_NE(nullptr, ptr); + ASSERT_EQ(5, ptr->asn1_constructed_type()); + const uint8_t* oid; + size_t length; + ASSERT_TRUE(ptr->asn1_oid_get(&oid, &length)); + ASSERT_EQ(1U, length); + ASSERT_EQ(0x01U, *oid); +} + +TEST(Asn1DecoderTest, ConstructedSkipAll_TruncatedLength_Failure) { + uint8_t truncated[] = { 0xA2, 0x82 }; + asn1_context ctx(truncated, sizeof(truncated)); + ASSERT_FALSE(ctx.asn1_constructed_skip_all()); +} + +TEST(Asn1DecoderTest, ConstructedSkipAll_Success) { + uint8_t data[] = { 0xA0, 0x03, 0x02, 0x01, 0x01, 0xA1, 0x03, 0x02, 0x01, 0x01, 0x06, 0x01, 0xA5 }; + asn1_context ctx(data, sizeof(data)); + ASSERT_TRUE(ctx.asn1_constructed_skip_all()); + const uint8_t* oid; + size_t length; + ASSERT_TRUE(ctx.asn1_oid_get(&oid, &length)); + ASSERT_EQ(1U, length); + ASSERT_EQ(0xA5U, *oid); +} + +TEST(Asn1DecoderTest, SequenceGet_TruncatedLength_Failure) { + uint8_t truncated[] = { 0x30, 0x82 }; + asn1_context ctx(truncated, sizeof(truncated)); + ASSERT_EQ(nullptr, ctx.asn1_sequence_get()); +} + +TEST(Asn1DecoderTest, SequenceGet_TooSmallForChild_Failure) { + uint8_t data[] = { 0x30, 0x02, 0x06, 0x01, 0x01 }; + asn1_context ctx(data, sizeof(data)); + std::unique_ptr<asn1_context> ptr(ctx.asn1_sequence_get()); + ASSERT_NE(nullptr, ptr); + const uint8_t* oid; + size_t length; + ASSERT_FALSE(ptr->asn1_oid_get(&oid, &length)); +} + +TEST(Asn1DecoderTest, SequenceGet_Success) { + uint8_t data[] = { 0x30, 0x03, 0x06, 0x01, 0x01 }; + asn1_context ctx(data, sizeof(data)); + std::unique_ptr<asn1_context> ptr(ctx.asn1_sequence_get()); + ASSERT_NE(nullptr, ptr); + const uint8_t* oid; + size_t length; + ASSERT_TRUE(ptr->asn1_oid_get(&oid, &length)); + ASSERT_EQ(1U, length); + ASSERT_EQ(0x01U, *oid); +} + +TEST(Asn1DecoderTest, SetGet_TruncatedLength_Failure) { + uint8_t truncated[] = { 0x31, 0x82 }; + asn1_context ctx(truncated, sizeof(truncated)); + ASSERT_EQ(nullptr, ctx.asn1_set_get()); +} + +TEST(Asn1DecoderTest, SetGet_TooSmallForChild_Failure) { + uint8_t data[] = { 0x31, 0x02, 0x06, 0x01, 0x01 }; + asn1_context ctx(data, sizeof(data)); + std::unique_ptr<asn1_context> ptr(ctx.asn1_set_get()); + ASSERT_NE(nullptr, ptr); + const uint8_t* oid; + size_t length; + ASSERT_FALSE(ptr->asn1_oid_get(&oid, &length)); +} + +TEST(Asn1DecoderTest, SetGet_Success) { + uint8_t data[] = { 0x31, 0x03, 0x06, 0x01, 0xBA }; + asn1_context ctx(data, sizeof(data)); + std::unique_ptr<asn1_context> ptr(ctx.asn1_set_get()); + ASSERT_NE(nullptr, ptr); + const uint8_t* oid; + size_t length; + ASSERT_TRUE(ptr->asn1_oid_get(&oid, &length)); + ASSERT_EQ(1U, length); + ASSERT_EQ(0xBAU, *oid); +} + +TEST(Asn1DecoderTest, OidGet_LengthZero_Failure) { + uint8_t data[] = { 0x06, 0x00, 0x01 }; + asn1_context ctx(data, sizeof(data)); + const uint8_t* oid; + size_t length; + ASSERT_FALSE(ctx.asn1_oid_get(&oid, &length)); +} + +TEST(Asn1DecoderTest, OidGet_TooSmall_Failure) { + uint8_t data[] = { 0x06, 0x01 }; + asn1_context ctx(data, sizeof(data)); + const uint8_t* oid; + size_t length; + ASSERT_FALSE(ctx.asn1_oid_get(&oid, &length)); +} + +TEST(Asn1DecoderTest, OidGet_Success) { + uint8_t data[] = { 0x06, 0x01, 0x99 }; + asn1_context ctx(data, sizeof(data)); + const uint8_t* oid; + size_t length; + ASSERT_TRUE(ctx.asn1_oid_get(&oid, &length)); + ASSERT_EQ(1U, length); + ASSERT_EQ(0x99U, *oid); +} + +TEST(Asn1DecoderTest, OctetStringGet_LengthZero_Failure) { + uint8_t data[] = { 0x04, 0x00, 0x55 }; + asn1_context ctx(data, sizeof(data)); + const uint8_t* string; + size_t length; + ASSERT_FALSE(ctx.asn1_octet_string_get(&string, &length)); +} + +TEST(Asn1DecoderTest, OctetStringGet_TooSmall_Failure) { + uint8_t data[] = { 0x04, 0x01 }; + asn1_context ctx(data, sizeof(data)); + const uint8_t* string; + size_t length; + ASSERT_FALSE(ctx.asn1_octet_string_get(&string, &length)); +} + +TEST(Asn1DecoderTest, OctetStringGet_Success) { + uint8_t data[] = { 0x04, 0x01, 0xAA }; + asn1_context ctx(data, sizeof(data)); + const uint8_t* string; + size_t length; + ASSERT_TRUE(ctx.asn1_octet_string_get(&string, &length)); + ASSERT_EQ(1U, length); + ASSERT_EQ(0xAAU, *string); +} diff --git a/updater/blockimg.cpp b/updater/blockimg.cpp index 0fa83d9d5..efdfec19a 100644 --- a/updater/blockimg.cpp +++ b/updater/blockimg.cpp @@ -44,6 +44,7 @@ #include <android-base/unique_fd.h> #include <applypatch/applypatch.h> #include <openssl/sha.h> +#include <private/android_filesystem_config.h> #include <ziparchive/zip_archive.h> #include "edify/expr.h" @@ -772,6 +773,11 @@ static int WriteStash(const std::string& base, const std::string& id, int blocks return -1; } + if (fchown(fd, AID_SYSTEM, AID_SYSTEM) != 0) { // system user + PLOG(ERROR) << "failed to chown \"" << fn << "\""; + return -1; + } + if (write_all(fd, buffer, blocks * BLOCKSIZE) == -1) { return -1; } @@ -841,6 +847,12 @@ static int CreateStash(State* state, size_t maxblocks, const std::string& blockd return -1; } + if (chown(dirname.c_str(), AID_SYSTEM, AID_SYSTEM) != 0) { // system user + ErrorAbort(state, kStashCreationFailure, "chown \"%s\" failed: %s\n", dirname.c_str(), + strerror(errno)); + return -1; + } + if (CacheSizeCheck(max_stash_size) != 0) { ErrorAbort(state, kStashCreationFailure, "not enough space for stash (%zu needed)\n", max_stash_size); @@ -1458,8 +1470,9 @@ struct Command { // - new data stream (filename within package.zip) // - patch stream (filename within package.zip, must be uncompressed) -static Value* PerformBlockImageUpdate(const char* name, State* state, int /* argc */, Expr* argv[], - const Command* commands, size_t cmdcount, bool dryrun) { +static Value* PerformBlockImageUpdate(const char* name, State* state, + const std::vector<std::unique_ptr<Expr>>& argv, + const Command* commands, size_t cmdcount, bool dryrun) { CommandParameters params = {}; params.canwrite = !dryrun; @@ -1468,9 +1481,14 @@ static Value* PerformBlockImageUpdate(const char* name, State* state, int /* arg is_retry = true; LOG(INFO) << "This update is a retry."; } + if (argv.size() != 4) { + ErrorAbort(state, kArgsParsingFailure, "block_image_update expects 4 arguments, got %zu", + argv.size()); + return StringValue(""); + } std::vector<std::unique_ptr<Value>> args; - if (!ReadValueArgs(state, 4, argv, &args)) { + if (!ReadValueArgs(state, argv, &args)) { return nullptr; } @@ -1750,7 +1768,8 @@ pbiudone: // command has already been completed and verify the integrity of // the source data. -Value* BlockImageVerifyFn(const char* name, State* state, int argc, Expr* argv[]) { +Value* BlockImageVerifyFn(const char* name, State* state, + const std::vector<std::unique_ptr<Expr>>& argv) { // Commands which are not tested are set to nullptr to skip them completely const Command commands[] = { { "bsdiff", PerformCommandDiff }, @@ -1764,11 +1783,12 @@ Value* BlockImageVerifyFn(const char* name, State* state, int argc, Expr* argv[] }; // Perform a dry run without writing to test if an update can proceed - return PerformBlockImageUpdate(name, state, argc, argv, commands, + return PerformBlockImageUpdate(name, state, argv, commands, sizeof(commands) / sizeof(commands[0]), true); } -Value* BlockImageUpdateFn(const char* name, State* state, int argc, Expr* argv[]) { +Value* BlockImageUpdateFn(const char* name, State* state, + const std::vector<std::unique_ptr<Expr>>& argv) { const Command commands[] = { { "bsdiff", PerformCommandDiff }, { "erase", PerformCommandErase }, @@ -1780,13 +1800,19 @@ Value* BlockImageUpdateFn(const char* name, State* state, int argc, Expr* argv[] { "zero", PerformCommandZero } }; - return PerformBlockImageUpdate(name, state, argc, argv, commands, + return PerformBlockImageUpdate(name, state, argv, commands, sizeof(commands) / sizeof(commands[0]), false); } -Value* RangeSha1Fn(const char* name, State* state, int /* argc */, Expr* argv[]) { +Value* RangeSha1Fn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { + if (argv.size() != 2) { + ErrorAbort(state, kArgsParsingFailure, "range_sha1 expects 2 arguments, got %zu", + argv.size()); + return StringValue(""); + } + std::vector<std::unique_ptr<Value>> args; - if (!ReadValueArgs(state, 2, argv, &args)) { + if (!ReadValueArgs(state, argv, &args)) { return nullptr; } @@ -1844,9 +1870,16 @@ Value* RangeSha1Fn(const char* name, State* state, int /* argc */, Expr* argv[]) // 1st block of each partition and check for mounting time/count. It return string "t" // if executes successfully and an empty string otherwise. -Value* CheckFirstBlockFn(const char* name, State* state, int argc, Expr* argv[]) { +Value* CheckFirstBlockFn(const char* name, State* state, + const std::vector<std::unique_ptr<Expr>>& argv) { + if (argv.size() != 1) { + ErrorAbort(state, kArgsParsingFailure, "check_first_block expects 1 argument, got %zu", + argv.size()); + return StringValue(""); + } + std::vector<std::unique_ptr<Value>> args; - if (!ReadValueArgs(state, 1, argv, &args)) { + if (!ReadValueArgs(state, argv, &args)) { return nullptr; } @@ -1892,9 +1925,16 @@ Value* CheckFirstBlockFn(const char* name, State* state, int argc, Expr* argv[]) } -Value* BlockImageRecoverFn(const char* name, State* state, int argc, Expr* argv[]) { +Value* BlockImageRecoverFn(const char* name, State* state, + const std::vector<std::unique_ptr<Expr>>& argv) { + if (argv.size() != 2) { + ErrorAbort(state, kArgsParsingFailure, "block_image_recover expects 2 arguments, got %zu", + argv.size()); + return StringValue(""); + } + std::vector<std::unique_ptr<Value>> args; - if (!ReadValueArgs(state, 2, argv, &args)) { + if (!ReadValueArgs(state, argv, &args)) { return nullptr; } diff --git a/updater/install.cpp b/updater/install.cpp index 0963333fc..c9a0270ec 100644 --- a/updater/install.cpp +++ b/updater/install.cpp @@ -126,15 +126,16 @@ static bool make_parents(const std::string& name) { // mount(fs_type, partition_type, location, mount_point) // mount(fs_type, partition_type, location, mount_point, mount_options) -// + // fs_type="ext4" partition_type="EMMC" location=device -Value* MountFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc != 4 && argc != 5) { - return ErrorAbort(state, kArgsParsingFailure, "%s() expects 4-5 args, got %d", name, argc); +Value* MountFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { + if (argv.size() != 4 && argv.size() != 5) { + return ErrorAbort(state, kArgsParsingFailure, "%s() expects 4-5 args, got %zu", name, + argv.size()); } std::vector<std::string> args; - if (!ReadArgs(state, argc, argv, &args)) { + if (!ReadArgs(state, argv, &args)) { return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); } const std::string& fs_type = args[0]; @@ -143,7 +144,7 @@ Value* MountFn(const char* name, State* state, int argc, Expr* argv[]) { const std::string& mount_point = args[3]; std::string mount_options; - if (argc == 5) { + if (argv.size() == 5) { mount_options = args[4]; } @@ -188,15 +189,14 @@ Value* MountFn(const char* name, State* state, int argc, Expr* argv[]) { return StringValue(mount_point); } - // is_mounted(mount_point) -Value* IsMountedFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc != 1) { - return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %d", name, argc); +Value* IsMountedFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { + if (argv.size() != 1) { + return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %zu", name, argv.size()); } std::vector<std::string> args; - if (!ReadArgs(state, argc, argv, &args)) { + if (!ReadArgs(state, argv, &args)) { return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); } const std::string& mount_point = args[0]; @@ -214,12 +214,12 @@ Value* IsMountedFn(const char* name, State* state, int argc, Expr* argv[]) { return StringValue(mount_point); } -Value* UnmountFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc != 1) { - return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %d", name, argc); +Value* UnmountFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { + if (argv.size() != 1) { + return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %zu", name, argv.size()); } std::vector<std::string> args; - if (!ReadArgs(state, argc, argv, &args)) { + if (!ReadArgs(state, argv, &args)) { return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); } const std::string& mount_point = args[0]; @@ -265,13 +265,14 @@ static int exec_cmd(const char* path, char* const argv[]) { // if fs_size == 0, then make fs uses the entire partition. // if fs_size > 0, that is the size to use // if fs_size < 0, then reserve that many bytes at the end of the partition (not for "f2fs") -Value* FormatFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc != 5) { - return ErrorAbort(state, kArgsParsingFailure, "%s() expects 5 args, got %d", name, argc); +Value* FormatFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { + if (argv.size() != 5) { + return ErrorAbort(state, kArgsParsingFailure, "%s() expects 5 args, got %zu", name, + argv.size()); } std::vector<std::string> args; - if (!ReadArgs(state, argc, argv, &args)) { + if (!ReadArgs(state, argv, &args)) { return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); } const std::string& fs_type = args[0]; @@ -332,13 +333,15 @@ Value* FormatFn(const char* name, State* state, int argc, Expr* argv[]) { return nullptr; } -Value* ShowProgressFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc != 2) { - return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc); +Value* ShowProgressFn(const char* name, State* state, + const std::vector<std::unique_ptr<Expr>>& argv) { + if (argv.size() != 2) { + return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %zu", name, + argv.size()); } std::vector<std::string> args; - if (!ReadArgs(state, argc, argv, &args)) { + if (!ReadArgs(state, argv, &args)) { return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); } const std::string& frac_str = args[0]; @@ -361,13 +364,13 @@ Value* ShowProgressFn(const char* name, State* state, int argc, Expr* argv[]) { return StringValue(frac_str); } -Value* SetProgressFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc != 1) { - return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %d", name, argc); +Value* SetProgressFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { + if (argv.size() != 1) { + return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %zu", name, argv.size()); } std::vector<std::string> args; - if (!ReadArgs(state, 1, argv, &args)) { + if (!ReadArgs(state, argv, &args)) { return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); } const std::string& frac_str = args[0]; @@ -390,13 +393,15 @@ Value* SetProgressFn(const char* name, State* state, int argc, Expr* argv[]) { // Example: package_extract_dir("system", "/system") // // Note: package_dir needs to be a relative path; dest_dir needs to be an absolute path. -Value* PackageExtractDirFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc != 2) { - return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc); +Value* PackageExtractDirFn(const char* name, State* state, + const std::vector<std::unique_ptr<Expr>>&argv) { + if (argv.size() != 2) { + return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %zu", name, + argv.size()); } std::vector<std::string> args; - if (!ReadArgs(state, 2, argv, &args)) { + if (!ReadArgs(state, argv, &args)) { return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); } const std::string& zip_path = args[0]; @@ -416,17 +421,20 @@ Value* PackageExtractDirFn(const char* name, State* state, int argc, Expr* argv[ // Extracts a single package_file from the update package and writes it to dest_file, // overwriting existing files if necessary. Without the dest_file argument, returns the // contents of the package file as a binary blob. -Value* PackageExtractFileFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc < 1 || argc > 2) { - return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 or 2 args, got %d", name, argc); +Value* PackageExtractFileFn(const char* name, State* state, + const std::vector<std::unique_ptr<Expr>>& argv) { + if (argv.size() < 1 || argv.size() > 2) { + return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 or 2 args, got %zu", name, + argv.size()); } - if (argc == 2) { + if (argv.size() == 2) { // The two-argument version extracts to a file. std::vector<std::string> args; - if (!ReadArgs(state, 2, argv, &args)) { - return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse %d args", name, argc); + if (!ReadArgs(state, argv, &args)) { + return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse %zu args", name, + argv.size()); } const std::string& zip_path = args[0]; const std::string& dest_path = args[1]; @@ -468,8 +476,9 @@ Value* PackageExtractFileFn(const char* name, State* state, int argc, Expr* argv // The one-argument version returns the contents of the file as the result. std::vector<std::string> args; - if (!ReadArgs(state, 1, argv, &args)) { - return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse %d args", name, argc); + if (!ReadArgs(state, argv, &args)) { + return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse %zu args", name, + argv.size()); } const std::string& zip_path = args[0]; @@ -495,9 +504,9 @@ Value* PackageExtractFileFn(const char* name, State* state, int argc, Expr* argv } } -Value* GetPropFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc != 1) { - return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %d", name, argc); +Value* GetPropFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { + if (argv.size() != 1) { + return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %zu", name, argv.size()); } std::string key; if (!Evaluate(state, argv[0], &key)) { @@ -513,13 +522,14 @@ Value* GetPropFn(const char* name, State* state, int argc, Expr* argv[]) { // interprets 'file' as a getprop-style file (key=value pairs, one // per line. # comment lines, blank lines, lines without '=' ignored), // and returns the value for 'key' (or "" if it isn't defined). -Value* FileGetPropFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc != 2) { - return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc); +Value* FileGetPropFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { + if (argv.size() != 2) { + return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %zu", name, + argv.size()); } std::vector<std::string> args; - if (!ReadArgs(state, 2, argv, &args)) { + if (!ReadArgs(state, argv, &args)) { return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); } const std::string& filename = args[0]; @@ -578,9 +588,13 @@ Value* FileGetPropFn(const char* name, State* state, int argc, Expr* argv[]) { } // apply_patch_space(bytes) -Value* ApplyPatchSpaceFn(const char* name, State* state, int argc, Expr* argv[]) { +Value* ApplyPatchSpaceFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { + if (argv.size() != 1) { + return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 args, got %zu", name, + argv.size()); + } std::vector<std::string> args; - if (!ReadArgs(state, 1, argv, &args)) { + if (!ReadArgs(state, argv, &args)) { return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); } const std::string& bytes_str = args[0]; @@ -606,14 +620,14 @@ Value* ApplyPatchSpaceFn(const char* name, State* state, int argc, Expr* argv[]) // state. If the process is interrupted during patching, the target file may be in an intermediate // state; a copy exists in the cache partition so restarting the update can successfully update // the file. -Value* ApplyPatchFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc < 6 || (argc % 2) == 1) { +Value* ApplyPatchFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { + if (argv.size() < 6 || (argv.size() % 2) == 1) { return ErrorAbort(state, kArgsParsingFailure, "%s(): expected at least 6 args and an " - "even number, got %d", name, argc); + "even number, got %zu", name, argv.size()); } std::vector<std::string> args; - if (!ReadArgs(state, 4, argv, &args)) { + if (!ReadArgs(state, argv, &args, 0, 4)) { return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); } const std::string& source_filename = args[0]; @@ -627,9 +641,9 @@ Value* ApplyPatchFn(const char* name, State* state, int argc, Expr* argv[]) { name, target_size_str.c_str()); } - int patchcount = (argc-4) / 2; + int patchcount = (argv.size()-4) / 2; std::vector<std::unique_ptr<Value>> arg_values; - if (!ReadValueArgs(state, argc-4, argv+4, &arg_values)) { + if (!ReadValueArgs(state, argv, &arg_values, 4, argv.size() - 4)) { return nullptr; } @@ -664,20 +678,20 @@ Value* ApplyPatchFn(const char* name, State* state, int argc, Expr* argv[]) { // specified as 40 hex digits. This function differs from sha1_check(read_file(filename), // sha1 [, ...]) in that it knows to check the cache partition copy, so apply_patch_check() will // succeed even if the file was corrupted by an interrupted apply_patch() update. -Value* ApplyPatchCheckFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc < 1) { - return ErrorAbort(state, kArgsParsingFailure, "%s(): expected at least 1 arg, got %d", name, - argc); +Value* ApplyPatchCheckFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { + if (argv.size() < 1) { + return ErrorAbort(state, kArgsParsingFailure, "%s(): expected at least 1 arg, got %zu", name, + argv.size()); } std::vector<std::string> args; - if (!ReadArgs(state, 1, argv, &args)) { + if (!ReadArgs(state, argv, &args, 0, 1)) { return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); } const std::string& filename = args[0]; std::vector<std::string> sha1s; - if (!ReadArgs(state, argc - 1, argv + 1, &sha1s)) { + if (!ReadArgs(state, argv, &sha1s, 1, argv.size() - 1)) { return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); } int result = applypatch_check(filename.c_str(), sha1s); @@ -687,9 +701,9 @@ Value* ApplyPatchCheckFn(const char* name, State* state, int argc, Expr* argv[]) // This is the updater side handler for ui_print() in edify script. Contents // will be sent over to the recovery side for on-screen display. -Value* UIPrintFn(const char* name, State* state, int argc, Expr* argv[]) { +Value* UIPrintFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { std::vector<std::string> args; - if (!ReadArgs(state, argc, argv, &args)) { + if (!ReadArgs(state, argv, &args)) { return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); } @@ -698,31 +712,32 @@ Value* UIPrintFn(const char* name, State* state, int argc, Expr* argv[]) { return StringValue(buffer); } -Value* WipeCacheFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc != 0) { - return ErrorAbort(state, kArgsParsingFailure, "%s() expects no args, got %d", name, argc); +Value* WipeCacheFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { + if (!argv.empty()) { + return ErrorAbort(state, kArgsParsingFailure, "%s() expects no args, got %zu", name, + argv.size()); } fprintf(static_cast<UpdaterInfo*>(state->cookie)->cmd_pipe, "wipe_cache\n"); return StringValue("t"); } -Value* RunProgramFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc < 1) { +Value* RunProgramFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { + if (argv.size() < 1) { return ErrorAbort(state, kArgsParsingFailure, "%s() expects at least 1 arg", name); } std::vector<std::string> args; - if (!ReadArgs(state, argc, argv, &args)) { + if (!ReadArgs(state, argv, &args)) { return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); } - char* args2[argc + 1]; - for (int i = 0; i < argc; i++) { + char* args2[argv.size() + 1]; + for (size_t i = 0; i < argv.size(); i++) { args2[i] = &args[i][0]; } - args2[argc] = nullptr; + args2[argv.size()] = nullptr; - LOG(INFO) << "about to run program [" << args2[0] << "] with " << argc << " args"; + LOG(INFO) << "about to run program [" << args2[0] << "] with " << argv.size() << " args"; pid_t child = fork(); if (child == 0) { @@ -752,13 +767,13 @@ Value* RunProgramFn(const char* name, State* state, int argc, Expr* argv[]) { // returns the sha1 of the file if it matches any of the hex // strings passed, or "" if it does not equal any of them. // -Value* Sha1CheckFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc < 1) { +Value* Sha1CheckFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { + if (argv.size() < 1) { return ErrorAbort(state, kArgsParsingFailure, "%s() expects at least 1 arg", name); } std::vector<std::unique_ptr<Value>> args; - if (!ReadValueArgs(state, argc, argv, &args)) { + if (!ReadValueArgs(state, argv, &args)) { return nullptr; } @@ -768,11 +783,11 @@ Value* Sha1CheckFn(const char* name, State* state, int argc, Expr* argv[]) { uint8_t digest[SHA_DIGEST_LENGTH]; SHA1(reinterpret_cast<const uint8_t*>(args[0]->data.c_str()), args[0]->data.size(), digest); - if (argc == 1) { + if (argv.size() == 1) { return StringValue(print_sha1(digest)); } - for (int i = 1; i < argc; ++i) { + for (size_t i = 1; i < argv.size(); ++i) { uint8_t arg_digest[SHA_DIGEST_LENGTH]; if (args[i]->type != VAL_STRING) { LOG(ERROR) << name << "(): arg " << i << " is not a string; skipping"; @@ -791,13 +806,13 @@ Value* Sha1CheckFn(const char* name, State* state, int argc, Expr* argv[]) { // Read a local file and return its contents (the Value* returned // is actually a FileContents*). -Value* ReadFileFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc != 1) { - return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %d", name, argc); +Value* ReadFileFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { + if (argv.size() != 1) { + return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %zu", name, argv.size()); } std::vector<std::string> args; - if (!ReadArgs(state, 1, argv, &args)) { + if (!ReadArgs(state, argv, &args)) { return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); } const std::string& filename = args[0]; @@ -815,13 +830,14 @@ Value* ReadFileFn(const char* name, State* state, int argc, Expr* argv[]) { // write_value(value, filename) // Writes 'value' to 'filename'. // Example: write_value("960000", "/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq") -Value* WriteValueFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc != 2) { - return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc); +Value* WriteValueFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { + if (argv.size() != 2) { + return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %zu", name, + argv.size()); } std::vector<std::string> args; - if (!ReadArgs(state, 2, argv, &args)) { + if (!ReadArgs(state, argv, &args)) { return ErrorAbort(state, kArgsParsingFailure, "%s(): Failed to parse the argument(s)", name); } @@ -848,13 +864,14 @@ Value* WriteValueFn(const char* name, State* state, int argc, Expr* argv[]) { // property. It can be "recovery" to boot from the recovery // partition, or "" (empty string) to boot from the regular boot // partition. -Value* RebootNowFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc != 2) { - return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc); +Value* RebootNowFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { + if (argv.size() != 2) { + return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %zu", name, + argv.size()); } std::vector<std::string> args; - if (!ReadArgs(state, 2, argv, &args)) { + if (!ReadArgs(state, argv, &args)) { return ErrorAbort(state, kArgsParsingFailure, "%s(): Failed to parse the argument(s)", name); } const std::string& filename = args[0]; @@ -890,13 +907,14 @@ Value* RebootNowFn(const char* name, State* state, int argc, Expr* argv[]) { // ("/misc" in the fstab), which is where this value is stored. The // second argument is the string to store; it should not exceed 31 // bytes. -Value* SetStageFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc != 2) { - return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc); +Value* SetStageFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { + if (argv.size() != 2) { + return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %zu", name, + argv.size()); } std::vector<std::string> args; - if (!ReadArgs(state, 2, argv, &args)) { + if (!ReadArgs(state, argv, &args)) { return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); } const std::string& filename = args[0]; @@ -923,13 +941,13 @@ Value* SetStageFn(const char* name, State* state, int argc, Expr* argv[]) { // Return the value most recently saved with SetStageFn. The argument // is the block device for the misc partition. -Value* GetStageFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc != 1) { - return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %d", name, argc); +Value* GetStageFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { + if (argv.size() != 1) { + return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %zu", name, argv.size()); } std::vector<std::string> args; - if (!ReadArgs(state, 1, argv, &args)) { + if (!ReadArgs(state, argv, &args)) { return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); } const std::string& filename = args[0]; @@ -944,13 +962,14 @@ Value* GetStageFn(const char* name, State* state, int argc, Expr* argv[]) { return StringValue(boot.stage); } -Value* WipeBlockDeviceFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc != 2) { - return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc); +Value* WipeBlockDeviceFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { + if (argv.size() != 2) { + return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %zu", name, + argv.size()); } std::vector<std::string> args; - if (!ReadArgs(state, 2, argv, &args)) { + if (!ReadArgs(state, argv, &args)) { return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); } const std::string& filename = args[0]; @@ -967,38 +986,39 @@ Value* WipeBlockDeviceFn(const char* name, State* state, int argc, Expr* argv[]) return StringValue((status == 0) ? "t" : ""); } -Value* EnableRebootFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc != 0) { - return ErrorAbort(state, kArgsParsingFailure, "%s() expects no args, got %d", name, argc); +Value* EnableRebootFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { + if (!argv.empty()) { + return ErrorAbort(state, kArgsParsingFailure, "%s() expects no args, got %zu", name, + argv.size()); } UpdaterInfo* ui = static_cast<UpdaterInfo*>(state->cookie); fprintf(ui->cmd_pipe, "enable_reboot\n"); return StringValue("t"); } -Value* Tune2FsFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc == 0) { - return ErrorAbort(state, kArgsParsingFailure, "%s() expects args, got %d", name, argc); +Value* Tune2FsFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { + if (argv.empty()) { + return ErrorAbort(state, kArgsParsingFailure, "%s() expects args, got %zu", name, argv.size()); } std::vector<std::string> args; - if (!ReadArgs(state, argc, argv, &args)) { + if (!ReadArgs(state, argv, &args)) { return ErrorAbort(state, kArgsParsingFailure, "%s() could not read args", name); } - char* args2[argc + 1]; + char* args2[argv.size() + 1]; // Tune2fs expects the program name as its args[0] args2[0] = const_cast<char*>(name); if (args2[0] == nullptr) { return nullptr; } - for (int i = 0; i < argc; ++i) { + for (size_t i = 0; i < argv.size(); ++i) { args2[i + 1] = &args[i][0]; } // tune2fs changes the file system parameters on an ext2 file system; it // returns 0 on success. - int result = tune2fs_main(argc + 1, args2); + int result = tune2fs_main(argv.size() + 1, args2); if (result != 0) { return ErrorAbort(state, kTune2FsFailure, "%s() returned error code %d", name, result); } diff --git a/updater/updater.cpp b/updater/updater.cpp index 22c060fcb..0693cbd98 100644 --- a/updater/updater.cpp +++ b/updater/updater.cpp @@ -130,7 +130,7 @@ int main(int argc, char** argv) { // Parse the script. - Expr* root; + std::unique_ptr<Expr> root; int error_count = 0; int error = parse_string(script.c_str(), &root, &error_count); if (error != 0 || error_count > 0) { diff --git a/verifier.cpp b/verifier.cpp index 7f165860e..8be6da09f 100644 --- a/verifier.cpp +++ b/verifier.cpp @@ -66,48 +66,50 @@ static bool read_pkcs7(const uint8_t* pkcs7_der, size_t pkcs7_der_len, CHECK(sig_der != nullptr); sig_der->clear(); - asn1_context_t* ctx = asn1_context_new(pkcs7_der, pkcs7_der_len); - if (ctx == NULL) { + asn1_context ctx(pkcs7_der, pkcs7_der_len); + + std::unique_ptr<asn1_context> pkcs7_seq(ctx.asn1_sequence_get()); + if (pkcs7_seq == nullptr || !pkcs7_seq->asn1_sequence_next()) { return false; } - asn1_context_t* pkcs7_seq = asn1_sequence_get(ctx); - if (pkcs7_seq != NULL && asn1_sequence_next(pkcs7_seq)) { - asn1_context_t *signed_data_app = asn1_constructed_get(pkcs7_seq); - if (signed_data_app != NULL) { - asn1_context_t* signed_data_seq = asn1_sequence_get(signed_data_app); - if (signed_data_seq != NULL - && asn1_sequence_next(signed_data_seq) - && asn1_sequence_next(signed_data_seq) - && asn1_sequence_next(signed_data_seq) - && asn1_constructed_skip_all(signed_data_seq)) { - asn1_context_t *sig_set = asn1_set_get(signed_data_seq); - if (sig_set != NULL) { - asn1_context_t* sig_seq = asn1_sequence_get(sig_set); - if (sig_seq != NULL - && asn1_sequence_next(sig_seq) - && asn1_sequence_next(sig_seq) - && asn1_sequence_next(sig_seq) - && asn1_sequence_next(sig_seq)) { - const uint8_t* sig_der_ptr; - size_t sig_der_length; - if (asn1_octet_string_get(sig_seq, &sig_der_ptr, &sig_der_length)) { - sig_der->resize(sig_der_length); - std::copy(sig_der_ptr, sig_der_ptr + sig_der_length, sig_der->begin()); - } - asn1_context_free(sig_seq); - } - asn1_context_free(sig_set); - } - asn1_context_free(signed_data_seq); - } - asn1_context_free(signed_data_app); - } - asn1_context_free(pkcs7_seq); + std::unique_ptr<asn1_context> signed_data_app(pkcs7_seq->asn1_constructed_get()); + if (signed_data_app == nullptr) { + return false; + } + + std::unique_ptr<asn1_context> signed_data_seq(signed_data_app->asn1_sequence_get()); + if (signed_data_seq == nullptr || + !signed_data_seq->asn1_sequence_next() || + !signed_data_seq->asn1_sequence_next() || + !signed_data_seq->asn1_sequence_next() || + !signed_data_seq->asn1_constructed_skip_all()) { + return false; + } + + std::unique_ptr<asn1_context> sig_set(signed_data_seq->asn1_set_get()); + if (sig_set == nullptr) { + return false; + } + + std::unique_ptr<asn1_context> sig_seq(sig_set->asn1_sequence_get()); + if (sig_seq == nullptr || + !sig_seq->asn1_sequence_next() || + !sig_seq->asn1_sequence_next() || + !sig_seq->asn1_sequence_next() || + !sig_seq->asn1_sequence_next()) { + return false; + } + + const uint8_t* sig_der_ptr; + size_t sig_der_length; + if (!sig_seq->asn1_octet_string_get(&sig_der_ptr, &sig_der_length)) { + return false; } - asn1_context_free(ctx); - return !sig_der->empty(); + sig_der->resize(sig_der_length); + std::copy(sig_der_ptr, sig_der_ptr + sig_der_length, sig_der->begin()); + return true; } /* |