summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Sepez <tsepez@chromium.org>2017-04-06 17:35:11 -0700
committerChromium commit bot <commit-bot@chromium.org>2017-04-07 16:02:27 +0000
commit1e8c39f18df6e597e079cce13d18d72631ef0fb9 (patch)
tree15e423b4cc83d4b215a5d7424a7121832221b1a8
parent03c5e1725be9f581ae80d839fd848d57b9bfa164 (diff)
downloadpdfium-1e8c39f18df6e597e079cce13d18d72631ef0fb9.tar.xz
Remove the "old way" of performing FlateUncompress.
Repeated looping over Realloc() with a linearly increasing buffer size is going to be O(N^2) which is why it was limited to small cases. But it's wrong to do it anyways, and it kicks out a lurking issue in PartitionAlloc as it turns out. See https://crbug.com/709271, but this doesn't actually fix that issue, it just avoids it. Change-Id: I39d8f8df0d5fc358b7b9caa15c507a8f57e45004 Reviewed-on: https://pdfium-review.googlesource.com/3910 Reviewed-by: Lei Zhang <thestig@chromium.org> Commit-Queue: Tom Sepez <tsepez@chromium.org>
-rw-r--r--core/fxcodec/codec/fx_codec_flate.cpp134
1 files changed, 44 insertions, 90 deletions
diff --git a/core/fxcodec/codec/fx_codec_flate.cpp b/core/fxcodec/codec/fx_codec_flate.cpp
index 2ac316100a..ef78248217 100644
--- a/core/fxcodec/codec/fx_codec_flate.cpp
+++ b/core/fxcodec/codec/fx_codec_flate.cpp
@@ -507,110 +507,64 @@ void FlateUncompress(const uint8_t* src_buf,
uint8_t*& dest_buf,
uint32_t& dest_size,
uint32_t& offset) {
- uint32_t guess_size = orig_size ? orig_size : src_size * 2;
- const uint32_t kStepSize = 10240;
- uint32_t alloc_step = orig_size ? kStepSize : std::min(src_size, kStepSize);
- static const uint32_t kMaxInitialAllocSize = 10000000;
- if (guess_size > kMaxInitialAllocSize) {
- guess_size = kMaxInitialAllocSize;
- alloc_step = kMaxInitialAllocSize;
- }
- uint32_t buf_size = guess_size;
- uint32_t last_buf_size = buf_size;
-
dest_buf = nullptr;
dest_size = 0;
void* context = FlateInit();
if (!context)
return;
- std::unique_ptr<uint8_t, FxFreeDeleter> guess_buf(
- FX_Alloc(uint8_t, guess_size + 1));
- guess_buf.get()[guess_size] = '\0';
-
FlateInput(context, src_buf, src_size);
- if (src_size < kStepSize) {
- // This is the old implementation.
- uint8_t* cur_buf = guess_buf.get();
- while (1) {
- uint32_t ret = FlateOutput(context, cur_buf, buf_size);
- if (ret != Z_OK)
- break;
- uint32_t avail_buf_size = FlateGetAvailOut(context);
- if (avail_buf_size != 0)
- break;
+ const uint32_t kMaxInitialAllocSize = 10000000;
+ uint32_t guess_size = orig_size ? orig_size : src_size * 2;
+ guess_size = std::min(guess_size, kMaxInitialAllocSize);
- uint32_t old_size = guess_size;
- guess_size += alloc_step;
- if (guess_size < old_size || guess_size + 1 < guess_size) {
- FlateEnd(context);
- return;
- }
+ uint32_t buf_size = guess_size;
+ uint32_t last_buf_size = buf_size;
+ std::unique_ptr<uint8_t, FxFreeDeleter> guess_buf(
+ FX_Alloc(uint8_t, guess_size + 1));
+ guess_buf.get()[guess_size] = '\0';
- {
- uint8_t* new_buf =
- FX_Realloc(uint8_t, guess_buf.release(), guess_size + 1);
- guess_buf.reset(new_buf);
- }
- guess_buf.get()[guess_size] = '\0';
- cur_buf = guess_buf.get() + old_size;
- buf_size = guess_size - old_size;
- }
- dest_size = FlateGetPossiblyTruncatedTotalOut(context);
- offset = FlateGetPossiblyTruncatedTotalIn(context);
- if (guess_size / 2 > dest_size) {
- {
- uint8_t* new_buf =
- FX_Realloc(uint8_t, guess_buf.release(), dest_size + 1);
- guess_buf.reset(new_buf);
- }
- guess_size = dest_size;
- guess_buf.get()[guess_size] = '\0';
- }
- dest_buf = guess_buf.release();
- } else {
- std::vector<uint8_t*> result_tmp_bufs;
- uint8_t* cur_buf = guess_buf.release();
- while (1) {
- uint32_t ret = FlateOutput(context, cur_buf, buf_size);
- uint32_t avail_buf_size = FlateGetAvailOut(context);
- if (ret != Z_OK || avail_buf_size != 0) {
- last_buf_size = buf_size - avail_buf_size;
- result_tmp_bufs.push_back(cur_buf);
- break;
- }
+ std::vector<uint8_t*> result_tmp_bufs;
+ uint8_t* cur_buf = guess_buf.release();
+ while (1) {
+ uint32_t ret = FlateOutput(context, cur_buf, buf_size);
+ uint32_t avail_buf_size = FlateGetAvailOut(context);
+ if (ret != Z_OK || avail_buf_size != 0) {
+ last_buf_size = buf_size - avail_buf_size;
result_tmp_bufs.push_back(cur_buf);
- cur_buf = FX_Alloc(uint8_t, buf_size + 1);
- cur_buf[buf_size] = '\0';
+ break;
}
+ result_tmp_bufs.push_back(cur_buf);
+ cur_buf = FX_Alloc(uint8_t, buf_size + 1);
+ cur_buf[buf_size] = '\0';
+ }
- // The TotalOut size returned from the library may not be big enough to
- // handle the content the library returns. We can only handle items
- // up to 4GB in size.
- dest_size = FlateGetPossiblyTruncatedTotalOut(context);
- offset = FlateGetPossiblyTruncatedTotalIn(context);
- if (result_tmp_bufs.size() == 1) {
- dest_buf = result_tmp_bufs[0];
- } else {
- uint8_t* result_buf = FX_Alloc(uint8_t, dest_size);
- uint32_t result_pos = 0;
- uint32_t remaining = dest_size;
- for (size_t i = 0; i < result_tmp_bufs.size(); i++) {
- uint8_t* tmp_buf = result_tmp_bufs[i];
- uint32_t tmp_buf_size = buf_size;
- if (i == result_tmp_bufs.size() - 1)
- tmp_buf_size = last_buf_size;
-
- uint32_t cp_size = std::min(tmp_buf_size, remaining);
- memcpy(result_buf + result_pos, tmp_buf, cp_size);
- result_pos += cp_size;
- remaining -= cp_size;
-
- FX_Free(result_tmp_bufs[i]);
- }
- dest_buf = result_buf;
+ // The TotalOut size returned from the library may not be big enough to
+ // handle the content the library returns. We can only handle items
+ // up to 4GB in size.
+ dest_size = FlateGetPossiblyTruncatedTotalOut(context);
+ offset = FlateGetPossiblyTruncatedTotalIn(context);
+ if (result_tmp_bufs.size() == 1) {
+ dest_buf = result_tmp_bufs[0];
+ } else {
+ uint8_t* result_buf = FX_Alloc(uint8_t, dest_size);
+ uint32_t result_pos = 0;
+ uint32_t remaining = dest_size;
+ for (size_t i = 0; i < result_tmp_bufs.size(); i++) {
+ uint8_t* tmp_buf = result_tmp_bufs[i];
+ uint32_t tmp_buf_size = buf_size;
+ if (i == result_tmp_bufs.size() - 1)
+ tmp_buf_size = last_buf_size;
+
+ uint32_t cp_size = std::min(tmp_buf_size, remaining);
+ memcpy(result_buf + result_pos, tmp_buf, cp_size);
+ result_pos += cp_size;
+ remaining -= cp_size;
+
+ FX_Free(result_tmp_bufs[i]);
}
+ dest_buf = result_buf;
}
FlateEnd(context);
}