Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(443)

Side by Side Diff: third_party/zlib/google/zip_reader.cc

Issue 2961373002: Improve Zip File Scanning on Mac (Closed)
Patch Set: minor Created 3 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « third_party/zlib/google/zip_reader.h ('k') | third_party/zlib/google/zip_reader_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
OLDNEW
« no previous file with comments | « third_party/zlib/google/zip_reader.h ('k') | third_party/zlib/google/zip_reader_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698