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 271 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
282 const int result = unzLocateFile(zip_file_, | 282 const int result = unzLocateFile(zip_file_, |
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, |
293 uint64_t num_bytes_to_extract) const { | |
293 DCHECK(zip_file_); | 294 DCHECK(zip_file_); |
294 | 295 |
295 const int open_result = unzOpenCurrentFile(zip_file_); | 296 const int open_result = unzOpenCurrentFile(zip_file_); |
296 if (open_result != UNZ_OK) | 297 if (open_result != UNZ_OK) |
297 return false; | 298 return false; |
298 | 299 |
299 if (!delegate->PrepareOutput()) | 300 if (!delegate->PrepareOutput()) |
300 return false; | 301 return false; |
302 bool entire_file_extracted = true; | |
satorux1
2017/07/27 07:05:31
start with false and set it to true only when the
mortonm
2017/07/27 18:32:00
Done.
| |
303 std::unique_ptr<char[]> buf(new char[internal::kZipBufSize]); | |
304 uint64_t total_num_bytes_read = 0; | |
305 while (true) { | |
306 uint64_t bytes_to_read = internal::kZipBufSize; | |
307 // This should never result in a negative value, as |num_bytes_to_extract| | |
308 // will always be greater than |total_num_bytes_read|. | |
309 auto unread_bytes = base::CheckedNumeric<uint64_t>(num_bytes_to_extract) - | |
310 total_num_bytes_read; | |
311 if (unread_bytes.ValueOrDie() < internal::kZipBufSize) { | |
312 bytes_to_read = unread_bytes.ValueOrDie(); | |
313 } | |
301 | 314 |
302 bool success = true; // This becomes false when something bad happens. | 315 const int num_bytes_read = |
303 std::unique_ptr<char[]> buf(new char[internal::kZipBufSize]); | 316 unzReadCurrentFile(zip_file_, buf.get(), bytes_to_read); |
304 while (true) { | 317 |
305 const int num_bytes_read = unzReadCurrentFile(zip_file_, buf.get(), | |
306 internal::kZipBufSize); | |
307 if (num_bytes_read == 0) { | 318 if (num_bytes_read == 0) { |
308 // Reached the end of the file. | 319 // Reached the end of the file without reaching |num_bytes_to_extract|. |
320 entire_file_extracted = true; | |
309 break; | 321 break; |
310 } else if (num_bytes_read < 0) { | 322 } else if (num_bytes_read < 0) { |
311 // If num_bytes_read < 0, then it's a specific UNZ_* error code. | 323 // If num_bytes_read < 0, then it's a specific UNZ_* error code. |
312 success = false; | 324 entire_file_extracted = false; |
313 break; | 325 break; |
314 } else if (num_bytes_read > 0) { | 326 } else if (num_bytes_read > 0) { |
315 // Some data is read. | 327 // Some data is read. |
316 if (!delegate->WriteBytes(buf.get(), num_bytes_read)) { | 328 if (!delegate->WriteBytes(buf.get(), num_bytes_read)) { |
317 success = false; | 329 entire_file_extracted = false; |
318 break; | 330 break; |
319 } | 331 } |
320 } | 332 } |
333 // Previous check ensures that num_bytes_read is not negative here. | |
334 total_num_bytes_read += base::checked_cast<uint64_t>(num_bytes_read); | |
335 if (total_num_bytes_read == num_bytes_to_extract) { | |
satorux1
2017/07/27 07:05:31
Special-casing this case seems tricky. Maybe we ca
satorux1
2017/07/27 07:10:28
we'd also need
if (num_bytes_to_write == 0)
mortonm
2017/07/27 18:32:00
Done.
mortonm
2017/07/27 18:32:00
Done.
| |
336 // Read as much data as was specified by |num_bytes_to_extract|. Still | |
337 // checks whether entire file has been read, since |num_bytes_to_extract| | |
338 // may or may not equal file size. | |
339 if (unzReadCurrentFile(zip_file_, buf.get(), 1) == 0) { | |
340 entire_file_extracted = true; | |
341 } else { | |
342 entire_file_extracted = false; | |
343 } | |
344 break; | |
345 } | |
321 } | 346 } |
322 | 347 |
323 unzCloseCurrentFile(zip_file_); | 348 unzCloseCurrentFile(zip_file_); |
324 | 349 |
325 return success; | 350 return entire_file_extracted; |
326 } | 351 } |
327 | 352 |
328 bool ZipReader::ExtractCurrentEntryToFilePath( | 353 bool ZipReader::ExtractCurrentEntryToFilePath( |
329 const base::FilePath& output_file_path) const { | 354 const base::FilePath& output_file_path) const { |
330 DCHECK(zip_file_); | 355 DCHECK(zip_file_); |
331 | 356 |
332 // If this is a directory, just create it and return. | 357 // If this is a directory, just create it and return. |
333 if (current_entry_info()->is_directory()) | 358 if (current_entry_info()->is_directory()) |
334 return base::CreateDirectory(output_file_path); | 359 return base::CreateDirectory(output_file_path); |
335 | 360 |
336 bool success = false; | 361 bool success = false; |
337 { | 362 { |
338 FilePathWriterDelegate writer(output_file_path); | 363 FilePathWriterDelegate writer(output_file_path); |
339 success = ExtractCurrentEntry(&writer); | 364 success = |
365 ExtractCurrentEntry(&writer, std::numeric_limits<uint64_t>::max()); | |
340 } | 366 } |
341 | 367 |
342 if (success && | 368 if (success && |
343 current_entry_info()->last_modified() != base::Time::UnixEpoch()) { | 369 current_entry_info()->last_modified() != base::Time::UnixEpoch()) { |
344 base::TouchFile(output_file_path, | 370 base::TouchFile(output_file_path, |
345 base::Time::Now(), | 371 base::Time::Now(), |
346 current_entry_info()->last_modified()); | 372 current_entry_info()->last_modified()); |
347 } | 373 } |
348 | 374 |
349 return success; | 375 return success; |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
409 | 435 |
410 bool ZipReader::ExtractCurrentEntryToFile(base::File* file) const { | 436 bool ZipReader::ExtractCurrentEntryToFile(base::File* file) const { |
411 DCHECK(zip_file_); | 437 DCHECK(zip_file_); |
412 | 438 |
413 // If this is a directory, there's nothing to extract to the file, so return | 439 // If this is a directory, there's nothing to extract to the file, so return |
414 // false. | 440 // false. |
415 if (current_entry_info()->is_directory()) | 441 if (current_entry_info()->is_directory()) |
416 return false; | 442 return false; |
417 | 443 |
418 FileWriterDelegate writer(file); | 444 FileWriterDelegate writer(file); |
419 return ExtractCurrentEntry(&writer); | 445 return ExtractCurrentEntry(&writer, std::numeric_limits<uint64_t>::max()); |
420 } | 446 } |
421 | 447 |
422 bool ZipReader::ExtractCurrentEntryToString(size_t max_read_bytes, | 448 bool ZipReader::ExtractCurrentEntryToString(uint64_t num_bytes, |
satorux1
2017/07/27 07:05:31
num_bytes -> max_read_bytes to be consistent with
mortonm
2017/07/27 18:32:00
Done.
| |
423 std::string* output) const { | 449 std::string* output) const { |
424 DCHECK(output); | 450 DCHECK(output); |
425 DCHECK(zip_file_); | 451 DCHECK(zip_file_); |
426 DCHECK_NE(0U, max_read_bytes); | 452 |
453 if (num_bytes == 0) { | |
454 output->clear(); | |
455 return true; | |
456 } | |
427 | 457 |
428 if (current_entry_info()->is_directory()) { | 458 if (current_entry_info()->is_directory()) { |
429 output->clear(); | 459 output->clear(); |
430 return true; | 460 return true; |
431 } | 461 } |
432 | 462 |
433 // The original_size() is the best hint for the real size, so it saves | 463 // 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 | 464 // doing reallocations for the common case when the uncompressed size is |
435 // correct. However, we need to assume that the uncompressed size could be | 465 // 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. | 466 // incorrect therefore this function needs to read as much data as possible. |
437 std::string contents; | 467 std::string contents; |
438 contents.reserve( | 468 contents.reserve( |
439 static_cast<size_t>(std::min(static_cast<int64_t>(max_read_bytes), | 469 static_cast<size_t>(std::min(base::checked_cast<int64_t>(num_bytes), |
440 current_entry_info()->original_size()))); | 470 current_entry_info()->original_size()))); |
441 | 471 |
442 StringWriterDelegate writer(max_read_bytes, &contents); | 472 StringWriterDelegate writer(num_bytes, &contents); |
443 if (!ExtractCurrentEntry(&writer)) | 473 if (!ExtractCurrentEntry(&writer, num_bytes)) { |
474 if (contents.length() < num_bytes) { | |
475 // There was an error in extracting entry. | |
satorux1
2017/07/27 07:05:31
I was a bit confused at first. Maybe add something
mortonm
2017/07/27 18:32:00
Done. The revised comment now explains the situati
| |
476 output->clear(); | |
477 } else { | |
478 // |num_bytes| is less than the length of current entry. | |
479 output->swap(contents); | |
480 } | |
444 return false; | 481 return false; |
482 } | |
445 output->swap(contents); | 483 output->swap(contents); |
446 return true; | 484 return true; |
447 } | 485 } |
448 | 486 |
449 bool ZipReader::OpenInternal() { | 487 bool ZipReader::OpenInternal() { |
450 DCHECK(zip_file_); | 488 DCHECK(zip_file_); |
451 | 489 |
452 unz_global_info zip_info = {}; // Zero-clear. | 490 unz_global_info zip_info = {}; // Zero-clear. |
453 if (unzGetGlobalInfo(zip_file_, &zip_info) != UNZ_OK) { | 491 if (unzGetGlobalInfo(zip_file_, &zip_info) != UNZ_OK) { |
454 return false; | 492 return false; |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
524 } | 562 } |
525 | 563 |
526 bool FileWriterDelegate::WriteBytes(const char* data, int num_bytes) { | 564 bool FileWriterDelegate::WriteBytes(const char* data, int num_bytes) { |
527 int bytes_written = file_->WriteAtCurrentPos(data, num_bytes); | 565 int bytes_written = file_->WriteAtCurrentPos(data, num_bytes); |
528 if (bytes_written > 0) | 566 if (bytes_written > 0) |
529 file_length_ += bytes_written; | 567 file_length_ += bytes_written; |
530 return bytes_written == num_bytes; | 568 return bytes_written == num_bytes; |
531 } | 569 } |
532 | 570 |
533 } // namespace zip | 571 } // namespace zip |
OLD | NEW |