}
void SkWriter32::rewindToOffset(size_t offset) {
+ if (offset >= fSize) {
+ return;
+ }
if (0 == offset) {
this->reset(NULL, 0);
return;
// 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);
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) {