OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "third_party/zlib/google/zip_reader.h" | 5 #include "third_party/zlib/google/zip_reader.h" |
6 | 6 |
7 #include <utility> | 7 #include <utility> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/files/file.h" | 10 #include "base/files/file.h" |
(...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
283 path_in_zip.AsUTF8Unsafe().c_str(), | 283 path_in_zip.AsUTF8Unsafe().c_str(), |
284 kDefaultCaseSensivityOfOS); | 284 kDefaultCaseSensivityOfOS); |
285 if (result != UNZ_OK) | 285 if (result != UNZ_OK) |
286 return false; | 286 return false; |
287 | 287 |
288 // Then Open the entry. | 288 // Then Open the entry. |
289 return OpenCurrentEntryInZip(); | 289 return OpenCurrentEntryInZip(); |
290 } | 290 } |
291 | 291 |
292 bool ZipReader::ExtractCurrentEntry(WriterDelegate* delegate) const { | 292 bool ZipReader::ExtractCurrentEntry(WriterDelegate* delegate) const { |
| 293 return ExtractFromBeginningOfCurrentEntry(delegate, -1); |
| 294 } |
| 295 |
| 296 bool ZipReader::ExtractFromBeginningOfCurrentEntry( |
| 297 WriterDelegate* delegate, |
| 298 int64_t num_bytes_to_extract) const { |
293 DCHECK(zip_file_); | 299 DCHECK(zip_file_); |
294 | 300 |
295 const int open_result = unzOpenCurrentFile(zip_file_); | 301 const int open_result = unzOpenCurrentFile(zip_file_); |
296 if (open_result != UNZ_OK) | 302 if (open_result != UNZ_OK) |
297 return false; | 303 return false; |
298 | 304 |
299 if (!delegate->PrepareOutput()) | 305 if (!delegate->PrepareOutput()) |
300 return false; | 306 return false; |
301 | 307 |
302 bool success = true; // This becomes false when something bad happens. | 308 bool success = true; // This becomes false when something bad happens. |
303 std::unique_ptr<char[]> buf(new char[internal::kZipBufSize]); | 309 std::unique_ptr<char[]> buf(new char[internal::kZipBufSize]); |
| 310 uint64_t total_num_bytes_read = 0; |
304 while (true) { | 311 while (true) { |
305 const int num_bytes_read = unzReadCurrentFile(zip_file_, buf.get(), | 312 uint64_t bytes_to_read = internal::kZipBufSize; |
306 internal::kZipBufSize); | 313 // This should never result in a negative value, as |num_bytes_to_extract| |
| 314 // will always be greater than |total_num_bytes_read|. |
| 315 if (num_bytes_to_extract >= 0) { |
| 316 auto unread_bytes = |
| 317 base::CheckedNumeric<uint64_t>( |
| 318 base::checked_cast<uint64_t>(num_bytes_to_extract)) - |
| 319 total_num_bytes_read; |
| 320 if (unread_bytes.ValueOrDie() < internal::kZipBufSize) { |
| 321 bytes_to_read = unread_bytes.ValueOrDie(); |
| 322 } |
| 323 } |
| 324 |
| 325 const int num_bytes_read = |
| 326 unzReadCurrentFile(zip_file_, buf.get(), bytes_to_read); |
| 327 |
307 if (num_bytes_read == 0) { | 328 if (num_bytes_read == 0) { |
308 // Reached the end of the file. | 329 // Reached the end of the file. Return true if entire file was supposed to |
309 break; | 330 // be read, false if not. |
| 331 if (num_bytes_to_extract == -1) { |
| 332 success = true; |
| 333 break; |
| 334 } else { |
| 335 success = false; |
| 336 break; |
| 337 } |
310 } else if (num_bytes_read < 0) { | 338 } else if (num_bytes_read < 0) { |
311 // If num_bytes_read < 0, then it's a specific UNZ_* error code. | 339 // If num_bytes_read < 0, then it's a specific UNZ_* error code. |
312 success = false; | 340 success = false; |
313 break; | 341 break; |
314 } else if (num_bytes_read > 0) { | 342 } else if (num_bytes_read > 0) { |
315 // Some data is read. | 343 // Some data is read. |
316 if (!delegate->WriteBytes(buf.get(), num_bytes_read)) { | 344 if (!delegate->WriteBytes(buf.get(), num_bytes_read)) { |
317 success = false; | 345 success = false; |
318 break; | 346 break; |
319 } | 347 } |
320 } | 348 } |
| 349 // Previous check ensures that num_bytes_read is not negative here. |
| 350 total_num_bytes_read += base::checked_cast<uint64_t>(num_bytes_read); |
| 351 if (num_bytes_to_extract >= 0 && |
| 352 total_num_bytes_read == |
| 353 base::checked_cast<uint64_t>(num_bytes_to_extract)) { |
| 354 // Read all the data. |
| 355 break; |
| 356 } |
321 } | 357 } |
322 | 358 |
323 unzCloseCurrentFile(zip_file_); | 359 unzCloseCurrentFile(zip_file_); |
324 | 360 |
325 return success; | 361 return success; |
326 } | 362 } |
327 | 363 |
328 bool ZipReader::ExtractCurrentEntryToFilePath( | 364 bool ZipReader::ExtractCurrentEntryToFilePath( |
329 const base::FilePath& output_file_path) const { | 365 const base::FilePath& output_file_path) const { |
330 DCHECK(zip_file_); | 366 DCHECK(zip_file_); |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
414 // false. | 450 // false. |
415 if (current_entry_info()->is_directory()) | 451 if (current_entry_info()->is_directory()) |
416 return false; | 452 return false; |
417 | 453 |
418 FileWriterDelegate writer(file); | 454 FileWriterDelegate writer(file); |
419 return ExtractCurrentEntry(&writer); | 455 return ExtractCurrentEntry(&writer); |
420 } | 456 } |
421 | 457 |
422 bool ZipReader::ExtractCurrentEntryToString(size_t max_read_bytes, | 458 bool ZipReader::ExtractCurrentEntryToString(size_t max_read_bytes, |
423 std::string* output) const { | 459 std::string* output) const { |
| 460 return ExtractFromBeginningOfCurrentEntryToString(max_read_bytes, true, |
| 461 output); |
| 462 } |
| 463 |
| 464 bool ZipReader::ExtractFromBeginningOfCurrentEntryToString( |
| 465 size_t num_bytes, |
| 466 bool read_entire_file, |
| 467 std::string* output) const { |
424 DCHECK(output); | 468 DCHECK(output); |
425 DCHECK(zip_file_); | 469 DCHECK(zip_file_); |
426 DCHECK_NE(0U, max_read_bytes); | 470 |
| 471 if (num_bytes == 0) { |
| 472 output->clear(); |
| 473 return true; |
| 474 } |
427 | 475 |
428 if (current_entry_info()->is_directory()) { | 476 if (current_entry_info()->is_directory()) { |
429 output->clear(); | 477 output->clear(); |
430 return true; | 478 return true; |
431 } | 479 } |
432 | 480 |
433 // The original_size() is the best hint for the real size, so it saves | 481 // The original_size() is the best hint for the real size, so it saves |
434 // doing reallocations for the common case when the uncompressed size is | 482 // doing reallocations for the common case when the uncompressed size is |
435 // correct. However, we need to assume that the uncompressed size could be | 483 // correct. However, we need to assume that the uncompressed size could be |
436 // incorrect therefore this function needs to read as much data as possible. | 484 // incorrect therefore this function needs to read as much data as possible. |
437 std::string contents; | 485 std::string contents; |
438 contents.reserve( | 486 if (read_entire_file) { |
439 static_cast<size_t>(std::min(static_cast<int64_t>(max_read_bytes), | 487 contents.reserve( |
440 current_entry_info()->original_size()))); | 488 static_cast<size_t>(std::min(static_cast<int64_t>(num_bytes), |
| 489 current_entry_info()->original_size()))); |
| 490 } else { |
| 491 contents.reserve(num_bytes); |
| 492 } |
441 | 493 |
442 StringWriterDelegate writer(max_read_bytes, &contents); | 494 StringWriterDelegate writer(num_bytes, &contents); |
443 if (!ExtractCurrentEntry(&writer)) | 495 if (read_entire_file) { |
444 return false; | 496 if (!ExtractCurrentEntry(&writer)) { |
445 output->swap(contents); | 497 output->clear(); |
| 498 return false; |
| 499 } |
| 500 output->swap(contents); |
| 501 } else { |
| 502 if (!ExtractFromBeginningOfCurrentEntry(&writer, num_bytes)) { |
| 503 output->clear(); |
| 504 return false; |
| 505 } |
| 506 output->swap(contents); |
| 507 } |
446 return true; | 508 return true; |
447 } | 509 } |
448 | 510 |
449 bool ZipReader::OpenInternal() { | 511 bool ZipReader::OpenInternal() { |
450 DCHECK(zip_file_); | 512 DCHECK(zip_file_); |
451 | 513 |
452 unz_global_info zip_info = {}; // Zero-clear. | 514 unz_global_info zip_info = {}; // Zero-clear. |
453 if (unzGetGlobalInfo(zip_file_, &zip_info) != UNZ_OK) { | 515 if (unzGetGlobalInfo(zip_file_, &zip_info) != UNZ_OK) { |
454 return false; | 516 return false; |
455 } | 517 } |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
524 } | 586 } |
525 | 587 |
526 bool FileWriterDelegate::WriteBytes(const char* data, int num_bytes) { | 588 bool FileWriterDelegate::WriteBytes(const char* data, int num_bytes) { |
527 int bytes_written = file_->WriteAtCurrentPos(data, num_bytes); | 589 int bytes_written = file_->WriteAtCurrentPos(data, num_bytes); |
528 if (bytes_written > 0) | 590 if (bytes_written > 0) |
529 file_length_ += bytes_written; | 591 file_length_ += bytes_written; |
530 return bytes_written == num_bytes; | 592 return bytes_written == num_bytes; |
531 } | 593 } |
532 | 594 |
533 } // namespace zip | 595 } // namespace zip |
OLD | NEW |