diff options
-rw-r--r-- | src/core/SkWriter32.cpp | 16 | ||||
-rw-r--r-- | tests/Writer32Test.cpp | 14 |
2 files changed, 24 insertions, 6 deletions
diff --git a/src/core/SkWriter32.cpp b/src/core/SkWriter32.cpp index d2c85876a9..3ae6a0775c 100644 --- a/src/core/SkWriter32.cpp +++ b/src/core/SkWriter32.cpp @@ -161,6 +161,9 @@ uint32_t* SkWriter32::peek32(size_t offset) { } void SkWriter32::rewindToOffset(size_t offset) { + if (offset >= fSize) { + return; + } if (0 == offset) { this->reset(NULL, 0); return; @@ -179,19 +182,20 @@ void SkWriter32::rewindToOffset(size_t offset) { // Similar to peek32, except that we free up any following blocks Block* block = fHead; SkASSERT(NULL != block); - while (offset >= block->fAllocatedSoFar) { offset -= block->fAllocatedSoFar; block = block->fNext; SkASSERT(NULL != block); } - fTail = block; + // update the size on the "last" block block->fAllocatedSoFar = offset; - - // free up any following blocks - SkASSERT(block); - block = block->fNext; + // end our list + fTail = block; + Block* next = block->fNext; + block->fNext = NULL; + // free up any trailing blocks + block = next; while (block) { Block* next = block->fNext; sk_free(block); diff --git a/tests/Writer32Test.cpp b/tests/Writer32Test.cpp index 21c11c16c6..4715f7a613 100644 --- a/tests/Writer32Test.cpp +++ b/tests/Writer32Test.cpp @@ -37,6 +37,20 @@ static void test_rewind(skiatest::Reporter* reporter) { REPORTER_ASSERT(reporter, sizeof(array) == writer.bytesWritten()); array[2] = 3; check_contents(reporter, writer, array, sizeof(array)); + + // test rewinding past allocated chunks. This used to crash because we + // didn't truncate our link-list after freeing trailing blocks + { + SkWriter32 writer(64); + for (int i = 0; i < 100; ++i) { + writer.writeInt(i); + } + REPORTER_ASSERT(reporter, 100*4 == writer.bytesWritten()); + for (int j = 100*4; j >= 0; j -= 16) { + writer.rewindToOffset(j); + } + REPORTER_ASSERT(reporter, writer.bytesWritten() < 16); + } } static void test_ptr(skiatest::Reporter* reporter) { |