Bug 529733 - Crash in nsCacheMetaData::SetElement; r=michal,jduell
authorAlfred Kayser <alfredkayser@gmail.com>
Tue, 23 Aug 2011 17:45:10 +0100
changeset 76794 72f1510e3f31ee8b9e4f717b0aefa0af14ad0265
parent 76793 4bd995181c52bbd6aebbadc1b778b8440aeb2a53
child 76795 d9859ad8932b023baef1623587f25f4ca90f9628
push id340
push userclegnitto@mozilla.com
push dateTue, 08 Nov 2011 22:56:33 +0000
treeherdermozilla-beta@f745dc151615 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmichal, jduell
bugs529733
milestone9.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 529733 - Crash in nsCacheMetaData::SetElement; r=michal,jduell
netwerk/cache/nsCacheMetaData.cpp
--- a/netwerk/cache/nsCacheMetaData.cpp
+++ b/netwerk/cache/nsCacheMetaData.cpp
@@ -46,22 +46,24 @@ const char *
 nsCacheMetaData::GetElement(const char * key)
 {
     const char * data = mBuffer;
     const char * limit = mBuffer + mMetaSize;
 
     while (data < limit) {
         // Point to the value part
         const char * value = data + strlen(data) + 1;
+        NS_ABORT_IF_FALSE(value < limit, "Cache Metadata corrupted");
         if (strcmp(data, key) == 0)
             return value;
 
         // Skip value part
         data = value + strlen(value) + 1;
     }
+    NS_ABORT_IF_FALSE(data == limit, "Metadata corrupted");
     return nsnull;
 }
 
 
 nsresult
 nsCacheMetaData::SetElement(const char * key,
                             const char * value)
 {
@@ -126,16 +128,33 @@ nsCacheMetaData::FlattenMetaData(char * 
     memcpy(buffer, mBuffer, mMetaSize);
     return NS_OK;
 }
 
 nsresult
 nsCacheMetaData::UnflattenMetaData(const char * data, PRUint32 size)
 {
     if (data && size) {
+        // Check if the metadata ends with a zero byte.
+        if (data[size-1] != '\0') {
+            NS_ERROR("Cache MetaData is not null terminated");
+            return NS_ERROR_ILLEGAL_VALUE;
+        }
+        // Check that there are an even number of zero bytes
+        // to match the pattern { key \0 value \0 }
+        PRBool odd = PR_FALSE;
+        for (int i = 0; i < size; i++) {
+            if (data[i] == '\0') 
+                odd = !odd;
+        }
+        if (odd) {
+            NS_ERROR("Cache MetaData is malformed");
+            return NS_ERROR_ILLEGAL_VALUE;
+        }
+
         nsresult rv = EnsureBuffer(size);
         NS_ENSURE_SUCCESS(rv, rv);
 
         memcpy(mBuffer, data, size);
         mMetaSize = size;
     }
     return NS_OK;
 }
@@ -145,24 +164,26 @@ nsCacheMetaData::VisitElements(nsICacheM
 {
     const char * data = mBuffer;
     const char * limit = mBuffer + mMetaSize;
 
     while (data < limit) {
         const char * key = data;
         // Skip key part
         data += strlen(data) + 1;
+        NS_ABORT_IF_FALSE(data < limit, "Metadata corrupted");
         PRBool keepGoing;
         nsresult rv = visitor->VisitMetaDataElement(key, data, &keepGoing);
         if (NS_FAILED(rv) || !keepGoing)
             break;
 
         // Skip value part
         data += strlen(data) + 1;
     }
+    NS_ABORT_IF_FALSE(data == limit, "Metadata corrupted");
     return NS_OK;
 }
 
 nsresult
 nsCacheMetaData::EnsureBuffer(PRUint32 bufSize)
 {
     if (mBufferSize < bufSize) {
         char * buf = (char *)PR_REALLOC(mBuffer, bufSize);