aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTianjie Xu2016-10-12 12:55:04 -0500
committerTianjie Xu2016-10-14 20:18:23 -0500
commitaced5d9e4e438ba478ce54f9217166b8ab7cc24f (patch)
treeb3bfca3430c25b7c35501497e0b8a0faf2251538
parentc5b4b719134a1d2d3b06a81f92a00b24e527248d (diff)
downloadplatform-bootable-recovery-aced5d9e4e438ba478ce54f9217166b8ab7cc24f.tar.gz
platform-bootable-recovery-aced5d9e4e438ba478ce54f9217166b8ab7cc24f.tar.xz
platform-bootable-recovery-aced5d9e4e438ba478ce54f9217166b8ab7cc24f.zip
Change StringValue to use std::string
Changing the field of 'Value' in edify to std::string from char*. Meanwhile cleaning up the users of 'Value' and switching them to cpp style. Test: compontent tests passed. Bug: 31713288 Change-Id: Iec5a7d601b1e4ca40935bf1c70d325dafecec235
-rw-r--r--applypatch/applypatch.cpp28
-rw-r--r--applypatch/bspatch.cpp12
-rw-r--r--applypatch/imgpatch.cpp44
-rw-r--r--applypatch/include/applypatch/applypatch.h10
-rw-r--r--applypatch/main.cpp42
-rw-r--r--applypatch/utils.cpp12
-rw-r--r--applypatch/utils.h6
-rw-r--r--edify/edify_parser.cpp6
-rw-r--r--edify/expr.cpp328
-rw-r--r--edify/expr.h44
-rw-r--r--tests/component/applypatch_test.cpp132
-rw-r--r--tests/component/edify_test.cpp8
-rw-r--r--tests/component/updater_test.cpp8
-rw-r--r--updater/blockimg.cpp154
-rw-r--r--updater/install.cpp191
-rw-r--r--updater/updater.cpp8
16 files changed, 505 insertions, 528 deletions
diff --git a/applypatch/applypatch.cpp b/applypatch/applypatch.cpp
index e52ef99d..cf155607 100644
--- a/applypatch/applypatch.cpp
+++ b/applypatch/applypatch.cpp
@@ -408,11 +408,10 @@ int ParseSha1(const char* str, uint8_t* digest) {
408// Search an array of sha1 strings for one matching the given sha1. 408// Search an array of sha1 strings for one matching the given sha1.
409// Return the index of the match on success, or -1 if no match is 409// Return the index of the match on success, or -1 if no match is
410// found. 410// found.
411int FindMatchingPatch(uint8_t* sha1, char* const * const patch_sha1_str, 411int FindMatchingPatch(uint8_t* sha1, const std::vector<std::string>& patch_sha1_str) {
412 int num_patches) { 412 for (size_t i = 0; i < patch_sha1_str.size(); ++i) {
413 uint8_t patch_sha1[SHA_DIGEST_LENGTH]; 413 uint8_t patch_sha1[SHA_DIGEST_LENGTH];
414 for (int i = 0; i < num_patches; ++i) { 414 if (ParseSha1(patch_sha1_str[i].c_str(), patch_sha1) == 0 &&
415 if (ParseSha1(patch_sha1_str[i], patch_sha1) == 0 &&
416 memcmp(patch_sha1, sha1, SHA_DIGEST_LENGTH) == 0) { 415 memcmp(patch_sha1, sha1, SHA_DIGEST_LENGTH) == 0) {
417 return i; 416 return i;
418 } 417 }
@@ -423,8 +422,7 @@ int FindMatchingPatch(uint8_t* sha1, char* const * const patch_sha1_str,
423// Returns 0 if the contents of the file (argv[2]) or the cached file 422// Returns 0 if the contents of the file (argv[2]) or the cached file
424// match any of the sha1's on the command line (argv[3:]). Returns 423// match any of the sha1's on the command line (argv[3:]). Returns
425// nonzero otherwise. 424// nonzero otherwise.
426int applypatch_check(const char* filename, int num_patches, 425int applypatch_check(const char* filename, const std::vector<std::string>& patch_sha1_str) {
427 char** const patch_sha1_str) {
428 FileContents file; 426 FileContents file;
429 427
430 // It's okay to specify no sha1s; the check will pass if the 428 // It's okay to specify no sha1s; the check will pass if the
@@ -432,8 +430,7 @@ int applypatch_check(const char* filename, int num_patches,
432 // partitions, where the filename encodes the sha1s; no need to 430 // partitions, where the filename encodes the sha1s; no need to
433 // check them twice.) 431 // check them twice.)
434 if (LoadFileContents(filename, &file) != 0 || 432 if (LoadFileContents(filename, &file) != 0 ||
435 (num_patches > 0 && 433 FindMatchingPatch(file.sha1, patch_sha1_str) < 0) {
436 FindMatchingPatch(file.sha1, patch_sha1_str, num_patches) < 0)) {
437 printf("file \"%s\" doesn't have any of expected " 434 printf("file \"%s\" doesn't have any of expected "
438 "sha1 sums; checking cache\n", filename); 435 "sha1 sums; checking cache\n", filename);
439 436
@@ -448,7 +445,7 @@ int applypatch_check(const char* filename, int num_patches,
448 return 1; 445 return 1;
449 } 446 }
450 447
451 if (FindMatchingPatch(file.sha1, patch_sha1_str, num_patches) < 0) { 448 if (FindMatchingPatch(file.sha1, patch_sha1_str) < 0) {
452 printf("cache bits don't match any sha1 for \"%s\"\n", filename); 449 printf("cache bits don't match any sha1 for \"%s\"\n", filename);
453 return 1; 450 return 1;
454 } 451 }
@@ -532,8 +529,7 @@ int applypatch(const char* source_filename,
532 const char* target_filename, 529 const char* target_filename,
533 const char* target_sha1_str, 530 const char* target_sha1_str,
534 size_t target_size, 531 size_t target_size,
535 int num_patches, 532 const std::vector<std::string>& patch_sha1_str,
536 char** const patch_sha1_str,
537 Value** patch_data, 533 Value** patch_data,
538 Value* bonus_data) { 534 Value* bonus_data) {
539 printf("patch %s: ", source_filename); 535 printf("patch %s: ", source_filename);
@@ -573,7 +569,7 @@ int applypatch(const char* source_filename,
573 } 569 }
574 570
575 if (!source_file.data.empty()) { 571 if (!source_file.data.empty()) {
576 int to_use = FindMatchingPatch(source_file.sha1, patch_sha1_str, num_patches); 572 int to_use = FindMatchingPatch(source_file.sha1, patch_sha1_str);
577 if (to_use >= 0) { 573 if (to_use >= 0) {
578 source_patch_value = patch_data[to_use]; 574 source_patch_value = patch_data[to_use];
579 } 575 }
@@ -589,7 +585,7 @@ int applypatch(const char* source_filename,
589 return 1; 585 return 1;
590 } 586 }
591 587
592 int to_use = FindMatchingPatch(copy_file.sha1, patch_sha1_str, num_patches); 588 int to_use = FindMatchingPatch(copy_file.sha1, patch_sha1_str);
593 if (to_use >= 0) { 589 if (to_use >= 0) {
594 copy_patch_value = patch_data[to_use]; 590 copy_patch_value = patch_data[to_use];
595 } 591 }
@@ -701,8 +697,8 @@ static int GenerateTarget(FileContents* source_file,
701 printf("patch is not a blob\n"); 697 printf("patch is not a blob\n");
702 return 1; 698 return 1;
703 } 699 }
704 char* header = patch->data; 700 const char* header = &patch->data[0];
705 ssize_t header_bytes_read = patch->size; 701 size_t header_bytes_read = patch->data.size();
706 bool use_bsdiff = false; 702 bool use_bsdiff = false;
707 if (header_bytes_read >= 8 && memcmp(header, "BSDIFF40", 8) == 0) { 703 if (header_bytes_read >= 8 && memcmp(header, "BSDIFF40", 8) == 0) {
708 use_bsdiff = true; 704 use_bsdiff = true;
diff --git a/applypatch/bspatch.cpp b/applypatch/bspatch.cpp
index a4945da2..eb45e9ce 100644
--- a/applypatch/bspatch.cpp
+++ b/applypatch/bspatch.cpp
@@ -64,7 +64,7 @@ void ShowBSDiffLicense() {
64 ); 64 );
65} 65}
66 66
67static off_t offtin(u_char *buf) 67static off_t offtin(const u_char *buf)
68{ 68{
69 off_t y; 69 off_t y;
70 70
@@ -130,7 +130,7 @@ int ApplyBSDiffPatchMem(const unsigned char* old_data, ssize_t old_size,
130 // from oldfile to x bytes from the diff block; copy y bytes from the 130 // from oldfile to x bytes from the diff block; copy y bytes from the
131 // extra block; seek forwards in oldfile by z bytes". 131 // extra block; seek forwards in oldfile by z bytes".
132 132
133 unsigned char* header = (unsigned char*) patch->data + patch_offset; 133 const unsigned char* header = reinterpret_cast<const unsigned char*>(&patch->data[patch_offset]);
134 if (memcmp(header, "BSDIFF40", 8) != 0) { 134 if (memcmp(header, "BSDIFF40", 8) != 0) {
135 printf("corrupt bsdiff patch file header (magic number)\n"); 135 printf("corrupt bsdiff patch file header (magic number)\n");
136 return 1; 136 return 1;
@@ -149,7 +149,7 @@ int ApplyBSDiffPatchMem(const unsigned char* old_data, ssize_t old_size,
149 int bzerr; 149 int bzerr;
150 150
151 bz_stream cstream; 151 bz_stream cstream;
152 cstream.next_in = patch->data + patch_offset + 32; 152 cstream.next_in = const_cast<char*>(&patch->data[patch_offset + 32]);
153 cstream.avail_in = ctrl_len; 153 cstream.avail_in = ctrl_len;
154 cstream.bzalloc = NULL; 154 cstream.bzalloc = NULL;
155 cstream.bzfree = NULL; 155 cstream.bzfree = NULL;
@@ -159,7 +159,7 @@ int ApplyBSDiffPatchMem(const unsigned char* old_data, ssize_t old_size,
159 } 159 }
160 160
161 bz_stream dstream; 161 bz_stream dstream;
162 dstream.next_in = patch->data + patch_offset + 32 + ctrl_len; 162 dstream.next_in = const_cast<char*>(&patch->data[patch_offset + 32 + ctrl_len]);
163 dstream.avail_in = data_len; 163 dstream.avail_in = data_len;
164 dstream.bzalloc = NULL; 164 dstream.bzalloc = NULL;
165 dstream.bzfree = NULL; 165 dstream.bzfree = NULL;
@@ -169,8 +169,8 @@ int ApplyBSDiffPatchMem(const unsigned char* old_data, ssize_t old_size,
169 } 169 }
170 170
171 bz_stream estream; 171 bz_stream estream;
172 estream.next_in = patch->data + patch_offset + 32 + ctrl_len + data_len; 172 estream.next_in = const_cast<char*>(&patch->data[patch_offset + 32 + ctrl_len + data_len]);
173 estream.avail_in = patch->size - (patch_offset + 32 + ctrl_len + data_len); 173 estream.avail_in = patch->data.size() - (patch_offset + 32 + ctrl_len + data_len);
174 estream.bzalloc = NULL; 174 estream.bzalloc = NULL;
175 estream.bzfree = NULL; 175 estream.bzfree = NULL;
176 estream.opaque = NULL; 176 estream.opaque = NULL;
diff --git a/applypatch/imgpatch.cpp b/applypatch/imgpatch.cpp
index 0c06d6b1..1c4409e3 100644
--- a/applypatch/imgpatch.cpp
+++ b/applypatch/imgpatch.cpp
@@ -24,6 +24,7 @@
24#include <unistd.h> 24#include <unistd.h>
25#include <string.h> 25#include <string.h>
26 26
27#include <string>
27#include <vector> 28#include <vector>
28 29
29#include "zlib.h" 30#include "zlib.h"
@@ -35,10 +36,10 @@
35int ApplyImagePatch(const unsigned char* old_data, ssize_t old_size, 36int ApplyImagePatch(const unsigned char* old_data, ssize_t old_size,
36 const unsigned char* patch_data, ssize_t patch_size, 37 const unsigned char* patch_data, ssize_t patch_size,
37 SinkFn sink, void* token) { 38 SinkFn sink, void* token) {
38 Value patch = {VAL_BLOB, patch_size, 39 Value patch(VAL_BLOB, std::string(
39 reinterpret_cast<char*>(const_cast<unsigned char*>(patch_data))}; 40 reinterpret_cast<const char*>(patch_data), patch_size));
40 return ApplyImagePatch( 41
41 old_data, old_size, &patch, sink, token, nullptr, nullptr); 42 return ApplyImagePatch(old_data, old_size, &patch, sink, token, nullptr, nullptr);
42} 43}
43 44
44/* 45/*
@@ -51,9 +52,7 @@ int ApplyImagePatch(const unsigned char* old_data, ssize_t old_size,
51 const Value* patch, 52 const Value* patch,
52 SinkFn sink, void* token, SHA_CTX* ctx, 53 SinkFn sink, void* token, SHA_CTX* ctx,
53 const Value* bonus_data) { 54 const Value* bonus_data) {
54 ssize_t pos = 12; 55 if (patch->data.size() < 12) {
55 char* header = patch->data;
56 if (patch->size < 12) {
57 printf("patch too short to contain header\n"); 56 printf("patch too short to contain header\n");
58 return -1; 57 return -1;
59 } 58 }
@@ -61,6 +60,8 @@ int ApplyImagePatch(const unsigned char* old_data, ssize_t old_size,
61 // IMGDIFF2 uses CHUNK_NORMAL, CHUNK_DEFLATE, and CHUNK_RAW. 60 // IMGDIFF2 uses CHUNK_NORMAL, CHUNK_DEFLATE, and CHUNK_RAW.
62 // (IMGDIFF1, which is no longer supported, used CHUNK_NORMAL and 61 // (IMGDIFF1, which is no longer supported, used CHUNK_NORMAL and
63 // CHUNK_GZIP.) 62 // CHUNK_GZIP.)
63 size_t pos = 12;
64 const char* header = &patch->data[0];
64 if (memcmp(header, "IMGDIFF2", 8) != 0) { 65 if (memcmp(header, "IMGDIFF2", 8) != 0) {
65 printf("corrupt patch file header (magic number)\n"); 66 printf("corrupt patch file header (magic number)\n");
66 return -1; 67 return -1;
@@ -68,20 +69,19 @@ int ApplyImagePatch(const unsigned char* old_data, ssize_t old_size,
68 69
69 int num_chunks = Read4(header+8); 70 int num_chunks = Read4(header+8);
70 71
71 int i; 72 for (int i = 0; i < num_chunks; ++i) {
72 for (i = 0; i < num_chunks; ++i) {
73 // each chunk's header record starts with 4 bytes. 73 // each chunk's header record starts with 4 bytes.
74 if (pos + 4 > patch->size) { 74 if (pos + 4 > patch->data.size()) {
75 printf("failed to read chunk %d record\n", i); 75 printf("failed to read chunk %d record\n", i);
76 return -1; 76 return -1;
77 } 77 }
78 int type = Read4(patch->data + pos); 78 int type = Read4(&patch->data[pos]);
79 pos += 4; 79 pos += 4;
80 80
81 if (type == CHUNK_NORMAL) { 81 if (type == CHUNK_NORMAL) {
82 char* normal_header = patch->data + pos; 82 const char* normal_header = &patch->data[pos];
83 pos += 24; 83 pos += 24;
84 if (pos > patch->size) { 84 if (pos > patch->data.size()) {
85 printf("failed to read chunk %d normal header data\n", i); 85 printf("failed to read chunk %d normal header data\n", i);
86 return -1; 86 return -1;
87 } 87 }
@@ -97,21 +97,21 @@ int ApplyImagePatch(const unsigned char* old_data, ssize_t old_size,
97 ApplyBSDiffPatch(old_data + src_start, src_len, 97 ApplyBSDiffPatch(old_data + src_start, src_len,
98 patch, patch_offset, sink, token, ctx); 98 patch, patch_offset, sink, token, ctx);
99 } else if (type == CHUNK_RAW) { 99 } else if (type == CHUNK_RAW) {
100 char* raw_header = patch->data + pos; 100 const char* raw_header = &patch->data[pos];
101 pos += 4; 101 pos += 4;
102 if (pos > patch->size) { 102 if (pos > patch->data.size()) {
103 printf("failed to read chunk %d raw header data\n", i); 103 printf("failed to read chunk %d raw header data\n", i);
104 return -1; 104 return -1;
105 } 105 }
106 106
107 ssize_t data_len = Read4(raw_header); 107 ssize_t data_len = Read4(raw_header);
108 108
109 if (pos + data_len > patch->size) { 109 if (pos + data_len > patch->data.size()) {
110 printf("failed to read chunk %d raw data\n", i); 110 printf("failed to read chunk %d raw data\n", i);
111 return -1; 111 return -1;
112 } 112 }
113 if (ctx) SHA1_Update(ctx, patch->data + pos, data_len); 113 if (ctx) SHA1_Update(ctx, &patch->data[pos], data_len);
114 if (sink((unsigned char*)patch->data + pos, 114 if (sink(reinterpret_cast<const unsigned char*>(&patch->data[pos]),
115 data_len, token) != data_len) { 115 data_len, token) != data_len) {
116 printf("failed to write chunk %d raw data\n", i); 116 printf("failed to write chunk %d raw data\n", i);
117 return -1; 117 return -1;
@@ -119,9 +119,9 @@ int ApplyImagePatch(const unsigned char* old_data, ssize_t old_size,
119 pos += data_len; 119 pos += data_len;
120 } else if (type == CHUNK_DEFLATE) { 120 } else if (type == CHUNK_DEFLATE) {
121 // deflate chunks have an additional 60 bytes in their chunk header. 121 // deflate chunks have an additional 60 bytes in their chunk header.
122 char* deflate_header = patch->data + pos; 122 const char* deflate_header = &patch->data[pos];
123 pos += 60; 123 pos += 60;
124 if (pos > patch->size) { 124 if (pos > patch->data.size()) {
125 printf("failed to read chunk %d deflate header data\n", i); 125 printf("failed to read chunk %d deflate header data\n", i);
126 return -1; 126 return -1;
127 } 127 }
@@ -149,7 +149,7 @@ int ApplyImagePatch(const unsigned char* old_data, ssize_t old_size,
149 // the patch was constructed with bonus data. The 149 // the patch was constructed with bonus data. The
150 // deflation will come up 'bonus_size' bytes short; these 150 // deflation will come up 'bonus_size' bytes short; these
151 // must be appended from the bonus_data value. 151 // must be appended from the bonus_data value.
152 size_t bonus_size = (i == 1 && bonus_data != NULL) ? bonus_data->size : 0; 152 size_t bonus_size = (i == 1 && bonus_data != NULL) ? bonus_data->data.size() : 0;
153 153
154 std::vector<unsigned char> expanded_source(expanded_len); 154 std::vector<unsigned char> expanded_source(expanded_len);
155 155
@@ -189,7 +189,7 @@ int ApplyImagePatch(const unsigned char* old_data, ssize_t old_size,
189 189
190 if (bonus_size) { 190 if (bonus_size) {
191 memcpy(expanded_source.data() + (expanded_len - bonus_size), 191 memcpy(expanded_source.data() + (expanded_len - bonus_size),
192 bonus_data->data, bonus_size); 192 &bonus_data->data[0], bonus_size);
193 } 193 }
194 } 194 }
195 195
diff --git a/applypatch/include/applypatch/applypatch.h b/applypatch/include/applypatch/applypatch.h
index 9ee39d29..80d68163 100644
--- a/applypatch/include/applypatch/applypatch.h
+++ b/applypatch/include/applypatch/applypatch.h
@@ -20,6 +20,7 @@
20#include <stdint.h> 20#include <stdint.h>
21#include <sys/stat.h> 21#include <sys/stat.h>
22 22
23#include <string>
23#include <vector> 24#include <vector>
24 25
25#include "openssl/sha.h" 26#include "openssl/sha.h"
@@ -52,19 +53,16 @@ int applypatch(const char* source_filename,
52 const char* target_filename, 53 const char* target_filename,
53 const char* target_sha1_str, 54 const char* target_sha1_str,
54 size_t target_size, 55 size_t target_size,
55 int num_patches, 56 const std::vector<std::string>& patch_sha1_str,
56 char** const patch_sha1_str,
57 Value** patch_data, 57 Value** patch_data,
58 Value* bonus_data); 58 Value* bonus_data);
59int applypatch_check(const char* filename, 59int applypatch_check(const char* filename,
60 int num_patches, 60 const std::vector<std::string>& patch_sha1_str);
61 char** const patch_sha1_str);
62 61
63int LoadFileContents(const char* filename, FileContents* file); 62int LoadFileContents(const char* filename, FileContents* file);
64int SaveFileContents(const char* filename, const FileContents* file); 63int SaveFileContents(const char* filename, const FileContents* file);
65void FreeFileContents(FileContents* file); 64void FreeFileContents(FileContents* file);
66int FindMatchingPatch(uint8_t* sha1, char* const * const patch_sha1_str, 65int FindMatchingPatch(uint8_t* sha1, const std::vector<std::string>& patch_sha1_str);
67 int num_patches);
68 66
69// bsdiff.cpp 67// bsdiff.cpp
70void ShowBSDiffLicense(); 68void ShowBSDiffLicense();
diff --git a/applypatch/main.cpp b/applypatch/main.cpp
index 1968ae48..a3a45d06 100644
--- a/applypatch/main.cpp
+++ b/applypatch/main.cpp
@@ -20,6 +20,7 @@
20#include <unistd.h> 20#include <unistd.h>
21 21
22#include <memory> 22#include <memory>
23#include <string>
23#include <vector> 24#include <vector>
24 25
25#include "applypatch/applypatch.h" 26#include "applypatch/applypatch.h"
@@ -30,7 +31,12 @@ static int CheckMode(int argc, char** argv) {
30 if (argc < 3) { 31 if (argc < 3) {
31 return 2; 32 return 2;
32 } 33 }
33 return applypatch_check(argv[2], argc-3, argv+3); 34 std::vector<std::string> sha1;
35 for (int i = 3; i < argc; i++) {
36 sha1.push_back(argv[i]);
37 }
38
39 return applypatch_check(argv[2], sha1);
34} 40}
35 41
36static int SpaceMode(int argc, char** argv) { 42static int SpaceMode(int argc, char** argv) {
@@ -49,11 +55,13 @@ static int SpaceMode(int argc, char** argv) {
49// Parse arguments (which should be of the form "<sha1>:<filename>" 55// Parse arguments (which should be of the form "<sha1>:<filename>"
50// into the new parallel arrays *sha1s and *files.Returns true on 56// into the new parallel arrays *sha1s and *files.Returns true on
51// success. 57// success.
52static bool ParsePatchArgs(int argc, char** argv, std::vector<char*>* sha1s, 58static bool ParsePatchArgs(int argc, char** argv, std::vector<std::string>* sha1s,
53 std::vector<FileContents>* files) { 59 std::vector<FileContents>* files) {
54 uint8_t digest[SHA_DIGEST_LENGTH]; 60 if (sha1s == nullptr) {
55 61 return false;
62 }
56 for (int i = 0; i < argc; ++i) { 63 for (int i = 0; i < argc; ++i) {
64 uint8_t digest[SHA_DIGEST_LENGTH];
57 char* colon = strchr(argv[i], ':'); 65 char* colon = strchr(argv[i], ':');
58 if (colon == nullptr) { 66 if (colon == nullptr) {
59 printf("no ':' in patch argument \"%s\"\n", argv[i]); 67 printf("no ':' in patch argument \"%s\"\n", argv[i]);
@@ -83,18 +91,15 @@ static int FlashMode(const char* src_filename, const char* tgt_filename,
83 91
84static int PatchMode(int argc, char** argv) { 92static int PatchMode(int argc, char** argv) {
85 FileContents bonusFc; 93 FileContents bonusFc;
86 Value bonusValue; 94 Value bonus(VAL_INVALID, "");
87 Value* bonus = nullptr;
88 95
89 if (argc >= 3 && strcmp(argv[1], "-b") == 0) { 96 if (argc >= 3 && strcmp(argv[1], "-b") == 0) {
90 if (LoadFileContents(argv[2], &bonusFc) != 0) { 97 if (LoadFileContents(argv[2], &bonusFc) != 0) {
91 printf("failed to load bonus file %s\n", argv[2]); 98 printf("failed to load bonus file %s\n", argv[2]);
92 return 1; 99 return 1;
93 } 100 }
94 bonus = &bonusValue; 101 bonus.type = VAL_BLOB;
95 bonus->type = VAL_BLOB; 102 bonus.data = reinterpret_cast<const char*>(bonusFc.data.data());
96 bonus->size = bonusFc.data.size();
97 bonus->data = reinterpret_cast<char*>(bonusFc.data.data());
98 argc -= 2; 103 argc -= 2;
99 argv += 2; 104 argv += 2;
100 } 105 }
@@ -112,29 +117,26 @@ static int PatchMode(int argc, char** argv) {
112 117
113 // If no <src-sha1>:<patch> is provided, it is in flash mode. 118 // If no <src-sha1>:<patch> is provided, it is in flash mode.
114 if (argc == 5) { 119 if (argc == 5) {
115 if (bonus != nullptr) { 120 if (bonus.type != VAL_INVALID) {
116 printf("bonus file not supported in flash mode\n"); 121 printf("bonus file not supported in flash mode\n");
117 return 1; 122 return 1;
118 } 123 }
119 return FlashMode(argv[1], argv[2], argv[3], target_size); 124 return FlashMode(argv[1], argv[2], argv[3], target_size);
120 } 125 }
121 std::vector<char*> sha1s; 126 std::vector<std::string> sha1s;
122 std::vector<FileContents> files; 127 std::vector<FileContents> files;
123 if (!ParsePatchArgs(argc-5, argv+5, &sha1s, &files)) { 128 if (!ParsePatchArgs(argc-5, argv+5, &sha1s, &files)) {
124 printf("failed to parse patch args\n"); 129 printf("failed to parse patch args\n");
125 return 1; 130 return 1;
126 } 131 }
127 std::vector<Value> patches(files.size()); 132 std::vector<Value> patches;
128 std::vector<Value*> patch_ptrs(files.size()); 133 std::vector<Value*> patch_ptrs;
129 for (size_t i = 0; i < files.size(); ++i) { 134 for (size_t i = 0; i < files.size(); ++i) {
130 patches[i].type = VAL_BLOB; 135 patches.push_back(Value(VAL_BLOB, reinterpret_cast<const char*>(files[i].data.data())));
131 patches[i].size = files[i].data.size(); 136 patch_ptrs.push_back(&patches[i]);
132 patches[i].data = reinterpret_cast<char*>(files[i].data.data());
133 patch_ptrs[i] = &patches[i];
134 } 137 }
135 return applypatch(argv[1], argv[2], argv[3], target_size, 138 return applypatch(argv[1], argv[2], argv[3], target_size,
136 patch_ptrs.size(), sha1s.data(), 139 sha1s, patch_ptrs.data(), &bonus);
137 patch_ptrs.data(), bonus);
138} 140}
139 141
140// This program applies binary patches to files in a way that is safe 142// This program applies binary patches to files in a way that is safe
diff --git a/applypatch/utils.cpp b/applypatch/utils.cpp
index fef250f0..450dc8d7 100644
--- a/applypatch/utils.cpp
+++ b/applypatch/utils.cpp
@@ -38,22 +38,22 @@ void Write8(int64_t value, FILE* f) {
38 fputc((value >> 56) & 0xff, f); 38 fputc((value >> 56) & 0xff, f);
39} 39}
40 40
41int Read2(void* pv) { 41int Read2(const void* pv) {
42 unsigned char* p = reinterpret_cast<unsigned char*>(pv); 42 const unsigned char* p = reinterpret_cast<const unsigned char*>(pv);
43 return (int)(((unsigned int)p[1] << 8) | 43 return (int)(((unsigned int)p[1] << 8) |
44 (unsigned int)p[0]); 44 (unsigned int)p[0]);
45} 45}
46 46
47int Read4(void* pv) { 47int Read4(const void* pv) {
48 unsigned char* p = reinterpret_cast<unsigned char*>(pv); 48 const unsigned char* p = reinterpret_cast<const unsigned char*>(pv);
49 return (int)(((unsigned int)p[3] << 24) | 49 return (int)(((unsigned int)p[3] << 24) |
50 ((unsigned int)p[2] << 16) | 50 ((unsigned int)p[2] << 16) |
51 ((unsigned int)p[1] << 8) | 51 ((unsigned int)p[1] << 8) |
52 (unsigned int)p[0]); 52 (unsigned int)p[0]);
53} 53}
54 54
55int64_t Read8(void* pv) { 55int64_t Read8(const void* pv) {
56 unsigned char* p = reinterpret_cast<unsigned char*>(pv); 56 const unsigned char* p = reinterpret_cast<const unsigned char*>(pv);
57 return (int64_t)(((uint64_t)p[7] << 56) | 57 return (int64_t)(((uint64_t)p[7] << 56) |
58 ((uint64_t)p[6] << 48) | 58 ((uint64_t)p[6] << 48) |
59 ((uint64_t)p[5] << 40) | 59 ((uint64_t)p[5] << 40) |
diff --git a/applypatch/utils.h b/applypatch/utils.h
index 1c34edd9..c7c8e90e 100644
--- a/applypatch/utils.h
+++ b/applypatch/utils.h
@@ -24,8 +24,8 @@
24 24
25void Write4(int value, FILE* f); 25void Write4(int value, FILE* f);
26void Write8(int64_t value, FILE* f); 26void Write8(int64_t value, FILE* f);
27int Read2(void* p); 27int Read2(const void* p);
28int Read4(void* p); 28int Read4(const void* p);
29int64_t Read8(void* p); 29int64_t Read8(const void* p);
30 30
31#endif // _BUILD_TOOLS_APPLYPATCH_UTILS_H 31#endif // _BUILD_TOOLS_APPLYPATCH_UTILS_H
diff --git a/edify/edify_parser.cpp b/edify/edify_parser.cpp
index 1b89cf21..908fcf13 100644
--- a/edify/edify_parser.cpp
+++ b/edify/edify_parser.cpp
@@ -66,12 +66,12 @@ int main(int argc, char** argv) {
66 ExprDump(0, root, buffer); 66 ExprDump(0, root, buffer);
67 67
68 State state(buffer, nullptr); 68 State state(buffer, nullptr);
69 char* result = Evaluate(&state, root); 69 std::string result;
70 if (result == NULL) { 70 if (!Evaluate(&state, root, &result)) {
71 printf("result was NULL, message is: %s\n", 71 printf("result was NULL, message is: %s\n",
72 (state.errmsg.empty() ? "(NULL)" : state.errmsg.c_str())); 72 (state.errmsg.empty() ? "(NULL)" : state.errmsg.c_str()));
73 } else { 73 } else {
74 printf("result is [%s]\n", result); 74 printf("result is [%s]\n", result.c_str());
75 } 75 }
76 } 76 }
77 return 0; 77 return 0;
diff --git a/edify/expr.cpp b/edify/expr.cpp
index 4000bc4d..ec240975 100644
--- a/edify/expr.cpp
+++ b/edify/expr.cpp
@@ -22,184 +22,164 @@
22#include <string.h> 22#include <string.h>
23#include <unistd.h> 23#include <unistd.h>
24 24
25#include <memory>
25#include <string> 26#include <string>
26#include <unordered_map> 27#include <unordered_map>
28#include <vector>
27 29
30#include <android-base/parseint.h>
28#include <android-base/stringprintf.h> 31#include <android-base/stringprintf.h>
29#include <android-base/strings.h> 32#include <android-base/strings.h>
30 33
31// Functions should: 34// Functions should:
32// 35//
33// - return a malloc()'d string 36// - return a malloc()'d string
34// - if Evaluate() on any argument returns NULL, return NULL. 37// - if Evaluate() on any argument returns nullptr, return nullptr.
35 38
36int BooleanString(const char* s) { 39static bool BooleanString(const std::string& s) {
37 return s[0] != '\0'; 40 return !s.empty();
38} 41}
39 42
40char* Evaluate(State* state, Expr* expr) { 43bool Evaluate(State* state, Expr* expr, std::string* result) {
41 Value* v = expr->fn(expr->name, state, expr->argc, expr->argv); 44 if (result == nullptr) {
42 if (v == NULL) return NULL; 45 return false;
46 }
47
48 std::unique_ptr<Value> v(expr->fn(expr->name, state, expr->argc, expr->argv));
49 if (!v) {
50 return false;
51 }
43 if (v->type != VAL_STRING) { 52 if (v->type != VAL_STRING) {
44 ErrorAbort(state, kArgsParsingFailure, "expecting string, got value type %d", v->type); 53 ErrorAbort(state, kArgsParsingFailure, "expecting string, got value type %d", v->type);
45 FreeValue(v); 54 return false;
46 return NULL;
47 } 55 }
48 char* result = v->data; 56
49 free(v); 57 *result = v->data;
50 return result; 58 return true;
51} 59}
52 60
53Value* EvaluateValue(State* state, Expr* expr) { 61Value* EvaluateValue(State* state, Expr* expr) {
54 return expr->fn(expr->name, state, expr->argc, expr->argv); 62 return expr->fn(expr->name, state, expr->argc, expr->argv);
55} 63}
56 64
57Value* StringValue(char* str) { 65Value* StringValue(const char* str) {
58 if (str == NULL) return NULL; 66 if (str == nullptr) {
59 Value* v = reinterpret_cast<Value*>(malloc(sizeof(Value))); 67 return nullptr;
60 v->type = VAL_STRING; 68 }
61 v->size = strlen(str); 69 return new Value(VAL_STRING, str);
62 v->data = str;
63 return v;
64} 70}
65 71
66void FreeValue(Value* v) { 72Value* StringValue(const std::string& str) {
67 if (v == NULL) return; 73 return StringValue(str.c_str());
68 free(v->data);
69 free(v);
70} 74}
71 75
72Value* ConcatFn(const char* name, State* state, int argc, Expr* argv[]) { 76Value* ConcatFn(const char* name, State* state, int argc, Expr* argv[]) {
73 if (argc == 0) { 77 if (argc == 0) {
74 return StringValue(strdup("")); 78 return StringValue("");
75 } 79 }
76 char** strings = reinterpret_cast<char**>(malloc(argc * sizeof(char*))); 80 std::string result;
77 int i; 81 for (int i = 0; i < argc; ++i) {
78 for (i = 0; i < argc; ++i) { 82 std::string str;
79 strings[i] = NULL; 83 if (!Evaluate(state, argv[i], &str)) {
80 } 84 return nullptr;
81 char* result = NULL;
82 int length = 0;
83 for (i = 0; i < argc; ++i) {
84 strings[i] = Evaluate(state, argv[i]);
85 if (strings[i] == NULL) {
86 goto done;
87 } 85 }
88 length += strlen(strings[i]); 86 result += str;
89 } 87 }
90 88
91 result = reinterpret_cast<char*>(malloc(length+1));
92 int p;
93 p = 0;
94 for (i = 0; i < argc; ++i) {
95 strcpy(result+p, strings[i]);
96 p += strlen(strings[i]);
97 }
98 result[p] = '\0';
99
100 done:
101 for (i = 0; i < argc; ++i) {
102 free(strings[i]);
103 }
104 free(strings);
105 return StringValue(result); 89 return StringValue(result);
106} 90}
107 91
108Value* IfElseFn(const char* name, State* state, int argc, Expr* argv[]) { 92Value* IfElseFn(const char* name, State* state, int argc, Expr* argv[]) {
109 if (argc != 2 && argc != 3) { 93 if (argc != 2 && argc != 3) {
110 state->errmsg = "ifelse expects 2 or 3 arguments"; 94 state->errmsg = "ifelse expects 2 or 3 arguments";
111 return NULL; 95 return nullptr;
112 } 96 }
113 char* cond = Evaluate(state, argv[0]); 97
114 if (cond == NULL) { 98 std::string cond;
115 return NULL; 99 if (!Evaluate(state, argv[0], &cond)) {
100 return nullptr;
116 } 101 }
117 102
118 if (BooleanString(cond) == true) { 103 if (!cond.empty()) {
119 free(cond);
120 return EvaluateValue(state, argv[1]); 104 return EvaluateValue(state, argv[1]);
121 } else { 105 } else if (argc == 3) {
122 if (argc == 3) { 106 return EvaluateValue(state, argv[2]);
123 free(cond);
124 return EvaluateValue(state, argv[2]);
125 } else {
126 return StringValue(cond);
127 }
128 } 107 }
108
109 return StringValue("");
129} 110}
130 111
131Value* AbortFn(const char* name, State* state, int argc, Expr* argv[]) { 112Value* AbortFn(const char* name, State* state, int argc, Expr* argv[]) {
132 char* msg = NULL; 113 std::string msg;
133 if (argc > 0) { 114 if (argc > 0 && Evaluate(state, argv[0], &msg)) {
134 msg = Evaluate(state, argv[0]);
135 }
136 if (msg) {
137 state->errmsg = msg; 115 state->errmsg = msg;
138 } else { 116 } else {
139 state->errmsg = "called abort()"; 117 state->errmsg = "called abort()";
140 } 118 }
141 return NULL; 119 return nullptr;
142} 120}
143 121
144Value* AssertFn(const char* name, State* state, int argc, Expr* argv[]) { 122Value* AssertFn(const char* name, State* state, int argc, Expr* argv[]) {
145 int i; 123 for (int i = 0; i < argc; ++i) {
146 for (i = 0; i < argc; ++i) { 124 std::string result;
147 char* v = Evaluate(state, argv[i]); 125 if (!Evaluate(state, argv[i], &result)) {
148 if (v == NULL) { 126 return nullptr;
149 return NULL;
150 } 127 }
151 int b = BooleanString(v); 128 if (result.empty()) {
152 free(v);
153 if (!b) {
154 int len = argv[i]->end - argv[i]->start; 129 int len = argv[i]->end - argv[i]->start;
155 state->errmsg = "assert failed: " + state->script.substr(argv[i]->start, len); 130 state->errmsg = "assert failed: " + state->script.substr(argv[i]->start, len);
156 return NULL; 131 return nullptr;
157 } 132 }
158 } 133 }
159 return StringValue(strdup("")); 134 return StringValue("");
160} 135}
161 136
162Value* SleepFn(const char* name, State* state, int argc, Expr* argv[]) { 137Value* SleepFn(const char* name, State* state, int argc, Expr* argv[]) {
163 char* val = Evaluate(state, argv[0]); 138 std::string val;
164 if (val == NULL) { 139 if (!Evaluate(state, argv[0], &val)) {
165 return NULL; 140 return nullptr;
141 }
142
143 int v;
144 if (!android::base::ParseInt(val.c_str(), &v, 0)) {
145 return nullptr;
166 } 146 }
167 int v = strtol(val, NULL, 10);
168 sleep(v); 147 sleep(v);
148
169 return StringValue(val); 149 return StringValue(val);
170} 150}
171 151
172Value* StdoutFn(const char* name, State* state, int argc, Expr* argv[]) { 152Value* StdoutFn(const char* name, State* state, int argc, Expr* argv[]) {
173 int i; 153 for (int i = 0; i < argc; ++i) {
174 for (i = 0; i < argc; ++i) { 154 std::string v;
175 char* v = Evaluate(state, argv[i]); 155 if (!Evaluate(state, argv[i], &v)) {
176 if (v == NULL) { 156 return nullptr;
177 return NULL;
178 } 157 }
179 fputs(v, stdout); 158 fputs(v.c_str(), stdout);
180 free(v);
181 } 159 }
182 return StringValue(strdup("")); 160 return StringValue("");
183} 161}
184 162
185Value* LogicalAndFn(const char* name, State* state, 163Value* LogicalAndFn(const char* name, State* state,
186 int argc, Expr* argv[]) { 164 int argc, Expr* argv[]) {
187 char* left = Evaluate(state, argv[0]); 165 std::string left;
188 if (left == NULL) return NULL; 166 if (!Evaluate(state, argv[0], &left)) {
189 if (BooleanString(left) == true) { 167 return nullptr;
190 free(left); 168 }
169 if (BooleanString(left)) {
191 return EvaluateValue(state, argv[1]); 170 return EvaluateValue(state, argv[1]);
192 } else { 171 } else {
193 return StringValue(left); 172 return StringValue("");
194 } 173 }
195} 174}
196 175
197Value* LogicalOrFn(const char* name, State* state, 176Value* LogicalOrFn(const char* name, State* state,
198 int argc, Expr* argv[]) { 177 int argc, Expr* argv[]) {
199 char* left = Evaluate(state, argv[0]); 178 std::string left;
200 if (left == NULL) return NULL; 179 if (!Evaluate(state, argv[0], &left)) {
201 if (BooleanString(left) == false) { 180 return nullptr;
202 free(left); 181 }
182 if (!BooleanString(left)) {
203 return EvaluateValue(state, argv[1]); 183 return EvaluateValue(state, argv[1]);
204 } else { 184 } else {
205 return StringValue(left); 185 return StringValue(left);
@@ -208,75 +188,75 @@ Value* LogicalOrFn(const char* name, State* state,
208 188
209Value* LogicalNotFn(const char* name, State* state, 189Value* LogicalNotFn(const char* name, State* state,
210 int argc, Expr* argv[]) { 190 int argc, Expr* argv[]) {
211 char* val = Evaluate(state, argv[0]); 191 std::string val;
212 if (val == NULL) return NULL; 192 if (!Evaluate(state, argv[0], &val)) {
213 bool bv = BooleanString(val); 193 return nullptr;
214 free(val); 194 }
215 return StringValue(strdup(bv ? "" : "t")); 195
196 return StringValue(BooleanString(val) ? "" : "t");
216} 197}
217 198
218Value* SubstringFn(const char* name, State* state, 199Value* SubstringFn(const char* name, State* state,
219 int argc, Expr* argv[]) { 200 int argc, Expr* argv[]) {
220 char* needle = Evaluate(state, argv[0]); 201 std::string needle;
221 if (needle == NULL) return NULL; 202 if (!Evaluate(state, argv[0], &needle)) {
222 char* haystack = Evaluate(state, argv[1]); 203 return nullptr;
223 if (haystack == NULL) { 204 }
224 free(needle); 205
225 return NULL; 206 std::string haystack;
207 if (!Evaluate(state, argv[1], &haystack)) {
208 return nullptr;
226 } 209 }
227 210
228 char* result = strdup(strstr(haystack, needle) ? "t" : ""); 211 std::string result = (haystack.find(needle) != std::string::npos) ? "t" : "";
229 free(needle);
230 free(haystack);
231 return StringValue(result); 212 return StringValue(result);
232} 213}
233 214
234Value* EqualityFn(const char* name, State* state, int argc, Expr* argv[]) { 215Value* EqualityFn(const char* name, State* state, int argc, Expr* argv[]) {
235 char* left = Evaluate(state, argv[0]); 216 std::string left;
236 if (left == NULL) return NULL; 217 if (!Evaluate(state, argv[0], &left)) {
237 char* right = Evaluate(state, argv[1]); 218 return nullptr;
238 if (right == NULL) { 219 }
239 free(left); 220 std::string right;
240 return NULL; 221 if (!Evaluate(state, argv[1], &right)) {
222 return nullptr;
241 } 223 }
242 224
243 char* result = strdup(strcmp(left, right) == 0 ? "t" : ""); 225 const char* result = (left == right) ? "t" : "";
244 free(left);
245 free(right);
246 return StringValue(result); 226 return StringValue(result);
247} 227}
248 228
249Value* InequalityFn(const char* name, State* state, int argc, Expr* argv[]) { 229Value* InequalityFn(const char* name, State* state, int argc, Expr* argv[]) {
250 char* left = Evaluate(state, argv[0]); 230 std::string left;
251 if (left == NULL) return NULL; 231 if (!Evaluate(state, argv[0], &left)) {
252 char* right = Evaluate(state, argv[1]); 232 return nullptr;
253 if (right == NULL) { 233 }
254 free(left); 234 std::string right;
255 return NULL; 235 if (!Evaluate(state, argv[1], &right)) {
236 return nullptr;
256 } 237 }
257 238
258 char* result = strdup(strcmp(left, right) != 0 ? "t" : ""); 239 const char* result = (left != right) ? "t" : "";
259 free(left);
260 free(right);
261 return StringValue(result); 240 return StringValue(result);
262} 241}
263 242
264Value* SequenceFn(const char* name, State* state, int argc, Expr* argv[]) { 243Value* SequenceFn(const char* name, State* state, int argc, Expr* argv[]) {
265 Value* left = EvaluateValue(state, argv[0]); 244 std::unique_ptr<Value> left(EvaluateValue(state, argv[0]));
266 if (left == NULL) return NULL; 245 if (!left) {
267 FreeValue(left); 246 return nullptr;
247 }
268 return EvaluateValue(state, argv[1]); 248 return EvaluateValue(state, argv[1]);
269} 249}
270 250
271Value* LessThanIntFn(const char* name, State* state, int argc, Expr* argv[]) { 251Value* LessThanIntFn(const char* name, State* state, int argc, Expr* argv[]) {
272 if (argc != 2) { 252 if (argc != 2) {
273 state->errmsg = "less_than_int expects 2 arguments"; 253 state->errmsg = "less_than_int expects 2 arguments";
274 return NULL; 254 return nullptr;
275 } 255 }
276 256
277 char* left; 257 char* left;
278 char* right; 258 char* right;
279 if (ReadArgs(state, argv, 2, &left, &right) < 0) return NULL; 259 if (ReadArgs(state, argv, 2, &left, &right) < 0) return nullptr;
280 260
281 bool result = false; 261 bool result = false;
282 char* end; 262 char* end;
@@ -298,14 +278,14 @@ Value* LessThanIntFn(const char* name, State* state, int argc, Expr* argv[]) {
298 done: 278 done:
299 free(left); 279 free(left);
300 free(right); 280 free(right);
301 return StringValue(strdup(result ? "t" : "")); 281 return StringValue(result ? "t" : "");
302} 282}
303 283
304Value* GreaterThanIntFn(const char* name, State* state, 284Value* GreaterThanIntFn(const char* name, State* state,
305 int argc, Expr* argv[]) { 285 int argc, Expr* argv[]) {
306 if (argc != 2) { 286 if (argc != 2) {
307 state->errmsg = "greater_than_int expects 2 arguments"; 287 state->errmsg = "greater_than_int expects 2 arguments";
308 return NULL; 288 return nullptr;
309 } 289 }
310 290
311 Expr* temp[2]; 291 Expr* temp[2];
@@ -316,7 +296,7 @@ Value* GreaterThanIntFn(const char* name, State* state,
316} 296}
317 297
318Value* Literal(const char* name, State* state, int argc, Expr* argv[]) { 298Value* Literal(const char* name, State* state, int argc, Expr* argv[]) {
319 return StringValue(strdup(name)); 299 return StringValue(name);
320} 300}
321 301
322// ----------------------------------------------------------------- 302// -----------------------------------------------------------------
@@ -355,6 +335,43 @@ void RegisterBuiltins() {
355// convenience methods for functions 335// convenience methods for functions
356// ----------------------------------------------------------------- 336// -----------------------------------------------------------------
357 337
338// Evaluate the expressions in argv, and put the results of strings in
339// args. If any expression evaluates to nullptr, free the rest and return
340// false. Return true on success.
341bool ReadArgs(State* state, int argc, Expr* argv[], std::vector<std::string>* args) {
342 if (args == nullptr) {
343 return false;
344 }
345 for (int i = 0; i < argc; ++i) {
346 std::string var;
347 if (!Evaluate(state, argv[i], &var)) {
348 args->clear();
349 return false;
350 }
351 args->push_back(var);
352 }
353 return true;
354}
355
356// Evaluate the expressions in argv, and put the results of Value* in
357// args. If any expression evaluate to nullptr, free the rest and return
358// false. Return true on success.
359bool ReadValueArgs(State* state, int argc, Expr* argv[],
360 std::vector<std::unique_ptr<Value>>* args) {
361 if (args == nullptr) {
362 return false;
363 }
364 for (int i = 0; i < argc; ++i) {
365 std::unique_ptr<Value> v(EvaluateValue(state, argv[i]));
366 if (!v) {
367 args->clear();
368 return false;
369 }
370 args->push_back(std::move(v));
371 }
372 return true;
373}
374
358// Evaluate the expressions in argv, giving 'count' char* (the ... is 375// Evaluate the expressions in argv, giving 'count' char* (the ... is
359// zero or more char** to put them in). If any expression evaluates 376// zero or more char** to put them in). If any expression evaluates
360// to NULL, free the rest and return -1. Return 0 on success. 377// to NULL, free the rest and return -1. Return 0 on success.
@@ -364,8 +381,9 @@ int ReadArgs(State* state, Expr* argv[], int count, ...) {
364 va_start(v, count); 381 va_start(v, count);
365 int i; 382 int i;
366 for (i = 0; i < count; ++i) { 383 for (i = 0; i < count; ++i) {
367 args[i] = Evaluate(state, argv[i]); 384 std::string str;
368 if (args[i] == NULL) { 385 if (!Evaluate(state, argv[i], &str) ||
386 (args[i] = strdup(str.c_str())) == nullptr) {
369 va_end(v); 387 va_end(v);
370 int j; 388 int j;
371 for (j = 0; j < i; ++j) { 389 for (j = 0; j < i; ++j) {
@@ -385,25 +403,24 @@ int ReadArgs(State* state, Expr* argv[], int count, ...) {
385// zero or more Value** to put them in). If any expression evaluates 403// zero or more Value** to put them in). If any expression evaluates
386// to NULL, free the rest and return -1. Return 0 on success. 404// to NULL, free the rest and return -1. Return 0 on success.
387int ReadValueArgs(State* state, Expr* argv[], int count, ...) { 405int ReadValueArgs(State* state, Expr* argv[], int count, ...) {
388 Value** args = reinterpret_cast<Value**>(malloc(count * sizeof(Value*))); 406 Value** args = new Value*[count];
389 va_list v; 407 va_list v;
390 va_start(v, count); 408 va_start(v, count);
391 int i; 409 for (int i = 0; i < count; ++i) {
392 for (i = 0; i < count; ++i) {
393 args[i] = EvaluateValue(state, argv[i]); 410 args[i] = EvaluateValue(state, argv[i]);
394 if (args[i] == NULL) { 411 if (args[i] == NULL) {
395 va_end(v); 412 va_end(v);
396 int j; 413 int j;
397 for (j = 0; j < i; ++j) { 414 for (j = 0; j < i; ++j) {
398 FreeValue(args[j]); 415 delete args[j];
399 } 416 }
400 free(args); 417 delete[] args;
401 return -1; 418 return -1;
402 } 419 }
403 *(va_arg(v, Value**)) = args[i]; 420 *(va_arg(v, Value**)) = args[i];
404 } 421 }
405 va_end(v); 422 va_end(v);
406 free(args); 423 delete[] args;
407 return 0; 424 return 0;
408} 425}
409 426
@@ -413,12 +430,11 @@ int ReadValueArgs(State* state, Expr* argv[], int count, ...) {
413// strings it contains. 430// strings it contains.
414char** ReadVarArgs(State* state, int argc, Expr* argv[]) { 431char** ReadVarArgs(State* state, int argc, Expr* argv[]) {
415 char** args = (char**)malloc(argc * sizeof(char*)); 432 char** args = (char**)malloc(argc * sizeof(char*));
416 int i = 0; 433 for (int i = 0; i < argc; ++i) {
417 for (i = 0; i < argc; ++i) { 434 std::string str;
418 args[i] = Evaluate(state, argv[i]); 435 if (!Evaluate(state, argv[i], &str) ||
419 if (args[i] == NULL) { 436 (args[i] = strdup(str.c_str())) == nullptr) {
420 int j; 437 for (int j = 0; j < i; ++j) {
421 for (j = 0; j < i; ++j) {
422 free(args[j]); 438 free(args[j]);
423 } 439 }
424 free(args); 440 free(args);
@@ -433,16 +449,16 @@ char** ReadVarArgs(State* state, int argc, Expr* argv[]) {
433// The caller is responsible for freeing the returned array and the 449// The caller is responsible for freeing the returned array and the
434// Values it contains. 450// Values it contains.
435Value** ReadValueVarArgs(State* state, int argc, Expr* argv[]) { 451Value** ReadValueVarArgs(State* state, int argc, Expr* argv[]) {
436 Value** args = (Value**)malloc(argc * sizeof(Value*)); 452 Value** args = new Value*[argc];
437 int i = 0; 453 int i = 0;
438 for (i = 0; i < argc; ++i) { 454 for (i = 0; i < argc; ++i) {
439 args[i] = EvaluateValue(state, argv[i]); 455 args[i] = EvaluateValue(state, argv[i]);
440 if (args[i] == NULL) { 456 if (args[i] == NULL) {
441 int j; 457 int j;
442 for (j = 0; j < i; ++j) { 458 for (j = 0; j < i; ++j) {
443 FreeValue(args[j]); 459 delete args[j];
444 } 460 }
445 free(args); 461 delete[] args;
446 return NULL; 462 return NULL;
447 } 463 }
448 } 464 }
diff --git a/edify/expr.h b/edify/expr.h
index cd6139a1..85306542 100644
--- a/edify/expr.h
+++ b/edify/expr.h
@@ -48,13 +48,19 @@ struct State {
48 bool is_retry = false; 48 bool is_retry = false;
49}; 49};
50 50
51#define VAL_STRING 1 // data will be NULL-terminated; size doesn't count null 51enum ValueType {
52#define VAL_BLOB 2 52 VAL_INVALID = -1,
53 VAL_STRING = 1,
54 VAL_BLOB = 2,
55};
53 56
54struct Value { 57struct Value {
55 int type; 58 ValueType type;
56 ssize_t size; 59 std::string data;
57 char* data; 60
61 Value(ValueType type, const std::string& str) :
62 type(type),
63 data(str) {}
58}; 64};
59 65
60struct Expr; 66struct Expr;
@@ -75,11 +81,11 @@ struct Expr {
75Value* EvaluateValue(State* state, Expr* expr); 81Value* EvaluateValue(State* state, Expr* expr);
76 82
77// Take one of the Expr*s passed to the function as an argument, 83// Take one of the Expr*s passed to the function as an argument,
78// evaluate it, assert that it is a string, and return the resulting 84// evaluate it, assert that it is a string, and update the result
79// char*. The caller takes ownership of the returned char*. This is 85// parameter. This function returns true if the evaluation succeeds.
80// a convenience function for older functions that want to deal only 86// This is a convenience function for older functions that want to
81// with strings. 87// deal only with strings.
82char* Evaluate(State* state, Expr* expr); 88bool Evaluate(State* state, Expr* expr, std::string* result);
83 89
84// Glue to make an Expr out of a literal. 90// Glue to make an Expr out of a literal.
85Value* Literal(const char* name, State* state, int argc, Expr* argv[]); 91Value* Literal(const char* name, State* state, int argc, Expr* argv[]);
@@ -114,6 +120,17 @@ Function FindFunction(const std::string& name);
114 120
115// --- convenience functions for use in functions --- 121// --- convenience functions for use in functions ---
116 122
123// Evaluate the expressions in argv, and put the results of strings in
124// args. If any expression evaluates to nullptr, free the rest and return
125// false. Return true on success.
126bool ReadArgs(State* state, int argc, Expr* argv[], std::vector<std::string>* args);
127
128// Evaluate the expressions in argv, and put the results of Value* in
129// args. If any expression evaluate to nullptr, free the rest and return
130// false. Return true on success.
131bool ReadValueArgs(State* state, int argc, Expr* argv[],
132 std::vector<std::unique_ptr<Value>>* args);
133
117// Evaluate the expressions in argv, giving 'count' char* (the ... is 134// Evaluate the expressions in argv, giving 'count' char* (the ... is
118// zero or more char** to put them in). If any expression evaluates 135// zero or more char** to put them in). If any expression evaluates
119// to NULL, free the rest and return -1. Return 0 on success. 136// to NULL, free the rest and return -1. Return 0 on success.
@@ -146,11 +163,10 @@ Value* ErrorAbort(State* state, const char* format, ...)
146Value* ErrorAbort(State* state, CauseCode cause_code, const char* format, ...) 163Value* ErrorAbort(State* state, CauseCode cause_code, const char* format, ...)
147 __attribute__((format(printf, 3, 4))); 164 __attribute__((format(printf, 3, 4)));
148 165
149// Wrap a string into a Value, taking ownership of the string. 166// Copying the string into a Value.
150Value* StringValue(char* str); 167Value* StringValue(const char* str);
151 168
152// Free a Value object. 169Value* StringValue(const std::string& str);
153void FreeValue(Value* v);
154 170
155int parse_string(const char* str, Expr** root, int* error_count); 171int parse_string(const char* str, Expr** root, int* error_count);
156 172
diff --git a/tests/component/applypatch_test.cpp b/tests/component/applypatch_test.cpp
index 2f7cb02f..75f2e101 100644
--- a/tests/component/applypatch_test.cpp
+++ b/tests/component/applypatch_test.cpp
@@ -153,25 +153,16 @@ class ApplyPatchFullTest : public ApplyPatchCacheTest {
153 struct FileContents fc; 153 struct FileContents fc;
154 154
155 ASSERT_EQ(0, LoadFileContents(&rand_file[0], &fc)); 155 ASSERT_EQ(0, LoadFileContents(&rand_file[0], &fc));
156 Value* patch1 = new Value(); 156 Value* patch1 = new Value(VAL_BLOB, std::string(fc.data.begin(), fc.data.end()));
157 patch1->type = VAL_BLOB;
158 patch1->size = fc.data.size();
159 patch1->data = static_cast<char*>(malloc(fc.data.size()));
160 memcpy(patch1->data, fc.data.data(), fc.data.size());
161 patches.push_back(patch1); 157 patches.push_back(patch1);
162 158
163 ASSERT_EQ(0, LoadFileContents(&patch_file[0], &fc)); 159 ASSERT_EQ(0, LoadFileContents(&patch_file[0], &fc));
164 Value* patch2 = new Value(); 160 Value* patch2 = new Value(VAL_BLOB, std::string(fc.data.begin(), fc.data.end()));
165 patch2->type = VAL_BLOB;
166 patch2->size = fc.st.st_size;
167 patch2->data = static_cast<char*>(malloc(fc.data.size()));
168 memcpy(patch2->data, fc.data.data(), fc.data.size());
169 patches.push_back(patch2); 161 patches.push_back(patch2);
170 } 162 }
171 static void TearDownTestCase() { 163 static void TearDownTestCase() {
172 delete output_f; 164 delete output_f;
173 for (auto it = patches.begin(); it != patches.end(); ++it) { 165 for (auto it = patches.begin(); it != patches.end(); ++it) {
174 free((*it)->data);
175 delete *it; 166 delete *it;
176 } 167 }
177 patches.clear(); 168 patches.clear();
@@ -210,88 +201,87 @@ TemporaryFile* ApplyPatchFullTest::output_f;
210std::string ApplyPatchFullTest::output_loc; 201std::string ApplyPatchFullTest::output_loc;
211 202
212TEST_F(ApplyPatchTest, CheckModeSingle) { 203TEST_F(ApplyPatchTest, CheckModeSingle) {
213 char* s = &old_sha1[0]; 204 std::vector<std::string> sha1s = { old_sha1 };
214 ASSERT_EQ(0, applypatch_check(&old_file[0], 1, &s)); 205 ASSERT_EQ(0, applypatch_check(&old_file[0], sha1s));
215} 206}
216 207
217TEST_F(ApplyPatchTest, CheckModeMultiple) { 208TEST_F(ApplyPatchTest, CheckModeMultiple) {
218 char* argv[3] = { 209 std::vector<std::string> sha1s = {
219 &bad_sha1_a[0], 210 bad_sha1_a,
220 &old_sha1[0], 211 old_sha1,
221 &bad_sha1_b[0] 212 bad_sha1_b
222 }; 213 };
223 ASSERT_EQ(0, applypatch_check(&old_file[0], 3, argv)); 214 ASSERT_EQ(0, applypatch_check(&old_file[0], sha1s));
224} 215}
225 216
226TEST_F(ApplyPatchTest, CheckModeFailure) { 217TEST_F(ApplyPatchTest, CheckModeFailure) {
227 char* argv[2] = { 218 std::vector<std::string> sha1s = {
228 &bad_sha1_a[0], 219 bad_sha1_a,
229 &bad_sha1_b[0] 220 bad_sha1_b
230 }; 221 };
231 ASSERT_NE(0, applypatch_check(&old_file[0], 2, argv)); 222 ASSERT_NE(0, applypatch_check(&old_file[0], sha1s));
232} 223}
233 224
234TEST_F(ApplyPatchCacheTest, CheckCacheCorruptedSingle) { 225TEST_F(ApplyPatchCacheTest, CheckCacheCorruptedSingle) {
235 mangle_file(old_file); 226 mangle_file(old_file);
236 char* s = &old_sha1[0]; 227 std::vector<std::string> sha1s = { old_sha1 };
237 ASSERT_EQ(0, applypatch_check(&old_file[0], 1, &s)); 228 ASSERT_EQ(0, applypatch_check(&old_file[0], sha1s));
238} 229}
239 230
240TEST_F(ApplyPatchCacheTest, CheckCacheCorruptedMultiple) { 231TEST_F(ApplyPatchCacheTest, CheckCacheCorruptedMultiple) {
241 mangle_file(old_file); 232 mangle_file(old_file);
242 char* argv[3] = { 233 std::vector<std::string> sha1s = {
243 &bad_sha1_a[0], 234 bad_sha1_a,
244 &old_sha1[0], 235 old_sha1,
245 &bad_sha1_b[0] 236 bad_sha1_b
246 }; 237 };
247 ASSERT_EQ(0, applypatch_check(&old_file[0], 3, argv)); 238 ASSERT_EQ(0, applypatch_check(&old_file[0], sha1s));
248} 239}
249 240
250TEST_F(ApplyPatchCacheTest, CheckCacheCorruptedFailure) { 241TEST_F(ApplyPatchCacheTest, CheckCacheCorruptedFailure) {
251 mangle_file(old_file); 242 mangle_file(old_file);
252 char* argv[2] = { 243 std::vector<std::string> sha1s = {
253 &bad_sha1_a[0], 244 bad_sha1_a,
254 &bad_sha1_b[0] 245 bad_sha1_b
255 }; 246 };
256 ASSERT_NE(0, applypatch_check(&old_file[0], 2, argv)); 247 ASSERT_NE(0, applypatch_check(&old_file[0], sha1s));
257} 248}
258 249
259TEST_F(ApplyPatchCacheTest, CheckCacheMissingSingle) { 250TEST_F(ApplyPatchCacheTest, CheckCacheMissingSingle) {
260 unlink(&old_file[0]); 251 unlink(&old_file[0]);
261 char* s = &old_sha1[0]; 252 std::vector<std::string> sha1s = { old_sha1 };
262 ASSERT_EQ(0, applypatch_check(&old_file[0], 1, &s)); 253 ASSERT_EQ(0, applypatch_check(&old_file[0], sha1s));
263} 254}
264 255
265TEST_F(ApplyPatchCacheTest, CheckCacheMissingMultiple) { 256TEST_F(ApplyPatchCacheTest, CheckCacheMissingMultiple) {
266 unlink(&old_file[0]); 257 unlink(&old_file[0]);
267 char* argv[3] = { 258 std::vector<std::string> sha1s = {
268 &bad_sha1_a[0], 259 bad_sha1_a,
269 &old_sha1[0], 260 old_sha1,
270 &bad_sha1_b[0] 261 bad_sha1_b
271 }; 262 };
272 ASSERT_EQ(0, applypatch_check(&old_file[0], 3, argv)); 263 ASSERT_EQ(0, applypatch_check(&old_file[0], sha1s));
273} 264}
274 265
275TEST_F(ApplyPatchCacheTest, CheckCacheMissingFailure) { 266TEST_F(ApplyPatchCacheTest, CheckCacheMissingFailure) {
276 unlink(&old_file[0]); 267 unlink(&old_file[0]);
277 char* argv[2] = { 268 std::vector<std::string> sha1s = {
278 &bad_sha1_a[0], 269 bad_sha1_a,
279 &bad_sha1_b[0] 270 bad_sha1_b
280 }; 271 };
281 ASSERT_NE(0, applypatch_check(&old_file[0], 2, argv)); 272 ASSERT_NE(0, applypatch_check(&old_file[0], sha1s));
282} 273}
283 274
284TEST_F(ApplyPatchFullTest, ApplyInPlace) { 275TEST_F(ApplyPatchFullTest, ApplyInPlace) {
285 std::vector<char*> sha1s; 276 std::vector<std::string> sha1s = {
286 sha1s.push_back(&bad_sha1_a[0]); 277 bad_sha1_a,
287 sha1s.push_back(&old_sha1[0]); 278 old_sha1
288 279 };
289 int ap_result = applypatch(&old_file[0], 280 int ap_result = applypatch(&old_file[0],
290 "-", 281 "-",
291 &new_sha1[0], 282 &new_sha1[0],
292 new_size, 283 new_size,
293 2, 284 sha1s,
294 sha1s.data(),
295 patches.data(), 285 patches.data(),
296 nullptr); 286 nullptr);
297 ASSERT_EQ(0, ap_result); 287 ASSERT_EQ(0, ap_result);
@@ -301,8 +291,7 @@ TEST_F(ApplyPatchFullTest, ApplyInPlace) {
301 "-", 291 "-",
302 &new_sha1[0], 292 &new_sha1[0],
303 new_size, 293 new_size,
304 2, 294 sha1s,
305 sha1s.data(),
306 patches.data(), 295 patches.data(),
307 nullptr); 296 nullptr);
308 ASSERT_EQ(0, ap_result); 297 ASSERT_EQ(0, ap_result);
@@ -310,15 +299,15 @@ TEST_F(ApplyPatchFullTest, ApplyInPlace) {
310} 299}
311 300
312TEST_F(ApplyPatchFullTest, ApplyInNewLocation) { 301TEST_F(ApplyPatchFullTest, ApplyInNewLocation) {
313 std::vector<char*> sha1s; 302 std::vector<std::string> sha1s = {
314 sha1s.push_back(&bad_sha1_a[0]); 303 bad_sha1_a,
315 sha1s.push_back(&old_sha1[0]); 304 old_sha1
305 };
316 int ap_result = applypatch(&old_file[0], 306 int ap_result = applypatch(&old_file[0],
317 &output_loc[0], 307 &output_loc[0],
318 &new_sha1[0], 308 &new_sha1[0],
319 new_size, 309 new_size,
320 2, 310 sha1s,
321 sha1s.data(),
322 patches.data(), 311 patches.data(),
323 nullptr); 312 nullptr);
324 ASSERT_EQ(0, ap_result); 313 ASSERT_EQ(0, ap_result);
@@ -327,8 +316,7 @@ TEST_F(ApplyPatchFullTest, ApplyInNewLocation) {
327 &output_loc[0], 316 &output_loc[0],
328 &new_sha1[0], 317 &new_sha1[0],
329 new_size, 318 new_size,
330 2, 319 sha1s,
331 sha1s.data(),
332 patches.data(), 320 patches.data(),
333 nullptr); 321 nullptr);
334 ASSERT_EQ(0, ap_result); 322 ASSERT_EQ(0, ap_result);
@@ -337,15 +325,15 @@ TEST_F(ApplyPatchFullTest, ApplyInNewLocation) {
337 325
338TEST_F(ApplyPatchFullTest, ApplyCorruptedInNewLocation) { 326TEST_F(ApplyPatchFullTest, ApplyCorruptedInNewLocation) {
339 mangle_file(old_file); 327 mangle_file(old_file);
340 std::vector<char*> sha1s; 328 std::vector<std::string> sha1s = {
341 sha1s.push_back(&bad_sha1_a[0]); 329 bad_sha1_a,
342 sha1s.push_back(&old_sha1[0]); 330 old_sha1
331 };
343 int ap_result = applypatch(&old_file[0], 332 int ap_result = applypatch(&old_file[0],
344 &output_loc[0], 333 &output_loc[0],
345 &new_sha1[0], 334 &new_sha1[0],
346 new_size, 335 new_size,
347 2, 336 sha1s,
348 sha1s.data(),
349 patches.data(), 337 patches.data(),
350 nullptr); 338 nullptr);
351 ASSERT_EQ(0, ap_result); 339 ASSERT_EQ(0, ap_result);
@@ -354,8 +342,7 @@ TEST_F(ApplyPatchFullTest, ApplyCorruptedInNewLocation) {
354 &output_loc[0], 342 &output_loc[0],
355 &new_sha1[0], 343 &new_sha1[0],
356 new_size, 344 new_size,
357 2, 345 sha1s,
358 sha1s.data(),
359 patches.data(), 346 patches.data(),
360 nullptr); 347 nullptr);
361 ASSERT_EQ(0, ap_result); 348 ASSERT_EQ(0, ap_result);
@@ -366,15 +353,15 @@ TEST_F(ApplyPatchDoubleCacheTest, ApplyDoubleCorruptedInNewLocation) {
366 mangle_file(old_file); 353 mangle_file(old_file);
367 mangle_file(cache_file); 354 mangle_file(cache_file);
368 355
369 std::vector<char*> sha1s; 356 std::vector<std::string> sha1s = {
370 sha1s.push_back(&bad_sha1_a[0]); 357 bad_sha1_a,
371 sha1s.push_back(&old_sha1[0]); 358 old_sha1
359 };
372 int ap_result = applypatch(&old_file[0], 360 int ap_result = applypatch(&old_file[0],
373 &output_loc[0], 361 &output_loc[0],
374 &new_sha1[0], 362 &new_sha1[0],
375 new_size, 363 new_size,
376 2, 364 sha1s,
377 sha1s.data(),
378 patches.data(), 365 patches.data(),
379 nullptr); 366 nullptr);
380 ASSERT_NE(0, ap_result); 367 ASSERT_NE(0, ap_result);
@@ -383,8 +370,7 @@ TEST_F(ApplyPatchDoubleCacheTest, ApplyDoubleCorruptedInNewLocation) {
383 &output_loc[0], 370 &output_loc[0],
384 &new_sha1[0], 371 &new_sha1[0],
385 new_size, 372 new_size,
386 2, 373 sha1s,
387 sha1s.data(),
388 patches.data(), 374 patches.data(),
389 nullptr); 375 nullptr);
390 ASSERT_NE(0, ap_result); 376 ASSERT_NE(0, ap_result);
diff --git a/tests/component/edify_test.cpp b/tests/component/edify_test.cpp
index a4dbb9fb..287e40cc 100644
--- a/tests/component/edify_test.cpp
+++ b/tests/component/edify_test.cpp
@@ -28,15 +28,15 @@ static void expect(const char* expr_str, const char* expected) {
28 28
29 State state(expr_str, nullptr); 29 State state(expr_str, nullptr);
30 30
31 char* result = Evaluate(&state, e); 31 std::string result;
32 bool status = Evaluate(&state, e, &result);
32 33
33 if (expected == nullptr) { 34 if (expected == nullptr) {
34 EXPECT_EQ(nullptr, result); 35 EXPECT_FALSE(status);
35 } else { 36 } else {
36 EXPECT_STREQ(expected, result); 37 EXPECT_STREQ(expected, result.c_str());
37 } 38 }
38 39
39 free(result);
40} 40}
41 41
42class EdifyTest : public ::testing::Test { 42class EdifyTest : public ::testing::Test {
diff --git a/tests/component/updater_test.cpp b/tests/component/updater_test.cpp
index 64a6b37c..a859f11c 100644
--- a/tests/component/updater_test.cpp
+++ b/tests/component/updater_test.cpp
@@ -32,12 +32,13 @@ static void expect(const char* expected, const char* expr_str, CauseCode cause_c
32 32
33 State state(expr_str, nullptr); 33 State state(expr_str, nullptr);
34 34
35 char* result = Evaluate(&state, e); 35 std::string result;
36 bool status = Evaluate(&state, e, &result);
36 37
37 if (expected == nullptr) { 38 if (expected == nullptr) {
38 EXPECT_EQ(nullptr, result); 39 EXPECT_FALSE(status);
39 } else { 40 } else {
40 EXPECT_STREQ(expected, result); 41 EXPECT_STREQ(expected, result.c_str());
41 } 42 }
42 43
43 // Error code is set in updater/updater.cpp only, by parsing State.errmsg. 44 // Error code is set in updater/updater.cpp only, by parsing State.errmsg.
@@ -46,7 +47,6 @@ static void expect(const char* expected, const char* expr_str, CauseCode cause_c
46 // Cause code should always be available. 47 // Cause code should always be available.
47 EXPECT_EQ(cause_code, state.cause_code); 48 EXPECT_EQ(cause_code, state.cause_code);
48 49
49 free(result);
50} 50}
51 51
52class UpdaterTest : public ::testing::Test { 52class UpdaterTest : public ::testing::Test {
diff --git a/updater/blockimg.cpp b/updater/blockimg.cpp
index 433d9802..5f9b437f 100644
--- a/updater/blockimg.cpp
+++ b/updater/blockimg.cpp
@@ -1216,7 +1216,7 @@ static int PerformCommandDiff(CommandParameters& params) {
1216 1216
1217 size_t len; 1217 size_t len;
1218 if (!android::base::ParseUint(params.tokens[params.cpos++].c_str(), &len)) { 1218 if (!android::base::ParseUint(params.tokens[params.cpos++].c_str(), &len)) {
1219 fprintf(stderr, "invalid patch offset\n"); 1219 fprintf(stderr, "invalid patch len\n");
1220 return -1; 1220 return -1;
1221 } 1221 }
1222 1222
@@ -1248,10 +1248,8 @@ static int PerformCommandDiff(CommandParameters& params) {
1248 if (status == 0) { 1248 if (status == 0) {
1249 fprintf(stderr, "patching %zu blocks to %zu\n", blocks, tgt.size); 1249 fprintf(stderr, "patching %zu blocks to %zu\n", blocks, tgt.size);
1250 1250
1251 Value patch_value; 1251 Value patch_value(VAL_BLOB,
1252 patch_value.type = VAL_BLOB; 1252 std::string(reinterpret_cast<const char*>(params.patch_start + offset), len));
1253 patch_value.size = len;
1254 patch_value.data = (char*) (params.patch_start + offset);
1255 1253
1256 RangeSinkState rss(tgt); 1254 RangeSinkState rss(tgt);
1257 rss.fd = params.fd; 1255 rss.fd = params.fd;
@@ -1398,64 +1396,62 @@ static Value* PerformBlockImageUpdate(const char* name, State* state, int /* arg
1398 Value* patch_data_fn = nullptr; 1396 Value* patch_data_fn = nullptr;
1399 if (ReadValueArgs(state, argv, 4, &blockdev_filename, &transfer_list_value, 1397 if (ReadValueArgs(state, argv, 4, &blockdev_filename, &transfer_list_value,
1400 &new_data_fn, &patch_data_fn) < 0) { 1398 &new_data_fn, &patch_data_fn) < 0) {
1401 return StringValue(strdup("")); 1399 return StringValue("");
1402 } 1400 }
1403 std::unique_ptr<Value, decltype(&FreeValue)> blockdev_filename_holder(blockdev_filename, 1401 std::unique_ptr<Value> blockdev_filename_holder(blockdev_filename);
1404 FreeValue); 1402 std::unique_ptr<Value> transfer_list_value_holder(transfer_list_value);
1405 std::unique_ptr<Value, decltype(&FreeValue)> transfer_list_value_holder(transfer_list_value, 1403 std::unique_ptr<Value> new_data_fn_holder(new_data_fn);
1406 FreeValue); 1404 std::unique_ptr<Value> patch_data_fn_holder(patch_data_fn);
1407 std::unique_ptr<Value, decltype(&FreeValue)> new_data_fn_holder(new_data_fn, FreeValue);
1408 std::unique_ptr<Value, decltype(&FreeValue)> patch_data_fn_holder(patch_data_fn, FreeValue);
1409 1405
1410 if (blockdev_filename->type != VAL_STRING) { 1406 if (blockdev_filename->type != VAL_STRING) {
1411 ErrorAbort(state, kArgsParsingFailure, "blockdev_filename argument to %s must be string", 1407 ErrorAbort(state, kArgsParsingFailure, "blockdev_filename argument to %s must be string",
1412 name); 1408 name);
1413 return StringValue(strdup("")); 1409 return StringValue("");
1414 } 1410 }
1415 if (transfer_list_value->type != VAL_BLOB) { 1411 if (transfer_list_value->type != VAL_BLOB) {
1416 ErrorAbort(state, kArgsParsingFailure, "transfer_list argument to %s must be blob", name); 1412 ErrorAbort(state, kArgsParsingFailure, "transfer_list argument to %s must be blob", name);
1417 return StringValue(strdup("")); 1413 return StringValue("");
1418 } 1414 }
1419 if (new_data_fn->type != VAL_STRING) { 1415 if (new_data_fn->type != VAL_STRING) {
1420 ErrorAbort(state, kArgsParsingFailure, "new_data_fn argument to %s must be string", name); 1416 ErrorAbort(state, kArgsParsingFailure, "new_data_fn argument to %s must be string", name);
1421 return StringValue(strdup("")); 1417 return StringValue("");
1422 } 1418 }
1423 if (patch_data_fn->type != VAL_STRING) { 1419 if (patch_data_fn->type != VAL_STRING) {
1424 ErrorAbort(state, kArgsParsingFailure, "patch_data_fn argument to %s must be string", 1420 ErrorAbort(state, kArgsParsingFailure, "patch_data_fn argument to %s must be string",
1425 name); 1421 name);
1426 return StringValue(strdup("")); 1422 return StringValue("");
1427 } 1423 }
1428 1424
1429 UpdaterInfo* ui = reinterpret_cast<UpdaterInfo*>(state->cookie); 1425 UpdaterInfo* ui = reinterpret_cast<UpdaterInfo*>(state->cookie);
1430 1426
1431 if (ui == nullptr) { 1427 if (ui == nullptr) {
1432 return StringValue(strdup("")); 1428 return StringValue("");
1433 } 1429 }
1434 1430
1435 FILE* cmd_pipe = ui->cmd_pipe; 1431 FILE* cmd_pipe = ui->cmd_pipe;
1436 ZipArchive* za = ui->package_zip; 1432 ZipArchive* za = ui->package_zip;
1437 1433
1438 if (cmd_pipe == nullptr || za == nullptr) { 1434 if (cmd_pipe == nullptr || za == nullptr) {
1439 return StringValue(strdup("")); 1435 return StringValue("");
1440 } 1436 }
1441 1437
1442 const ZipEntry* patch_entry = mzFindZipEntry(za, patch_data_fn->data); 1438 const ZipEntry* patch_entry = mzFindZipEntry(za, patch_data_fn->data.c_str());
1443 if (patch_entry == nullptr) { 1439 if (patch_entry == nullptr) {
1444 fprintf(stderr, "%s(): no file \"%s\" in package", name, patch_data_fn->data); 1440 fprintf(stderr, "%s(): no file \"%s\" in package", name, patch_data_fn->data.c_str());
1445 return StringValue(strdup("")); 1441 return StringValue("");
1446 } 1442 }
1447 1443
1448 params.patch_start = ui->package_zip_addr + mzGetZipEntryOffset(patch_entry); 1444 params.patch_start = ui->package_zip_addr + mzGetZipEntryOffset(patch_entry);
1449 const ZipEntry* new_entry = mzFindZipEntry(za, new_data_fn->data); 1445 const ZipEntry* new_entry = mzFindZipEntry(za, new_data_fn->data.c_str());
1450 if (new_entry == nullptr) { 1446 if (new_entry == nullptr) {
1451 fprintf(stderr, "%s(): no file \"%s\" in package", name, new_data_fn->data); 1447 fprintf(stderr, "%s(): no file \"%s\" in package", name, new_data_fn->data.c_str());
1452 return StringValue(strdup("")); 1448 return StringValue("");
1453 } 1449 }
1454 1450
1455 params.fd.reset(TEMP_FAILURE_RETRY(ota_open(blockdev_filename->data, O_RDWR))); 1451 params.fd.reset(TEMP_FAILURE_RETRY(ota_open(blockdev_filename->data.c_str(), O_RDWR)));
1456 if (params.fd == -1) { 1452 if (params.fd == -1) {
1457 fprintf(stderr, "open \"%s\" failed: %s\n", blockdev_filename->data, strerror(errno)); 1453 fprintf(stderr, "open \"%s\" failed: %s\n", blockdev_filename->data.c_str(), strerror(errno));
1458 return StringValue(strdup("")); 1454 return StringValue("");
1459 } 1455 }
1460 1456
1461 if (params.canwrite) { 1457 if (params.canwrite) {
@@ -1471,24 +1467,21 @@ static Value* PerformBlockImageUpdate(const char* name, State* state, int /* arg
1471 int error = pthread_create(&params.thread, &attr, unzip_new_data, &params.nti); 1467 int error = pthread_create(&params.thread, &attr, unzip_new_data, &params.nti);
1472 if (error != 0) { 1468 if (error != 0) {
1473 fprintf(stderr, "pthread_create failed: %s\n", strerror(error)); 1469 fprintf(stderr, "pthread_create failed: %s\n", strerror(error));
1474 return StringValue(strdup("")); 1470 return StringValue("");
1475 } 1471 }
1476 } 1472 }
1477 1473
1478 // Copy all the lines in transfer_list_value into std::string for 1474 std::vector<std::string> lines = android::base::Split(transfer_list_value->data, "\n");
1479 // processing.
1480 const std::string transfer_list(transfer_list_value->data, transfer_list_value->size);
1481 std::vector<std::string> lines = android::base::Split(transfer_list, "\n");
1482 if (lines.size() < 2) { 1475 if (lines.size() < 2) {
1483 ErrorAbort(state, kArgsParsingFailure, "too few lines in the transfer list [%zd]\n", 1476 ErrorAbort(state, kArgsParsingFailure, "too few lines in the transfer list [%zd]\n",
1484 lines.size()); 1477 lines.size());
1485 return StringValue(strdup("")); 1478 return StringValue("");
1486 } 1479 }
1487 1480
1488 // First line in transfer list is the version number 1481 // First line in transfer list is the version number
1489 if (!android::base::ParseInt(lines[0].c_str(), &params.version, 1, 4)) { 1482 if (!android::base::ParseInt(lines[0].c_str(), &params.version, 1, 4)) {
1490 fprintf(stderr, "unexpected transfer list version [%s]\n", lines[0].c_str()); 1483 fprintf(stderr, "unexpected transfer list version [%s]\n", lines[0].c_str());
1491 return StringValue(strdup("")); 1484 return StringValue("");
1492 } 1485 }
1493 1486
1494 fprintf(stderr, "blockimg version is %d\n", params.version); 1487 fprintf(stderr, "blockimg version is %d\n", params.version);
@@ -1497,11 +1490,11 @@ static Value* PerformBlockImageUpdate(const char* name, State* state, int /* arg
1497 int total_blocks; 1490 int total_blocks;
1498 if (!android::base::ParseInt(lines[1].c_str(), &total_blocks, 0)) { 1491 if (!android::base::ParseInt(lines[1].c_str(), &total_blocks, 0)) {
1499 ErrorAbort(state, kArgsParsingFailure, "unexpected block count [%s]\n", lines[1].c_str()); 1492 ErrorAbort(state, kArgsParsingFailure, "unexpected block count [%s]\n", lines[1].c_str());
1500 return StringValue(strdup("")); 1493 return StringValue("");
1501 } 1494 }
1502 1495
1503 if (total_blocks == 0) { 1496 if (total_blocks == 0) {
1504 return StringValue(strdup("t")); 1497 return StringValue("t");
1505 } 1498 }
1506 1499
1507 size_t start = 2; 1500 size_t start = 2;
@@ -1509,7 +1502,7 @@ static Value* PerformBlockImageUpdate(const char* name, State* state, int /* arg
1509 if (lines.size() < 4) { 1502 if (lines.size() < 4) {
1510 ErrorAbort(state, kArgsParsingFailure, "too few lines in the transfer list [%zu]\n", 1503 ErrorAbort(state, kArgsParsingFailure, "too few lines in the transfer list [%zu]\n",
1511 lines.size()); 1504 lines.size());
1512 return StringValue(strdup("")); 1505 return StringValue("");
1513 } 1506 }
1514 1507
1515 // Third line is how many stash entries are needed simultaneously 1508 // Third line is how many stash entries are needed simultaneously
@@ -1520,12 +1513,12 @@ static Value* PerformBlockImageUpdate(const char* name, State* state, int /* arg
1520 if (!android::base::ParseInt(lines[3].c_str(), &stash_max_blocks, 0)) { 1513 if (!android::base::ParseInt(lines[3].c_str(), &stash_max_blocks, 0)) {
1521 ErrorAbort(state, kArgsParsingFailure, "unexpected maximum stash blocks [%s]\n", 1514 ErrorAbort(state, kArgsParsingFailure, "unexpected maximum stash blocks [%s]\n",
1522 lines[3].c_str()); 1515 lines[3].c_str());
1523 return StringValue(strdup("")); 1516 return StringValue("");
1524 } 1517 }
1525 1518
1526 int res = CreateStash(state, stash_max_blocks, blockdev_filename->data, params.stashbase); 1519 int res = CreateStash(state, stash_max_blocks, blockdev_filename->data.c_str(), params.stashbase);
1527 if (res == -1) { 1520 if (res == -1) {
1528 return StringValue(strdup("")); 1521 return StringValue("");
1529 } 1522 }
1530 1523
1531 params.createdstash = res; 1524 params.createdstash = res;
@@ -1589,7 +1582,7 @@ static Value* PerformBlockImageUpdate(const char* name, State* state, int /* arg
1589 fprintf(stderr, "stashed %zu blocks\n", params.stashed); 1582 fprintf(stderr, "stashed %zu blocks\n", params.stashed);
1590 fprintf(stderr, "max alloc needed was %zu\n", params.buffer.size()); 1583 fprintf(stderr, "max alloc needed was %zu\n", params.buffer.size());
1591 1584
1592 const char* partition = strrchr(blockdev_filename->data, '/'); 1585 const char* partition = strrchr(blockdev_filename->data.c_str(), '/');
1593 if (partition != nullptr && *(partition+1) != 0) { 1586 if (partition != nullptr && *(partition+1) != 0) {
1594 fprintf(cmd_pipe, "log bytes_written_%s: %zu\n", partition + 1, 1587 fprintf(cmd_pipe, "log bytes_written_%s: %zu\n", partition + 1,
1595 params.written * BLOCKSIZE); 1588 params.written * BLOCKSIZE);
@@ -1623,7 +1616,7 @@ pbiudone:
1623 state->cause_code = failure_type; 1616 state->cause_code = failure_type;
1624 } 1617 }
1625 1618
1626 return StringValue(rc == 0 ? strdup("t") : strdup("")); 1619 return StringValue(rc == 0 ? "t" : "");
1627} 1620}
1628 1621
1629// The transfer list is a text file containing commands to 1622// The transfer list is a text file containing commands to
@@ -1721,27 +1714,26 @@ Value* RangeSha1Fn(const char* name, State* state, int /* argc */, Expr* argv[])
1721 Value* ranges; 1714 Value* ranges;
1722 1715
1723 if (ReadValueArgs(state, argv, 2, &blockdev_filename, &ranges) < 0) { 1716 if (ReadValueArgs(state, argv, 2, &blockdev_filename, &ranges) < 0) {
1724 return StringValue(strdup("")); 1717 return StringValue("");
1725 } 1718 }
1726 std::unique_ptr<Value, decltype(&FreeValue)> ranges_holder(ranges, FreeValue); 1719 std::unique_ptr<Value> ranges_holder(ranges);
1727 std::unique_ptr<Value, decltype(&FreeValue)> blockdev_filename_holder(blockdev_filename, 1720 std::unique_ptr<Value> blockdev_filename_holder(blockdev_filename);
1728 FreeValue);
1729 1721
1730 if (blockdev_filename->type != VAL_STRING) { 1722 if (blockdev_filename->type != VAL_STRING) {
1731 ErrorAbort(state, kArgsParsingFailure, "blockdev_filename argument to %s must be string", 1723 ErrorAbort(state, kArgsParsingFailure, "blockdev_filename argument to %s must be string",
1732 name); 1724 name);
1733 return StringValue(strdup("")); 1725 return StringValue("");
1734 } 1726 }
1735 if (ranges->type != VAL_STRING) { 1727 if (ranges->type != VAL_STRING) {
1736 ErrorAbort(state, kArgsParsingFailure, "ranges argument to %s must be string", name); 1728 ErrorAbort(state, kArgsParsingFailure, "ranges argument to %s must be string", name);
1737 return StringValue(strdup("")); 1729 return StringValue("");
1738 } 1730 }
1739 1731
1740 android::base::unique_fd fd(ota_open(blockdev_filename->data, O_RDWR)); 1732 android::base::unique_fd fd(ota_open(blockdev_filename->data.c_str(), O_RDWR));
1741 if (fd == -1) { 1733 if (fd == -1) {
1742 ErrorAbort(state, kFileOpenFailure, "open \"%s\" failed: %s", blockdev_filename->data, 1734 ErrorAbort(state, kFileOpenFailure, "open \"%s\" failed: %s",
1743 strerror(errno)); 1735 blockdev_filename->data.c_str(), strerror(errno));
1744 return StringValue(strdup("")); 1736 return StringValue("");
1745 } 1737 }
1746 1738
1747 RangeSet rs; 1739 RangeSet rs;
@@ -1753,16 +1745,16 @@ Value* RangeSha1Fn(const char* name, State* state, int /* argc */, Expr* argv[])
1753 std::vector<uint8_t> buffer(BLOCKSIZE); 1745 std::vector<uint8_t> buffer(BLOCKSIZE);
1754 for (size_t i = 0; i < rs.count; ++i) { 1746 for (size_t i = 0; i < rs.count; ++i) {
1755 if (!check_lseek(fd, (off64_t)rs.pos[i*2] * BLOCKSIZE, SEEK_SET)) { 1747 if (!check_lseek(fd, (off64_t)rs.pos[i*2] * BLOCKSIZE, SEEK_SET)) {
1756 ErrorAbort(state, kLseekFailure, "failed to seek %s: %s", blockdev_filename->data, 1748 ErrorAbort(state, kLseekFailure, "failed to seek %s: %s",
1757 strerror(errno)); 1749 blockdev_filename->data.c_str(), strerror(errno));
1758 return StringValue(strdup("")); 1750 return StringValue("");
1759 } 1751 }
1760 1752
1761 for (size_t j = rs.pos[i*2]; j < rs.pos[i*2+1]; ++j) { 1753 for (size_t j = rs.pos[i*2]; j < rs.pos[i*2+1]; ++j) {
1762 if (read_all(fd, buffer, BLOCKSIZE) == -1) { 1754 if (read_all(fd, buffer, BLOCKSIZE) == -1) {
1763 ErrorAbort(state, kFreadFailure, "failed to read %s: %s", blockdev_filename->data, 1755 ErrorAbort(state, kFreadFailure, "failed to read %s: %s",
1764 strerror(errno)); 1756 blockdev_filename->data.c_str(), strerror(errno));
1765 return StringValue(strdup("")); 1757 return StringValue("");
1766 } 1758 }
1767 1759
1768 SHA1_Update(&ctx, buffer.data(), BLOCKSIZE); 1760 SHA1_Update(&ctx, buffer.data(), BLOCKSIZE);
@@ -1771,7 +1763,7 @@ Value* RangeSha1Fn(const char* name, State* state, int /* argc */, Expr* argv[])
1771 uint8_t digest[SHA_DIGEST_LENGTH]; 1763 uint8_t digest[SHA_DIGEST_LENGTH];
1772 SHA1_Final(digest, &ctx); 1764 SHA1_Final(digest, &ctx);
1773 1765
1774 return StringValue(strdup(print_sha1(digest).c_str())); 1766 return StringValue(print_sha1(digest));
1775} 1767}
1776 1768
1777// This function checks if a device has been remounted R/W prior to an incremental 1769// This function checks if a device has been remounted R/W prior to an incremental
@@ -1785,27 +1777,27 @@ Value* CheckFirstBlockFn(const char* name, State* state, int argc, Expr* argv[])
1785 if (ReadValueArgs(state, argv, 1, &arg_filename) < 0) { 1777 if (ReadValueArgs(state, argv, 1, &arg_filename) < 0) {
1786 return nullptr; 1778 return nullptr;
1787 } 1779 }
1788 std::unique_ptr<Value, decltype(&FreeValue)> filename(arg_filename, FreeValue); 1780 std::unique_ptr<Value> filename(arg_filename);
1789 1781
1790 if (filename->type != VAL_STRING) { 1782 if (filename->type != VAL_STRING) {
1791 ErrorAbort(state, kArgsParsingFailure, "filename argument to %s must be string", name); 1783 ErrorAbort(state, kArgsParsingFailure, "filename argument to %s must be string", name);
1792 return StringValue(strdup("")); 1784 return StringValue("");
1793 } 1785 }
1794 1786
1795 android::base::unique_fd fd(ota_open(arg_filename->data, O_RDONLY)); 1787 android::base::unique_fd fd(ota_open(arg_filename->data.c_str(), O_RDONLY));
1796 if (fd == -1) { 1788 if (fd == -1) {
1797 ErrorAbort(state, kFileOpenFailure, "open \"%s\" failed: %s", arg_filename->data, 1789 ErrorAbort(state, kFileOpenFailure, "open \"%s\" failed: %s", arg_filename->data.c_str(),
1798 strerror(errno)); 1790 strerror(errno));
1799 return StringValue(strdup("")); 1791 return StringValue("");
1800 } 1792 }
1801 1793
1802 RangeSet blk0 {1 /*count*/, 1/*size*/, std::vector<size_t> {0, 1}/*position*/}; 1794 RangeSet blk0 {1 /*count*/, 1/*size*/, std::vector<size_t> {0, 1}/*position*/};
1803 std::vector<uint8_t> block0_buffer(BLOCKSIZE); 1795 std::vector<uint8_t> block0_buffer(BLOCKSIZE);
1804 1796
1805 if (ReadBlocks(blk0, block0_buffer, fd) == -1) { 1797 if (ReadBlocks(blk0, block0_buffer, fd) == -1) {
1806 ErrorAbort(state, kFreadFailure, "failed to read %s: %s", arg_filename->data, 1798 ErrorAbort(state, kFreadFailure, "failed to read %s: %s", arg_filename->data.c_str(),
1807 strerror(errno)); 1799 strerror(errno));
1808 return StringValue(strdup("")); 1800 return StringValue("");
1809 } 1801 }
1810 1802
1811 // https://ext4.wiki.kernel.org/index.php/Ext4_Disk_Layout 1803 // https://ext4.wiki.kernel.org/index.php/Ext4_Disk_Layout
@@ -1823,7 +1815,7 @@ Value* CheckFirstBlockFn(const char* name, State* state, int argc, Expr* argv[])
1823 uiPrintf(state, "Last remount happened on %s", ctime(&mount_time)); 1815 uiPrintf(state, "Last remount happened on %s", ctime(&mount_time));
1824 } 1816 }
1825 1817
1826 return StringValue(strdup("t")); 1818 return StringValue("t");
1827} 1819}
1828 1820
1829 1821
@@ -1835,40 +1827,40 @@ Value* BlockImageRecoverFn(const char* name, State* state, int argc, Expr* argv[
1835 return NULL; 1827 return NULL;
1836 } 1828 }
1837 1829
1838 std::unique_ptr<Value, decltype(&FreeValue)> filename(arg_filename, FreeValue); 1830 std::unique_ptr<Value> filename(arg_filename);
1839 std::unique_ptr<Value, decltype(&FreeValue)> ranges(arg_ranges, FreeValue); 1831 std::unique_ptr<Value> ranges(arg_ranges);
1840 1832
1841 if (filename->type != VAL_STRING) { 1833 if (filename->type != VAL_STRING) {
1842 ErrorAbort(state, kArgsParsingFailure, "filename argument to %s must be string", name); 1834 ErrorAbort(state, kArgsParsingFailure, "filename argument to %s must be string", name);
1843 return StringValue(strdup("")); 1835 return StringValue("");
1844 } 1836 }
1845 if (ranges->type != VAL_STRING) { 1837 if (ranges->type != VAL_STRING) {
1846 ErrorAbort(state, kArgsParsingFailure, "ranges argument to %s must be string", name); 1838 ErrorAbort(state, kArgsParsingFailure, "ranges argument to %s must be string", name);
1847 return StringValue(strdup("")); 1839 return StringValue("");
1848 } 1840 }
1849 1841
1850 // Output notice to log when recover is attempted 1842 // Output notice to log when recover is attempted
1851 fprintf(stderr, "%s image corrupted, attempting to recover...\n", filename->data); 1843 fprintf(stderr, "%s image corrupted, attempting to recover...\n", filename->data.c_str());
1852 1844
1853 // When opened with O_RDWR, libfec rewrites corrupted blocks when they are read 1845 // When opened with O_RDWR, libfec rewrites corrupted blocks when they are read
1854 fec::io fh(filename->data, O_RDWR); 1846 fec::io fh(filename->data.c_str(), O_RDWR);
1855 1847
1856 if (!fh) { 1848 if (!fh) {
1857 ErrorAbort(state, kLibfecFailure, "fec_open \"%s\" failed: %s", filename->data, 1849 ErrorAbort(state, kLibfecFailure, "fec_open \"%s\" failed: %s", filename->data.c_str(),
1858 strerror(errno)); 1850 strerror(errno));
1859 return StringValue(strdup("")); 1851 return StringValue("");
1860 } 1852 }
1861 1853
1862 if (!fh.has_ecc() || !fh.has_verity()) { 1854 if (!fh.has_ecc() || !fh.has_verity()) {
1863 ErrorAbort(state, kLibfecFailure, "unable to use metadata to correct errors"); 1855 ErrorAbort(state, kLibfecFailure, "unable to use metadata to correct errors");
1864 return StringValue(strdup("")); 1856 return StringValue("");
1865 } 1857 }
1866 1858
1867 fec_status status; 1859 fec_status status;
1868 1860
1869 if (!fh.get_status(status)) { 1861 if (!fh.get_status(status)) {
1870 ErrorAbort(state, kLibfecFailure, "failed to read FEC status"); 1862 ErrorAbort(state, kLibfecFailure, "failed to read FEC status");
1871 return StringValue(strdup("")); 1863 return StringValue("");
1872 } 1864 }
1873 1865
1874 RangeSet rs; 1866 RangeSet rs;
@@ -1885,8 +1877,8 @@ Value* BlockImageRecoverFn(const char* name, State* state, int argc, Expr* argv[
1885 1877
1886 if (fh.pread(buffer, BLOCKSIZE, (off64_t)j * BLOCKSIZE) != BLOCKSIZE) { 1878 if (fh.pread(buffer, BLOCKSIZE, (off64_t)j * BLOCKSIZE) != BLOCKSIZE) {
1887 ErrorAbort(state, kLibfecFailure, "failed to recover %s (block %zu): %s", 1879 ErrorAbort(state, kLibfecFailure, "failed to recover %s (block %zu): %s",
1888 filename->data, j, strerror(errno)); 1880 filename->data.c_str(), j, strerror(errno));
1889 return StringValue(strdup("")); 1881 return StringValue("");
1890 } 1882 }
1891 1883
1892 // If we want to be able to recover from a situation where rewriting a corrected 1884 // If we want to be able to recover from a situation where rewriting a corrected
@@ -1901,8 +1893,8 @@ Value* BlockImageRecoverFn(const char* name, State* state, int argc, Expr* argv[
1901 // read and check if the errors field value has increased. 1893 // read and check if the errors field value has increased.
1902 } 1894 }
1903 } 1895 }
1904 fprintf(stderr, "...%s image recovered successfully.\n", filename->data); 1896 fprintf(stderr, "...%s image recovered successfully.\n", filename->data.c_str());
1905 return StringValue(strdup("t")); 1897 return StringValue("t");
1906} 1898}
1907 1899
1908void RegisterBlockImageFunctions() { 1900void RegisterBlockImageFunctions() {
diff --git a/updater/install.cpp b/updater/install.cpp
index 3546968d..d723b388 100644
--- a/updater/install.cpp
+++ b/updater/install.cpp
@@ -116,7 +116,7 @@ static int make_parents(char* name) {
116// 116//
117// fs_type="ext4" partition_type="EMMC" location=device 117// fs_type="ext4" partition_type="EMMC" location=device
118Value* MountFn(const char* name, State* state, int argc, Expr* argv[]) { 118Value* MountFn(const char* name, State* state, int argc, Expr* argv[]) {
119 char* result = NULL; 119 char* result = nullptr;
120 if (argc != 4 && argc != 5) { 120 if (argc != 4 && argc != 5) {
121 return ErrorAbort(state, kArgsParsingFailure, "%s() expects 4-5 args, got %d", name, argc); 121 return ErrorAbort(state, kArgsParsingFailure, "%s() expects 4-5 args, got %d", name, argc);
122 } 122 }
@@ -197,7 +197,7 @@ done:
197 197
198// is_mounted(mount_point) 198// is_mounted(mount_point)
199Value* IsMountedFn(const char* name, State* state, int argc, Expr* argv[]) { 199Value* IsMountedFn(const char* name, State* state, int argc, Expr* argv[]) {
200 char* result = NULL; 200 char* result = nullptr;
201 if (argc != 1) { 201 if (argc != 1) {
202 return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %d", name, argc); 202 return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %d", name, argc);
203 } 203 }
@@ -227,7 +227,7 @@ done:
227 227
228 228
229Value* UnmountFn(const char* name, State* state, int argc, Expr* argv[]) { 229Value* UnmountFn(const char* name, State* state, int argc, Expr* argv[]) {
230 char* result = NULL; 230 char* result = nullptr;
231 if (argc != 1) { 231 if (argc != 1) {
232 return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %d", name, argc); 232 return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %d", name, argc);
233 } 233 }
@@ -284,7 +284,7 @@ static int exec_cmd(const char* path, char* const argv[]) {
284// if fs_size > 0, that is the size to use 284// if fs_size > 0, that is the size to use
285// if fs_size < 0, then reserve that many bytes at the end of the partition (not for "f2fs") 285// if fs_size < 0, then reserve that many bytes at the end of the partition (not for "f2fs")
286Value* FormatFn(const char* name, State* state, int argc, Expr* argv[]) { 286Value* FormatFn(const char* name, State* state, int argc, Expr* argv[]) {
287 char* result = NULL; 287 char* result = nullptr;
288 if (argc != 5) { 288 if (argc != 5) {
289 return ErrorAbort(state, kArgsParsingFailure, "%s() expects 5 args, got %d", name, argc); 289 return ErrorAbort(state, kArgsParsingFailure, "%s() expects 5 args, got %d", name, argc);
290 } 290 }
@@ -358,7 +358,7 @@ done:
358} 358}
359 359
360Value* RenameFn(const char* name, State* state, int argc, Expr* argv[]) { 360Value* RenameFn(const char* name, State* state, int argc, Expr* argv[]) {
361 char* result = NULL; 361 char* result = nullptr;
362 if (argc != 2) { 362 if (argc != 2) {
363 return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc); 363 return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc);
364 } 364 }
@@ -397,15 +397,10 @@ done:
397} 397}
398 398
399Value* DeleteFn(const char* name, State* state, int argc, Expr* argv[]) { 399Value* DeleteFn(const char* name, State* state, int argc, Expr* argv[]) {
400 char** paths = reinterpret_cast<char**>(malloc(argc * sizeof(char*))); 400 std::vector<std::string> paths;
401 for (int i = 0; i < argc; ++i) { 401 for (int i = 0; i < argc; ++i) {
402 paths[i] = Evaluate(state, argv[i]); 402 if (!Evaluate(state, argv[i], &paths[i])) {
403 if (paths[i] == NULL) { 403 return nullptr;
404 for (int j = 0; j < i; ++j) {
405 free(paths[j]);
406 }
407 free(paths);
408 return NULL;
409 } 404 }
410 } 405 }
411 406
@@ -413,15 +408,12 @@ Value* DeleteFn(const char* name, State* state, int argc, Expr* argv[]) {
413 408
414 int success = 0; 409 int success = 0;
415 for (int i = 0; i < argc; ++i) { 410 for (int i = 0; i < argc; ++i) {
416 if ((recursive ? dirUnlinkHierarchy(paths[i]) : unlink(paths[i])) == 0) 411 if ((recursive ? dirUnlinkHierarchy(paths[i].c_str()) : unlink(paths[i].c_str())) == 0) {
417 ++success; 412 ++success;
418 free(paths[i]); 413 }
419 } 414 }
420 free(paths);
421 415
422 char buffer[10]; 416 return StringValue(android::base::StringPrintf("%d", success));
423 sprintf(buffer, "%d", success);
424 return StringValue(strdup(buffer));
425} 417}
426 418
427 419
@@ -483,7 +475,7 @@ Value* PackageExtractDirFn(const char* name, State* state,
483 NULL, NULL, sehandle); 475 NULL, NULL, sehandle);
484 free(zip_path); 476 free(zip_path);
485 free(dest_path); 477 free(dest_path);
486 return StringValue(strdup(success ? "t" : "")); 478 return StringValue(success ? "t" : "");
487} 479}
488 480
489 481
@@ -536,7 +528,7 @@ Value* PackageExtractFileFn(const char* name, State* state,
536 done2: 528 done2:
537 free(zip_path); 529 free(zip_path);
538 free(dest_path); 530 free(dest_path);
539 return StringValue(strdup(success ? "t" : "")); 531 return StringValue(success ? "t" : "");
540 } else { 532 } else {
541 // The one-argument version returns the contents of the file 533 // The one-argument version returns the contents of the file
542 // as the result. 534 // as the result.
@@ -544,10 +536,7 @@ Value* PackageExtractFileFn(const char* name, State* state,
544 char* zip_path; 536 char* zip_path;
545 if (ReadArgs(state, argv, 1, &zip_path) < 0) return NULL; 537 if (ReadArgs(state, argv, 1, &zip_path) < 0) return NULL;
546 538
547 Value* v = reinterpret_cast<Value*>(malloc(sizeof(Value))); 539 Value* v = new Value(VAL_INVALID, "");
548 v->type = VAL_BLOB;
549 v->size = -1;
550 v->data = NULL;
551 540
552 ZipArchive* za = ((UpdaterInfo*)(state->cookie))->package_zip; 541 ZipArchive* za = ((UpdaterInfo*)(state->cookie))->package_zip;
553 const ZipEntry* entry = mzFindZipEntry(za, zip_path); 542 const ZipEntry* entry = mzFindZipEntry(za, zip_path);
@@ -556,23 +545,16 @@ Value* PackageExtractFileFn(const char* name, State* state,
556 goto done1; 545 goto done1;
557 } 546 }
558 547
559 v->size = mzGetZipEntryUncompLen(entry); 548 v->data.resize(mzGetZipEntryUncompLen(entry));
560 v->data = reinterpret_cast<char*>(malloc(v->size));
561 if (v->data == NULL) {
562 printf("%s: failed to allocate %zd bytes for %s\n",
563 name, v->size, zip_path);
564 goto done1;
565 }
566
567 success = mzExtractZipEntryToBuffer(za, entry, 549 success = mzExtractZipEntryToBuffer(za, entry,
568 (unsigned char *)v->data); 550 reinterpret_cast<unsigned char *>(&v->data[0]));
569 551
570 done1: 552 done1:
571 free(zip_path); 553 free(zip_path);
572 if (!success) { 554 if (!success) {
573 free(v->data); 555 v->data.clear();
574 v->data = NULL; 556 } else {
575 v->size = -1; 557 v->type = VAL_BLOB;
576 } 558 }
577 return v; 559 return v;
578 } 560 }
@@ -584,13 +566,13 @@ Value* SymlinkFn(const char* name, State* state, int argc, Expr* argv[]) {
584 if (argc == 0) { 566 if (argc == 0) {
585 return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1+ args, got %d", name, argc); 567 return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1+ args, got %d", name, argc);
586 } 568 }
587 char* target; 569 std::string target;
588 target = Evaluate(state, argv[0]); 570 if (!Evaluate(state, argv[0], &target)) {
589 if (target == NULL) return NULL; 571 return nullptr;
572 }
590 573
591 char** srcs = ReadVarArgs(state, argc-1, argv+1); 574 char** srcs = ReadVarArgs(state, argc-1, argv+1);
592 if (srcs == NULL) { 575 if (srcs == NULL) {
593 free(target);
594 return NULL; 576 return NULL;
595 } 577 }
596 578
@@ -606,12 +588,12 @@ Value* SymlinkFn(const char* name, State* state, int argc, Expr* argv[]) {
606 } 588 }
607 if (make_parents(srcs[i])) { 589 if (make_parents(srcs[i])) {
608 printf("%s: failed to symlink %s to %s: making parents failed\n", 590 printf("%s: failed to symlink %s to %s: making parents failed\n",
609 name, srcs[i], target); 591 name, srcs[i], target.c_str());
610 ++bad; 592 ++bad;
611 } 593 }
612 if (symlink(target, srcs[i]) < 0) { 594 if (symlink(target.c_str(), srcs[i]) < 0) {
613 printf("%s: failed to symlink %s to %s: %s\n", 595 printf("%s: failed to symlink %s to %s: %s\n",
614 name, srcs[i], target, strerror(errno)); 596 name, srcs[i], target.c_str(), strerror(errno));
615 ++bad; 597 ++bad;
616 } 598 }
617 free(srcs[i]); 599 free(srcs[i]);
@@ -620,7 +602,7 @@ Value* SymlinkFn(const char* name, State* state, int argc, Expr* argv[]) {
620 if (bad) { 602 if (bad) {
621 return ErrorAbort(state, kSymlinkFailure, "%s: some symlinks failed", name); 603 return ErrorAbort(state, kSymlinkFailure, "%s: some symlinks failed", name);
622 } 604 }
623 return StringValue(strdup("")); 605 return StringValue("");
624} 606}
625 607
626struct perm_parsed_args { 608struct perm_parsed_args {
@@ -883,20 +865,20 @@ done:
883 return ErrorAbort(state, kSetMetadataFailure, "%s: some changes failed", name); 865 return ErrorAbort(state, kSetMetadataFailure, "%s: some changes failed", name);
884 } 866 }
885 867
886 return StringValue(strdup("")); 868 return StringValue("");
887} 869}
888 870
889Value* GetPropFn(const char* name, State* state, int argc, Expr* argv[]) { 871Value* GetPropFn(const char* name, State* state, int argc, Expr* argv[]) {
890 if (argc != 1) { 872 if (argc != 1) {
891 return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %d", name, argc); 873 return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %d", name, argc);
892 } 874 }
893 char* key = Evaluate(state, argv[0]); 875 std::string key;
894 if (key == NULL) return NULL; 876 if (!Evaluate(state, argv[0], &key)) {
895 877 return nullptr;
878 }
896 std::string value = android::base::GetProperty(key, ""); 879 std::string value = android::base::GetProperty(key, "");
897 free(key);
898 880
899 return StringValue(strdup(value.c_str())); 881 return StringValue(value);
900} 882}
901 883
902 884
@@ -1015,7 +997,7 @@ Value* ApplyPatchSpaceFn(const char* name, State* state,
1015 return nullptr; 997 return nullptr;
1016 } 998 }
1017 999
1018 return StringValue(strdup(CacheSizeCheck(bytes) ? "" : "t")); 1000 return StringValue(CacheSizeCheck(bytes) ? "" : "t");
1019} 1001}
1020 1002
1021// apply_patch(file, size, init_sha1, tgt_sha1, patch) 1003// apply_patch(file, size, init_sha1, tgt_sha1, patch)
@@ -1047,17 +1029,16 @@ Value* ApplyPatchFn(const char* name, State* state, int argc, Expr* argv[]) {
1047 } 1029 }
1048 1030
1049 int patchcount = (argc-4) / 2; 1031 int patchcount = (argc-4) / 2;
1050 std::unique_ptr<Value*, decltype(&free)> arg_values(ReadValueVarArgs(state, argc-4, argv+4), 1032 std::unique_ptr<Value*> arg_values(ReadValueVarArgs(state, argc-4, argv+4));
1051 free);
1052 if (!arg_values) { 1033 if (!arg_values) {
1053 return nullptr; 1034 return nullptr;
1054 } 1035 }
1055 std::vector<std::unique_ptr<Value, decltype(&FreeValue)>> patch_shas; 1036 std::vector<std::unique_ptr<Value>> patch_shas;
1056 std::vector<std::unique_ptr<Value, decltype(&FreeValue)>> patches; 1037 std::vector<std::unique_ptr<Value>> patches;
1057 // Protect values by unique_ptrs first to get rid of memory leak. 1038 // Protect values by unique_ptrs first to get rid of memory leak.
1058 for (int i = 0; i < patchcount * 2; i += 2) { 1039 for (int i = 0; i < patchcount * 2; i += 2) {
1059 patch_shas.emplace_back(arg_values.get()[i], FreeValue); 1040 patch_shas.emplace_back(arg_values.get()[i]);
1060 patches.emplace_back(arg_values.get()[i+1], FreeValue); 1041 patches.emplace_back(arg_values.get()[i+1]);
1061 } 1042 }
1062 1043
1063 for (int i = 0; i < patchcount; ++i) { 1044 for (int i = 0; i < patchcount; ++i) {
@@ -1071,7 +1052,7 @@ Value* ApplyPatchFn(const char* name, State* state, int argc, Expr* argv[]) {
1071 } 1052 }
1072 } 1053 }
1073 1054
1074 std::vector<char*> patch_sha_str; 1055 std::vector<std::string> patch_sha_str;
1075 std::vector<Value*> patch_ptrs; 1056 std::vector<Value*> patch_ptrs;
1076 for (int i = 0; i < patchcount; ++i) { 1057 for (int i = 0; i < patchcount; ++i) {
1077 patch_sha_str.push_back(patch_shas[i]->data); 1058 patch_sha_str.push_back(patch_shas[i]->data);
@@ -1080,9 +1061,9 @@ Value* ApplyPatchFn(const char* name, State* state, int argc, Expr* argv[]) {
1080 1061
1081 int result = applypatch(source_filename, target_filename, 1062 int result = applypatch(source_filename, target_filename,
1082 target_sha1, target_size, 1063 target_sha1, target_size,
1083 patchcount, patch_sha_str.data(), patch_ptrs.data(), NULL); 1064 patch_sha_str, patch_ptrs.data(), NULL);
1084 1065
1085 return StringValue(strdup(result == 0 ? "t" : "")); 1066 return StringValue(result == 0 ? "t" : "");
1086} 1067}
1087 1068
1088// apply_patch_check(file, [sha1_1, ...]) 1069// apply_patch_check(file, [sha1_1, ...])
@@ -1095,21 +1076,17 @@ Value* ApplyPatchCheckFn(const char* name, State* state,
1095 1076
1096 char* filename; 1077 char* filename;
1097 if (ReadArgs(state, argv, 1, &filename) < 0) { 1078 if (ReadArgs(state, argv, 1, &filename) < 0) {
1098 return NULL; 1079 return nullptr;
1099 } 1080 }
1100 1081
1101 int patchcount = argc-1; 1082 std::vector<std::string> sha1s;
1102 char** sha1s = ReadVarArgs(state, argc-1, argv+1); 1083 if (!ReadArgs(state, argc-1, argv+1, &sha1s)) {
1103 1084 return nullptr;
1104 int result = applypatch_check(filename, patchcount, sha1s);
1105
1106 int i;
1107 for (i = 0; i < patchcount; ++i) {
1108 free(sha1s[i]);
1109 } 1085 }
1110 free(sha1s);
1111 1086
1112 return StringValue(strdup(result == 0 ? "t" : "")); 1087 int result = applypatch_check(filename, sha1s);
1088
1089 return StringValue(result == 0 ? "t" : "");
1113} 1090}
1114 1091
1115// This is the updater side handler for ui_print() in edify script. Contents 1092// This is the updater side handler for ui_print() in edify script. Contents
@@ -1129,7 +1106,7 @@ Value* UIPrintFn(const char* name, State* state, int argc, Expr* argv[]) {
1129 1106
1130 buffer += "\n"; 1107 buffer += "\n";
1131 uiPrint(state, buffer); 1108 uiPrint(state, buffer);
1132 return StringValue(strdup(buffer.c_str())); 1109 return StringValue(buffer);
1133} 1110}
1134 1111
1135Value* WipeCacheFn(const char* name, State* state, int argc, Expr* argv[]) { 1112Value* WipeCacheFn(const char* name, State* state, int argc, Expr* argv[]) {
@@ -1137,7 +1114,7 @@ Value* WipeCacheFn(const char* name, State* state, int argc, Expr* argv[]) {
1137 return ErrorAbort(state, kArgsParsingFailure, "%s() expects no args, got %d", name, argc); 1114 return ErrorAbort(state, kArgsParsingFailure, "%s() expects no args, got %d", name, argc);
1138 } 1115 }
1139 fprintf(((UpdaterInfo*)(state->cookie))->cmd_pipe, "wipe_cache\n"); 1116 fprintf(((UpdaterInfo*)(state->cookie))->cmd_pipe, "wipe_cache\n");
1140 return StringValue(strdup("t")); 1117 return StringValue("t");
1141} 1118}
1142 1119
1143Value* RunProgramFn(const char* name, State* state, int argc, Expr* argv[]) { 1120Value* RunProgramFn(const char* name, State* state, int argc, Expr* argv[]) {
@@ -1180,10 +1157,7 @@ Value* RunProgramFn(const char* name, State* state, int argc, Expr* argv[]) {
1180 free(args); 1157 free(args);
1181 free(args2); 1158 free(args2);
1182 1159
1183 char buffer[20]; 1160 return StringValue(android::base::StringPrintf("%d", status));
1184 sprintf(buffer, "%d", status);
1185
1186 return StringValue(strdup(buffer));
1187} 1161}
1188 1162
1189// sha1_check(data) 1163// sha1_check(data)
@@ -1199,32 +1173,32 @@ Value* Sha1CheckFn(const char* name, State* state, int argc, Expr* argv[]) {
1199 return ErrorAbort(state, kArgsParsingFailure, "%s() expects at least 1 arg", name); 1173 return ErrorAbort(state, kArgsParsingFailure, "%s() expects at least 1 arg", name);
1200 } 1174 }
1201 1175
1202 std::unique_ptr<Value*, decltype(&free)> arg_values(ReadValueVarArgs(state, argc, argv), free); 1176 std::unique_ptr<Value*> arg_values(ReadValueVarArgs(state, argc, argv));
1203 if (arg_values == nullptr) { 1177 if (arg_values == nullptr) {
1204 return nullptr; 1178 return nullptr;
1205 } 1179 }
1206 std::vector<std::unique_ptr<Value, decltype(&FreeValue)>> args; 1180 std::vector<std::unique_ptr<Value>> args;
1207 for (int i = 0; i < argc; ++i) { 1181 for (int i = 0; i < argc; ++i) {
1208 args.emplace_back(arg_values.get()[i], FreeValue); 1182 args.emplace_back(arg_values.get()[i]);
1209 } 1183 }
1210 1184
1211 if (args[0]->size < 0) { 1185 if (args[0]->type == VAL_INVALID) {
1212 return StringValue(strdup("")); 1186 return StringValue("");
1213 } 1187 }
1214 uint8_t digest[SHA_DIGEST_LENGTH]; 1188 uint8_t digest[SHA_DIGEST_LENGTH];
1215 SHA1(reinterpret_cast<uint8_t*>(args[0]->data), args[0]->size, digest); 1189 SHA1(reinterpret_cast<const uint8_t*>(args[0]->data.c_str()), args[0]->data.size(), digest);
1216 1190
1217 if (argc == 1) { 1191 if (argc == 1) {
1218 return StringValue(strdup(print_sha1(digest).c_str())); 1192 return StringValue(print_sha1(digest));
1219 } 1193 }
1220 1194
1221 for (int i = 1; i < argc; ++i) { 1195 for (int i = 1; i < argc; ++i) {
1222 uint8_t arg_digest[SHA_DIGEST_LENGTH]; 1196 uint8_t arg_digest[SHA_DIGEST_LENGTH];
1223 if (args[i]->type != VAL_STRING) { 1197 if (args[i]->type != VAL_STRING) {
1224 printf("%s(): arg %d is not a string; skipping", name, i); 1198 printf("%s(): arg %d is not a string; skipping", name, i);
1225 } else if (ParseSha1(args[i]->data, arg_digest) != 0) { 1199 } else if (ParseSha1(args[i]->data.c_str(), arg_digest) != 0) {
1226 // Warn about bad args and skip them. 1200 // Warn about bad args and skip them.
1227 printf("%s(): error parsing \"%s\" as sha-1; skipping", name, args[i]->data); 1201 printf("%s(): error parsing \"%s\" as sha-1; skipping", name, args[i]->data.c_str());
1228 } else if (memcmp(digest, arg_digest, SHA_DIGEST_LENGTH) == 0) { 1202 } else if (memcmp(digest, arg_digest, SHA_DIGEST_LENGTH) == 0) {
1229 // Found a match. 1203 // Found a match.
1230 return args[i].release(); 1204 return args[i].release();
@@ -1232,7 +1206,7 @@ Value* Sha1CheckFn(const char* name, State* state, int argc, Expr* argv[]) {
1232 } 1206 }
1233 1207
1234 // Didn't match any of the hex strings; return false. 1208 // Didn't match any of the hex strings; return false.
1235 return StringValue(strdup("")); 1209 return StringValue("");
1236} 1210}
1237 1211
1238// Read a local file and return its contents (the Value* returned 1212// Read a local file and return its contents (the Value* returned
@@ -1244,21 +1218,12 @@ Value* ReadFileFn(const char* name, State* state, int argc, Expr* argv[]) {
1244 char* filename; 1218 char* filename;
1245 if (ReadArgs(state, argv, 1, &filename) < 0) return NULL; 1219 if (ReadArgs(state, argv, 1, &filename) < 0) return NULL;
1246 1220
1247 Value* v = static_cast<Value*>(malloc(sizeof(Value))); 1221 Value* v = new Value(VAL_INVALID, "");
1248 if (v == nullptr) {
1249 return nullptr;
1250 }
1251 v->type = VAL_BLOB;
1252 v->size = -1;
1253 v->data = nullptr;
1254 1222
1255 FileContents fc; 1223 FileContents fc;
1256 if (LoadFileContents(filename, &fc) == 0) { 1224 if (LoadFileContents(filename, &fc) == 0) {
1257 v->data = static_cast<char*>(malloc(fc.data.size())); 1225 v->type = VAL_BLOB;
1258 if (v->data != nullptr) { 1226 v->data = std::string(fc.data.begin(), fc.data.end());
1259 memcpy(v->data, fc.data.data(), fc.data.size());
1260 v->size = fc.data.size();
1261 }
1262 } 1227 }
1263 free(filename); 1228 free(filename);
1264 return v; 1229 return v;
@@ -1326,16 +1291,19 @@ Value* SetStageFn(const char* name, State* state, int argc, Expr* argv[]) {
1326 // package installation. 1291 // package installation.
1327 FILE* f = ota_fopen(filename, "r+b"); 1292 FILE* f = ota_fopen(filename, "r+b");
1328 fseek(f, offsetof(struct bootloader_message, stage), SEEK_SET); 1293 fseek(f, offsetof(struct bootloader_message, stage), SEEK_SET);
1329 int to_write = strlen(stagestr)+1; 1294 size_t to_write = strlen(stagestr) + 1;
1330 int max_size = sizeof(((struct bootloader_message*)0)->stage); 1295 size_t max_size = sizeof(((struct bootloader_message*)0)->stage);
1331 if (to_write > max_size) { 1296 if (to_write > max_size) {
1332 to_write = max_size; 1297 to_write = max_size;
1333 stagestr[max_size-1] = 0; 1298 stagestr[max_size - 1] = 0;
1334 } 1299 }
1335 ota_fwrite(stagestr, to_write, 1, f); 1300 size_t status = ota_fwrite(stagestr, to_write, 1, f);
1336 ota_fclose(f); 1301 ota_fclose(f);
1337 1302
1338 free(stagestr); 1303 free(stagestr);
1304 if (status != to_write) {
1305 return StringValue("");
1306 }
1339 return StringValue(filename); 1307 return StringValue(filename);
1340} 1308}
1341 1309
@@ -1352,11 +1320,14 @@ Value* GetStageFn(const char* name, State* state, int argc, Expr* argv[]) {
1352 char buffer[sizeof(((struct bootloader_message*)0)->stage)]; 1320 char buffer[sizeof(((struct bootloader_message*)0)->stage)];
1353 FILE* f = ota_fopen(filename, "rb"); 1321 FILE* f = ota_fopen(filename, "rb");
1354 fseek(f, offsetof(struct bootloader_message, stage), SEEK_SET); 1322 fseek(f, offsetof(struct bootloader_message, stage), SEEK_SET);
1355 ota_fread(buffer, sizeof(buffer), 1, f); 1323 size_t status = ota_fread(buffer, sizeof(buffer), 1, f);
1356 ota_fclose(f); 1324 ota_fclose(f);
1357 buffer[sizeof(buffer)-1] = '\0'; 1325 if (status != sizeof(buffer)) {
1326 return StringValue("");
1327 }
1358 1328
1359 return StringValue(strdup(buffer)); 1329 buffer[sizeof(buffer)-1] = '\0';
1330 return StringValue(buffer);
1360} 1331}
1361 1332
1362Value* WipeBlockDeviceFn(const char* name, State* state, int argc, Expr* argv[]) { 1333Value* WipeBlockDeviceFn(const char* name, State* state, int argc, Expr* argv[]) {
@@ -1378,7 +1349,7 @@ Value* WipeBlockDeviceFn(const char* name, State* state, int argc, Expr* argv[])
1378 1349
1379 ota_close(fd); 1350 ota_close(fd);
1380 1351
1381 return StringValue(strdup(success ? "t" : "")); 1352 return StringValue(success ? "t" : "");
1382} 1353}
1383 1354
1384Value* EnableRebootFn(const char* name, State* state, int argc, Expr* argv[]) { 1355Value* EnableRebootFn(const char* name, State* state, int argc, Expr* argv[]) {
@@ -1387,7 +1358,7 @@ Value* EnableRebootFn(const char* name, State* state, int argc, Expr* argv[]) {
1387 } 1358 }
1388 UpdaterInfo* ui = (UpdaterInfo*)(state->cookie); 1359 UpdaterInfo* ui = (UpdaterInfo*)(state->cookie);
1389 fprintf(ui->cmd_pipe, "enable_reboot\n"); 1360 fprintf(ui->cmd_pipe, "enable_reboot\n");
1390 return StringValue(strdup("t")); 1361 return StringValue("t");
1391} 1362}
1392 1363
1393Value* Tune2FsFn(const char* name, State* state, int argc, Expr* argv[]) { 1364Value* Tune2FsFn(const char* name, State* state, int argc, Expr* argv[]) {
@@ -1418,7 +1389,7 @@ Value* Tune2FsFn(const char* name, State* state, int argc, Expr* argv[]) {
1418 return ErrorAbort(state, kTune2FsFailure, "%s() returned error code %d", 1389 return ErrorAbort(state, kTune2FsFailure, "%s() returned error code %d",
1419 name, result); 1390 name, result);
1420 } 1391 }
1421 return StringValue(strdup("t")); 1392 return StringValue("t");
1422} 1393}
1423 1394
1424void RegisterInstallFunctions() { 1395void RegisterInstallFunctions() {
diff --git a/updater/updater.cpp b/updater/updater.cpp
index c752ebbf..47696b80 100644
--- a/updater/updater.cpp
+++ b/updater/updater.cpp
@@ -151,13 +151,14 @@ int main(int argc, char** argv) {
151 } 151 }
152 } 152 }
153 153
154 char* result = Evaluate(&state, root); 154 std::string result;
155 bool status = Evaluate(&state, root, &result);
155 156
156 if (have_eio_error) { 157 if (have_eio_error) {
157 fprintf(cmd_pipe, "retry_update\n"); 158 fprintf(cmd_pipe, "retry_update\n");
158 } 159 }
159 160
160 if (result == NULL) { 161 if (!status) {
161 if (state.errmsg.empty()) { 162 if (state.errmsg.empty()) {
162 printf("script aborted (no error message)\n"); 163 printf("script aborted (no error message)\n");
163 fprintf(cmd_pipe, "ui_print script aborted (no error message)\n"); 164 fprintf(cmd_pipe, "ui_print script aborted (no error message)\n");
@@ -188,8 +189,7 @@ int main(int argc, char** argv) {
188 189
189 return 7; 190 return 7;
190 } else { 191 } else {
191 fprintf(cmd_pipe, "ui_print script succeeded: result was [%s]\n", result); 192 fprintf(cmd_pipe, "ui_print script succeeded: result was [%s]\n", result.c_str());
192 free(result);
193 } 193 }
194 194
195 if (updater_info.package_zip) { 195 if (updater_info.package_zip) {