1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include <stdio.h> 18 #include <stdlib.h> 19 #include <sys/stat.h> 20 #include <sys/types.h> 21 #include <unistd.h> 22 23 #include <algorithm> 24 #include <memory> 25 #include <string> 26 #include <vector> 27 28 #include <android-base/file.h> 29 #include <android-base/properties.h> 30 #include <android-base/stringprintf.h> 31 #include <android-base/strings.h> 32 #include <android-base/test_utils.h> 33 #include <bootloader_message/bootloader_message.h> 34 #include <brotli/encode.h> 35 #include <bsdiff.h> 36 #include <gtest/gtest.h> 37 #include <ziparchive/zip_archive.h> 38 #include <ziparchive/zip_writer.h> 39 40 #include "common/test_constants.h" 41 #include "edify/expr.h" 42 #include "error_code.h" 43 #include "otautil/SysUtil.h" 44 #include "print_sha1.h" 45 #include "updater/blockimg.h" 46 #include "updater/install.h" 47 #include "updater/updater.h" 48 49 struct selabel_handle *sehandle = nullptr; 50 51 static void expect(const char* expected, const char* expr_str, CauseCode cause_code, 52 UpdaterInfo* info = nullptr) { 53 std::unique_ptr<Expr> e; 54 int error_count = 0; 55 ASSERT_EQ(0, parse_string(expr_str, &e, &error_count)); 56 ASSERT_EQ(0, error_count); 57 58 State state(expr_str, info); 59 60 std::string result; 61 bool status = Evaluate(&state, e, &result); 62 63 if (expected == nullptr) { 64 ASSERT_FALSE(status); 65 } else { 66 ASSERT_TRUE(status); 67 ASSERT_STREQ(expected, result.c_str()); 68 } 69 70 // Error code is set in updater/updater.cpp only, by parsing State.errmsg. 71 ASSERT_EQ(kNoError, state.error_code); 72 73 // Cause code should always be available. 74 ASSERT_EQ(cause_code, state.cause_code); 75 } 76 77 static std::string get_sha1(const std::string& content) { 78 uint8_t digest[SHA_DIGEST_LENGTH]; 79 SHA1(reinterpret_cast<const uint8_t*>(content.c_str()), content.size(), digest); 80 return print_sha1(digest); 81 } 82 83 class UpdaterTest : public ::testing::Test { 84 protected: 85 virtual void SetUp() override { 86 RegisterBuiltins(); 87 RegisterInstallFunctions(); 88 RegisterBlockImageFunctions(); 89 } 90 }; 91 92 TEST_F(UpdaterTest, getprop) { 93 expect(android::base::GetProperty("ro.product.device", "").c_str(), 94 "getprop(\"ro.product.device\")", 95 kNoCause); 96 97 expect(android::base::GetProperty("ro.build.fingerprint", "").c_str(), 98 "getprop(\"ro.build.fingerprint\")", 99 kNoCause); 100 101 // getprop() accepts only one parameter. 102 expect(nullptr, "getprop()", kArgsParsingFailure); 103 expect(nullptr, "getprop(\"arg1\", \"arg2\")", kArgsParsingFailure); 104 } 105 106 TEST_F(UpdaterTest, sha1_check) { 107 // sha1_check(data) returns the SHA-1 of the data. 108 expect("81fe8bfe87576c3ecb22426f8e57847382917acf", "sha1_check(\"abcd\")", kNoCause); 109 expect("da39a3ee5e6b4b0d3255bfef95601890afd80709", "sha1_check(\"\")", kNoCause); 110 111 // sha1_check(data, sha1_hex, [sha1_hex, ...]) returns the matched SHA-1. 112 expect("81fe8bfe87576c3ecb22426f8e57847382917acf", 113 "sha1_check(\"abcd\", \"81fe8bfe87576c3ecb22426f8e57847382917acf\")", 114 kNoCause); 115 116 expect("81fe8bfe87576c3ecb22426f8e57847382917acf", 117 "sha1_check(\"abcd\", \"wrong_sha1\", \"81fe8bfe87576c3ecb22426f8e57847382917acf\")", 118 kNoCause); 119 120 // Or "" if there's no match. 121 expect("", 122 "sha1_check(\"abcd\", \"wrong_sha1\")", 123 kNoCause); 124 125 expect("", 126 "sha1_check(\"abcd\", \"wrong_sha1\", \"wrong_sha2\")", 127 kNoCause); 128 129 // sha1_check() expects at least one argument. 130 expect(nullptr, "sha1_check()", kArgsParsingFailure); 131 } 132 133 TEST_F(UpdaterTest, apply_patch_check) { 134 // Zero-argument is not valid. 135 expect(nullptr, "apply_patch_check()", kArgsParsingFailure); 136 137 // File not found. 138 expect("", "apply_patch_check(\"/doesntexist\")", kNoCause); 139 140 std::string src_file = from_testdata_base("old.file"); 141 std::string src_content; 142 ASSERT_TRUE(android::base::ReadFileToString(src_file, &src_content)); 143 size_t src_size = src_content.size(); 144 std::string src_hash = get_sha1(src_content); 145 146 // One-argument with EMMC:file:size:sha1 should pass the check. 147 std::string filename = android::base::Join( 148 std::vector<std::string>{ "EMMC", src_file, std::to_string(src_size), src_hash }, ":"); 149 std::string cmd = "apply_patch_check(\"" + filename + "\")"; 150 expect("t", cmd.c_str(), kNoCause); 151 152 // EMMC:file:(size-1):sha1:(size+1):sha1 should fail the check. 153 std::string filename_bad = android::base::Join( 154 std::vector<std::string>{ "EMMC", src_file, std::to_string(src_size - 1), src_hash, 155 std::to_string(src_size + 1), src_hash }, 156 ":"); 157 cmd = "apply_patch_check(\"" + filename_bad + "\")"; 158 expect("", cmd.c_str(), kNoCause); 159 160 // EMMC:file:(size-1):sha1:size:sha1:(size+1):sha1 should pass the check. 161 filename_bad = 162 android::base::Join(std::vector<std::string>{ "EMMC", src_file, std::to_string(src_size - 1), 163 src_hash, std::to_string(src_size), src_hash, 164 std::to_string(src_size + 1), src_hash }, 165 ":"); 166 cmd = "apply_patch_check(\"" + filename_bad + "\")"; 167 expect("t", cmd.c_str(), kNoCause); 168 169 // Multiple arguments. 170 cmd = "apply_patch_check(\"" + filename + "\", \"wrong_sha1\", \"wrong_sha2\")"; 171 expect("", cmd.c_str(), kNoCause); 172 173 cmd = "apply_patch_check(\"" + filename + "\", \"wrong_sha1\", \"" + src_hash + 174 "\", \"wrong_sha2\")"; 175 expect("t", cmd.c_str(), kNoCause); 176 177 cmd = "apply_patch_check(\"" + filename_bad + "\", \"wrong_sha1\", \"" + src_hash + 178 "\", \"wrong_sha2\")"; 179 expect("t", cmd.c_str(), kNoCause); 180 } 181 182 TEST_F(UpdaterTest, file_getprop) { 183 // file_getprop() expects two arguments. 184 expect(nullptr, "file_getprop()", kArgsParsingFailure); 185 expect(nullptr, "file_getprop(\"arg1\")", kArgsParsingFailure); 186 expect(nullptr, "file_getprop(\"arg1\", \"arg2\", \"arg3\")", kArgsParsingFailure); 187 188 // File doesn't exist. 189 expect(nullptr, "file_getprop(\"/doesntexist\", \"key1\")", kFileGetPropFailure); 190 191 // Reject too large files (current limit = 65536). 192 TemporaryFile temp_file1; 193 std::string buffer(65540, '\0'); 194 ASSERT_TRUE(android::base::WriteStringToFile(buffer, temp_file1.path)); 195 196 // Read some keys. 197 TemporaryFile temp_file2; 198 std::string content("ro.product.name=tardis\n" 199 "# comment\n\n\n" 200 "ro.product.model\n" 201 "ro.product.board = magic \n"); 202 ASSERT_TRUE(android::base::WriteStringToFile(content, temp_file2.path)); 203 204 std::string script1("file_getprop(\"" + std::string(temp_file2.path) + 205 "\", \"ro.product.name\")"); 206 expect("tardis", script1.c_str(), kNoCause); 207 208 std::string script2("file_getprop(\"" + std::string(temp_file2.path) + 209 "\", \"ro.product.board\")"); 210 expect("magic", script2.c_str(), kNoCause); 211 212 // No match. 213 std::string script3("file_getprop(\"" + std::string(temp_file2.path) + 214 "\", \"ro.product.wrong\")"); 215 expect("", script3.c_str(), kNoCause); 216 217 std::string script4("file_getprop(\"" + std::string(temp_file2.path) + 218 "\", \"ro.product.name=\")"); 219 expect("", script4.c_str(), kNoCause); 220 221 std::string script5("file_getprop(\"" + std::string(temp_file2.path) + 222 "\", \"ro.product.nam\")"); 223 expect("", script5.c_str(), kNoCause); 224 225 std::string script6("file_getprop(\"" + std::string(temp_file2.path) + 226 "\", \"ro.product.model\")"); 227 expect("", script6.c_str(), kNoCause); 228 } 229 230 // TODO: Test extracting to block device. 231 TEST_F(UpdaterTest, package_extract_file) { 232 // package_extract_file expects 1 or 2 arguments. 233 expect(nullptr, "package_extract_file()", kArgsParsingFailure); 234 expect(nullptr, "package_extract_file(\"arg1\", \"arg2\", \"arg3\")", kArgsParsingFailure); 235 236 std::string zip_path = from_testdata_base("ziptest_valid.zip"); 237 ZipArchiveHandle handle; 238 ASSERT_EQ(0, OpenArchive(zip_path.c_str(), &handle)); 239 240 // Need to set up the ziphandle. 241 UpdaterInfo updater_info; 242 updater_info.package_zip = handle; 243 244 // Two-argument version. 245 TemporaryFile temp_file1; 246 std::string script("package_extract_file(\"a.txt\", \"" + std::string(temp_file1.path) + "\")"); 247 expect("t", script.c_str(), kNoCause, &updater_info); 248 249 // Verify the extracted entry. 250 std::string data; 251 ASSERT_TRUE(android::base::ReadFileToString(temp_file1.path, &data)); 252 ASSERT_EQ(kATxtContents, data); 253 254 // Now extract another entry to the same location, which should overwrite. 255 script = "package_extract_file(\"b.txt\", \"" + std::string(temp_file1.path) + "\")"; 256 expect("t", script.c_str(), kNoCause, &updater_info); 257 258 ASSERT_TRUE(android::base::ReadFileToString(temp_file1.path, &data)); 259 ASSERT_EQ(kBTxtContents, data); 260 261 // Missing zip entry. The two-argument version doesn't abort. 262 script = "package_extract_file(\"doesntexist\", \"" + std::string(temp_file1.path) + "\")"; 263 expect("", script.c_str(), kNoCause, &updater_info); 264 265 // Extract to /dev/full should fail. 266 script = "package_extract_file(\"a.txt\", \"/dev/full\")"; 267 expect("", script.c_str(), kNoCause, &updater_info); 268 269 // One-argument version. 270 script = "sha1_check(package_extract_file(\"a.txt\"))"; 271 expect(kATxtSha1Sum.c_str(), script.c_str(), kNoCause, &updater_info); 272 273 script = "sha1_check(package_extract_file(\"b.txt\"))"; 274 expect(kBTxtSha1Sum.c_str(), script.c_str(), kNoCause, &updater_info); 275 276 // Missing entry. The one-argument version aborts the evaluation. 277 script = "package_extract_file(\"doesntexist\")"; 278 expect(nullptr, script.c_str(), kPackageExtractFileFailure, &updater_info); 279 280 CloseArchive(handle); 281 } 282 283 TEST_F(UpdaterTest, write_value) { 284 // write_value() expects two arguments. 285 expect(nullptr, "write_value()", kArgsParsingFailure); 286 expect(nullptr, "write_value(\"arg1\")", kArgsParsingFailure); 287 expect(nullptr, "write_value(\"arg1\", \"arg2\", \"arg3\")", kArgsParsingFailure); 288 289 // filename cannot be empty. 290 expect(nullptr, "write_value(\"value\", \"\")", kArgsParsingFailure); 291 292 // Write some value to file. 293 TemporaryFile temp_file; 294 std::string value = "magicvalue"; 295 std::string script("write_value(\"" + value + "\", \"" + std::string(temp_file.path) + "\")"); 296 expect("t", script.c_str(), kNoCause); 297 298 // Verify the content. 299 std::string content; 300 ASSERT_TRUE(android::base::ReadFileToString(temp_file.path, &content)); 301 ASSERT_EQ(value, content); 302 303 // Allow writing empty string. 304 script = "write_value(\"\", \"" + std::string(temp_file.path) + "\")"; 305 expect("t", script.c_str(), kNoCause); 306 307 // Verify the content. 308 ASSERT_TRUE(android::base::ReadFileToString(temp_file.path, &content)); 309 ASSERT_EQ("", content); 310 311 // It should fail gracefully when write fails. 312 script = "write_value(\"value\", \"/proc/0/file1\")"; 313 expect("", script.c_str(), kNoCause); 314 } 315 316 TEST_F(UpdaterTest, get_stage) { 317 // get_stage() expects one argument. 318 expect(nullptr, "get_stage()", kArgsParsingFailure); 319 expect(nullptr, "get_stage(\"arg1\", \"arg2\")", kArgsParsingFailure); 320 expect(nullptr, "get_stage(\"arg1\", \"arg2\", \"arg3\")", kArgsParsingFailure); 321 322 // Set up a local file as BCB. 323 TemporaryFile tf; 324 std::string temp_file(tf.path); 325 bootloader_message boot; 326 strlcpy(boot.stage, "2/3", sizeof(boot.stage)); 327 std::string err; 328 ASSERT_TRUE(write_bootloader_message_to(boot, temp_file, &err)); 329 330 // Can read the stage value. 331 std::string script("get_stage(\"" + temp_file + "\")"); 332 expect("2/3", script.c_str(), kNoCause); 333 334 // Bad BCB path. 335 script = "get_stage(\"doesntexist\")"; 336 expect("", script.c_str(), kNoCause); 337 } 338 339 TEST_F(UpdaterTest, set_stage) { 340 // set_stage() expects two arguments. 341 expect(nullptr, "set_stage()", kArgsParsingFailure); 342 expect(nullptr, "set_stage(\"arg1\")", kArgsParsingFailure); 343 expect(nullptr, "set_stage(\"arg1\", \"arg2\", \"arg3\")", kArgsParsingFailure); 344 345 // Set up a local file as BCB. 346 TemporaryFile tf; 347 std::string temp_file(tf.path); 348 bootloader_message boot; 349 strlcpy(boot.command, "command", sizeof(boot.command)); 350 strlcpy(boot.stage, "2/3", sizeof(boot.stage)); 351 std::string err; 352 ASSERT_TRUE(write_bootloader_message_to(boot, temp_file, &err)); 353 354 // Write with set_stage(). 355 std::string script("set_stage(\"" + temp_file + "\", \"1/3\")"); 356 expect(tf.path, script.c_str(), kNoCause); 357 358 // Verify. 359 bootloader_message boot_verify; 360 ASSERT_TRUE(read_bootloader_message_from(&boot_verify, temp_file, &err)); 361 362 // Stage should be updated, with command part untouched. 363 ASSERT_STREQ("1/3", boot_verify.stage); 364 ASSERT_STREQ(boot.command, boot_verify.command); 365 366 // Bad BCB path. 367 script = "set_stage(\"doesntexist\", \"1/3\")"; 368 expect("", script.c_str(), kNoCause); 369 370 script = "set_stage(\"/dev/full\", \"1/3\")"; 371 expect("", script.c_str(), kNoCause); 372 } 373 374 TEST_F(UpdaterTest, set_progress) { 375 // set_progress() expects one argument. 376 expect(nullptr, "set_progress()", kArgsParsingFailure); 377 expect(nullptr, "set_progress(\"arg1\", \"arg2\")", kArgsParsingFailure); 378 379 // Invalid progress argument. 380 expect(nullptr, "set_progress(\"arg1\")", kArgsParsingFailure); 381 expect(nullptr, "set_progress(\"3x+5\")", kArgsParsingFailure); 382 expect(nullptr, "set_progress(\".3.5\")", kArgsParsingFailure); 383 384 TemporaryFile tf; 385 UpdaterInfo updater_info; 386 updater_info.cmd_pipe = fdopen(tf.fd, "w"); 387 expect(".52", "set_progress(\".52\")", kNoCause, &updater_info); 388 fflush(updater_info.cmd_pipe); 389 390 std::string cmd; 391 ASSERT_TRUE(android::base::ReadFileToString(tf.path, &cmd)); 392 ASSERT_EQ(android::base::StringPrintf("set_progress %f\n", .52), cmd); 393 // recovery-updater protocol expects 2 tokens ("set_progress <frac>"). 394 ASSERT_EQ(2U, android::base::Split(cmd, " ").size()); 395 } 396 397 TEST_F(UpdaterTest, show_progress) { 398 // show_progress() expects two arguments. 399 expect(nullptr, "show_progress()", kArgsParsingFailure); 400 expect(nullptr, "show_progress(\"arg1\")", kArgsParsingFailure); 401 expect(nullptr, "show_progress(\"arg1\", \"arg2\", \"arg3\")", kArgsParsingFailure); 402 403 // Invalid progress arguments. 404 expect(nullptr, "show_progress(\"arg1\", \"arg2\")", kArgsParsingFailure); 405 expect(nullptr, "show_progress(\"3x+5\", \"10\")", kArgsParsingFailure); 406 expect(nullptr, "show_progress(\".3\", \"5a\")", kArgsParsingFailure); 407 408 TemporaryFile tf; 409 UpdaterInfo updater_info; 410 updater_info.cmd_pipe = fdopen(tf.fd, "w"); 411 expect(".52", "show_progress(\".52\", \"10\")", kNoCause, &updater_info); 412 fflush(updater_info.cmd_pipe); 413 414 std::string cmd; 415 ASSERT_TRUE(android::base::ReadFileToString(tf.path, &cmd)); 416 ASSERT_EQ(android::base::StringPrintf("progress %f %d\n", .52, 10), cmd); 417 // recovery-updater protocol expects 3 tokens ("progress <frac> <secs>"). 418 ASSERT_EQ(3U, android::base::Split(cmd, " ").size()); 419 } 420 421 TEST_F(UpdaterTest, block_image_update) { 422 // Create a zip file with new_data and patch_data. 423 TemporaryFile zip_file; 424 FILE* zip_file_ptr = fdopen(zip_file.fd, "wb"); 425 ZipWriter zip_writer(zip_file_ptr); 426 427 // Add a dummy new data. 428 ASSERT_EQ(0, zip_writer.StartEntry("new_data", 0)); 429 ASSERT_EQ(0, zip_writer.FinishEntry()); 430 431 // Generate and add the patch data. 432 std::string src_content = std::string(4096, 'a') + std::string(4096, 'c'); 433 std::string tgt_content = std::string(4096, 'b') + std::string(4096, 'd'); 434 TemporaryFile patch_file; 435 ASSERT_EQ(0, bsdiff::bsdiff(reinterpret_cast<const uint8_t*>(src_content.data()), 436 src_content.size(), reinterpret_cast<const uint8_t*>(tgt_content.data()), 437 tgt_content.size(), patch_file.path, nullptr)); 438 std::string patch_content; 439 ASSERT_TRUE(android::base::ReadFileToString(patch_file.path, &patch_content)); 440 ASSERT_EQ(0, zip_writer.StartEntry("patch_data", 0)); 441 ASSERT_EQ(0, zip_writer.WriteBytes(patch_content.data(), patch_content.size())); 442 ASSERT_EQ(0, zip_writer.FinishEntry()); 443 444 // Add two transfer lists. The first one contains a bsdiff; and we expect the update to succeed. 445 std::string src_hash = get_sha1(src_content); 446 std::string tgt_hash = get_sha1(tgt_content); 447 std::vector<std::string> transfer_list = { 448 "4", 449 "2", 450 "0", 451 "2", 452 "stash " + src_hash + " 2,0,2", 453 android::base::StringPrintf("bsdiff 0 %zu %s %s 2,0,2 2 - %s:2,0,2", patch_content.size(), 454 src_hash.c_str(), tgt_hash.c_str(), src_hash.c_str()), 455 "free " + src_hash, 456 }; 457 ASSERT_EQ(0, zip_writer.StartEntry("transfer_list", 0)); 458 std::string commands = android::base::Join(transfer_list, '\n'); 459 ASSERT_EQ(0, zip_writer.WriteBytes(commands.data(), commands.size())); 460 ASSERT_EQ(0, zip_writer.FinishEntry()); 461 462 // Stash and free some blocks, then fail the 2nd update intentionally. 463 std::vector<std::string> fail_transfer_list = { 464 "4", 465 "2", 466 "0", 467 "2", 468 "stash " + tgt_hash + " 2,0,2", 469 "free " + tgt_hash, 470 "fail", 471 }; 472 ASSERT_EQ(0, zip_writer.StartEntry("fail_transfer_list", 0)); 473 std::string fail_commands = android::base::Join(fail_transfer_list, '\n'); 474 ASSERT_EQ(0, zip_writer.WriteBytes(fail_commands.data(), fail_commands.size())); 475 ASSERT_EQ(0, zip_writer.FinishEntry()); 476 ASSERT_EQ(0, zip_writer.Finish()); 477 ASSERT_EQ(0, fclose(zip_file_ptr)); 478 479 MemMapping map; 480 ASSERT_TRUE(map.MapFile(zip_file.path)); 481 ZipArchiveHandle handle; 482 ASSERT_EQ(0, OpenArchiveFromMemory(map.addr, map.length, zip_file.path, &handle)); 483 484 // Set up the handler, command_pipe, patch offset & length. 485 UpdaterInfo updater_info; 486 updater_info.package_zip = handle; 487 TemporaryFile temp_pipe; 488 updater_info.cmd_pipe = fopen(temp_pipe.path, "wbe"); 489 updater_info.package_zip_addr = map.addr; 490 updater_info.package_zip_len = map.length; 491 492 // Execute the commands in the 1st transfer list. 493 TemporaryFile update_file; 494 ASSERT_TRUE(android::base::WriteStringToFile(src_content, update_file.path)); 495 std::string script = "block_image_update(\"" + std::string(update_file.path) + 496 R"(", package_extract_file("transfer_list"), "new_data", "patch_data"))"; 497 expect("t", script.c_str(), kNoCause, &updater_info); 498 // The update_file should be patched correctly. 499 std::string updated_content; 500 ASSERT_TRUE(android::base::ReadFileToString(update_file.path, &updated_content)); 501 ASSERT_EQ(tgt_hash, get_sha1(updated_content)); 502 503 // Expect the 2nd update to fail, but expect the stashed blocks to be freed. 504 script = "block_image_update(\"" + std::string(update_file.path) + 505 R"(", package_extract_file("fail_transfer_list"), "new_data", "patch_data"))"; 506 expect("", script.c_str(), kNoCause, &updater_info); 507 // Updater generates the stash name based on the input file name. 508 std::string name_digest = get_sha1(update_file.path); 509 std::string stash_base = "/cache/recovery/" + name_digest; 510 ASSERT_EQ(0, access(stash_base.c_str(), F_OK)); 511 ASSERT_EQ(-1, access((stash_base + tgt_hash).c_str(), F_OK)); 512 ASSERT_EQ(0, rmdir(stash_base.c_str())); 513 514 ASSERT_EQ(0, fclose(updater_info.cmd_pipe)); 515 CloseArchive(handle); 516 } 517 518 TEST_F(UpdaterTest, new_data_short_write) { 519 // Create a zip file with new_data. 520 TemporaryFile zip_file; 521 FILE* zip_file_ptr = fdopen(zip_file.fd, "wb"); 522 ZipWriter zip_writer(zip_file_ptr); 523 524 // Add the empty new data. 525 ASSERT_EQ(0, zip_writer.StartEntry("empty_new_data", 0)); 526 ASSERT_EQ(0, zip_writer.FinishEntry()); 527 // Add the short written new data. 528 ASSERT_EQ(0, zip_writer.StartEntry("short_new_data", 0)); 529 std::string new_data_short = std::string(10, 'a'); 530 ASSERT_EQ(0, zip_writer.WriteBytes(new_data_short.data(), new_data_short.size())); 531 ASSERT_EQ(0, zip_writer.FinishEntry()); 532 // Add the data of exactly one block. 533 ASSERT_EQ(0, zip_writer.StartEntry("exact_new_data", 0)); 534 std::string new_data_exact = std::string(4096, 'a'); 535 ASSERT_EQ(0, zip_writer.WriteBytes(new_data_exact.data(), new_data_exact.size())); 536 ASSERT_EQ(0, zip_writer.FinishEntry()); 537 // Add a dummy patch data. 538 ASSERT_EQ(0, zip_writer.StartEntry("patch_data", 0)); 539 ASSERT_EQ(0, zip_writer.FinishEntry()); 540 541 std::vector<std::string> transfer_list = { 542 "4", 543 "1", 544 "0", 545 "0", 546 "new 2,0,1", 547 }; 548 ASSERT_EQ(0, zip_writer.StartEntry("transfer_list", 0)); 549 std::string commands = android::base::Join(transfer_list, '\n'); 550 ASSERT_EQ(0, zip_writer.WriteBytes(commands.data(), commands.size())); 551 ASSERT_EQ(0, zip_writer.FinishEntry()); 552 ASSERT_EQ(0, zip_writer.Finish()); 553 ASSERT_EQ(0, fclose(zip_file_ptr)); 554 555 MemMapping map; 556 ASSERT_TRUE(map.MapFile(zip_file.path)); 557 ZipArchiveHandle handle; 558 ASSERT_EQ(0, OpenArchiveFromMemory(map.addr, map.length, zip_file.path, &handle)); 559 560 // Set up the handler, command_pipe, patch offset & length. 561 UpdaterInfo updater_info; 562 updater_info.package_zip = handle; 563 TemporaryFile temp_pipe; 564 updater_info.cmd_pipe = fopen(temp_pipe.path, "wbe"); 565 updater_info.package_zip_addr = map.addr; 566 updater_info.package_zip_len = map.length; 567 568 // Updater should report the failure gracefully rather than stuck in deadlock. 569 TemporaryFile update_file; 570 std::string script_empty_data = "block_image_update(\"" + std::string(update_file.path) + 571 R"(", package_extract_file("transfer_list"), "empty_new_data", "patch_data"))"; 572 expect("", script_empty_data.c_str(), kNoCause, &updater_info); 573 574 std::string script_short_data = "block_image_update(\"" + std::string(update_file.path) + 575 R"(", package_extract_file("transfer_list"), "short_new_data", "patch_data"))"; 576 expect("", script_short_data.c_str(), kNoCause, &updater_info); 577 578 // Expect to write 1 block of new data successfully. 579 std::string script_exact_data = "block_image_update(\"" + std::string(update_file.path) + 580 R"(", package_extract_file("transfer_list"), "exact_new_data", "patch_data"))"; 581 expect("t", script_exact_data.c_str(), kNoCause, &updater_info); 582 CloseArchive(handle); 583 } 584 585 TEST_F(UpdaterTest, brotli_new_data) { 586 // Create a zip file with new_data. 587 TemporaryFile zip_file; 588 FILE* zip_file_ptr = fdopen(zip_file.fd, "wb"); 589 ZipWriter zip_writer(zip_file_ptr); 590 591 // Add a brotli compressed new data entry. 592 ASSERT_EQ(0, zip_writer.StartEntry("new.dat.br", 0)); 593 594 auto generator = []() { return rand() % 128; }; 595 // Generate 100 blocks of random data. 596 std::string brotli_new_data; 597 brotli_new_data.reserve(4096 * 100); 598 generate_n(back_inserter(brotli_new_data), 4096 * 100, generator); 599 600 size_t encoded_size = BrotliEncoderMaxCompressedSize(brotli_new_data.size()); 601 std::vector<uint8_t> encoded_data(encoded_size); 602 ASSERT_TRUE(BrotliEncoderCompress( 603 BROTLI_DEFAULT_QUALITY, BROTLI_DEFAULT_WINDOW, BROTLI_DEFAULT_MODE, brotli_new_data.size(), 604 reinterpret_cast<const uint8_t*>(brotli_new_data.data()), &encoded_size, encoded_data.data())); 605 606 ASSERT_EQ(0, zip_writer.WriteBytes(encoded_data.data(), encoded_size)); 607 ASSERT_EQ(0, zip_writer.FinishEntry()); 608 // Add a dummy patch data. 609 ASSERT_EQ(0, zip_writer.StartEntry("patch_data", 0)); 610 ASSERT_EQ(0, zip_writer.FinishEntry()); 611 612 // Write a few small chunks of new data, then a large chunk, and finally a few small chunks. 613 // This helps us to catch potential short writes. 614 std::vector<std::string> transfer_list = { 615 "4", 616 "100", 617 "0", 618 "0", 619 "new 2,0,1", 620 "new 2,1,2", 621 "new 4,2,50,50,97", 622 "new 2,97,98", 623 "new 2,98,99", 624 "new 2,99,100", 625 }; 626 ASSERT_EQ(0, zip_writer.StartEntry("transfer_list", 0)); 627 std::string commands = android::base::Join(transfer_list, '\n'); 628 ASSERT_EQ(0, zip_writer.WriteBytes(commands.data(), commands.size())); 629 ASSERT_EQ(0, zip_writer.FinishEntry()); 630 ASSERT_EQ(0, zip_writer.Finish()); 631 ASSERT_EQ(0, fclose(zip_file_ptr)); 632 633 MemMapping map; 634 ASSERT_TRUE(map.MapFile(zip_file.path)); 635 ZipArchiveHandle handle; 636 ASSERT_EQ(0, OpenArchiveFromMemory(map.addr, map.length, zip_file.path, &handle)); 637 638 // Set up the handler, command_pipe, patch offset & length. 639 UpdaterInfo updater_info; 640 updater_info.package_zip = handle; 641 TemporaryFile temp_pipe; 642 updater_info.cmd_pipe = fopen(temp_pipe.path, "wb"); 643 updater_info.package_zip_addr = map.addr; 644 updater_info.package_zip_len = map.length; 645 646 // Check if we can decompress the new data correctly. 647 TemporaryFile update_file; 648 std::string script_new_data = 649 "block_image_update(\"" + std::string(update_file.path) + 650 R"(", package_extract_file("transfer_list"), "new.dat.br", "patch_data"))"; 651 expect("t", script_new_data.c_str(), kNoCause, &updater_info); 652 653 std::string updated_content; 654 ASSERT_TRUE(android::base::ReadFileToString(update_file.path, &updated_content)); 655 ASSERT_EQ(brotli_new_data, updated_content); 656 CloseArchive(handle); 657 } 658