truncate our llist w/ null during rewind.
authorreed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Fri, 31 Aug 2012 20:17:56 +0000 (20:17 +0000)
committerreed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Fri, 31 Aug 2012 20:17:56 +0000 (20:17 +0000)
git-svn-id: http://skia.googlecode.com/svn/trunk@5375 2bbb7eff-a529-9590-31e7-b0007b416f81

src/core/SkWriter32.cpp
tests/Writer32Test.cpp

index d2c8587..3ae6a07 100644 (file)
@@ -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);
index 21c11c1..4715f7a 100644 (file)
@@ -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) {