Commit 281a10c5 authored by 's avatar
Browse files

Bug 882130 - In IDBObjectStore, endian swapped data are treated improperly on...

Bug 882130 - In IDBObjectStore, endian swapped data are treated improperly on big endian platform. r=janv (bitrot fixed by stevensn)
parent f6ce5da2
Loading
Loading
Loading
Loading
+25 −44
Original line number Diff line number Diff line
@@ -13,6 +13,7 @@

#include <algorithm>
#include "jsfriendapi.h"
#include "mozilla/Endian.h"
#include "mozilla/dom/ContentChild.h"
#include "mozilla/dom/ContentParent.h"
#include "mozilla/dom/FileHandleBinding.h"
@@ -56,6 +57,7 @@ using namespace mozilla::dom::indexedDB::ipc;
using mozilla::dom::quota::FileOutputStream;
using mozilla::ErrorResult;
using mozilla::fallible_t;
using mozilla::NativeEndian;

BEGIN_INDEXEDDB_NAMESPACE

@@ -1372,36 +1374,6 @@ IDBObjectStore::SerializeValue(JSContext* aCx,
  return buffer.write(aCx, aValue, &callbacks, &aCloneWriteInfo);
}

static inline uint32_t
SwapBytes(uint32_t u)
{
#ifdef IS_BIG_ENDIAN
  return ((u & 0x000000ffU) << 24) |
         ((u & 0x0000ff00U) << 8) |
         ((u & 0x00ff0000U) >> 8) |
         ((u & 0xff000000U) >> 24);
#else
  return u;
#endif
}

static inline double
SwapBytes(uint64_t u)
{
#ifdef IS_BIG_ENDIAN
  return ((u & 0x00000000000000ffLLU) << 56) |
         ((u & 0x000000000000ff00LLU) << 40) |
         ((u & 0x0000000000ff0000LLU) << 24) |
         ((u & 0x00000000ff000000LLU) << 8) |
         ((u & 0x000000ff00000000LLU) >> 8) |
         ((u & 0x0000ff0000000000LLU) >> 24) |
         ((u & 0x00ff000000000000LLU) >> 40) |
         ((u & 0xff00000000000000LLU) >> 56);
#else
  return double(u);
#endif
}

static inline bool
StructuredCloneReadString(JSStructuredCloneReader* aReader,
                          nsCString& aString)
@@ -1411,7 +1383,7 @@ StructuredCloneReadString(JSStructuredCloneReader* aReader,
    NS_WARNING("Failed to read length!");
    return false;
  }
  length = SwapBytes(length);
  length = NativeEndian::swapFromLittleEndian(length);

  if (!aString.SetLength(length, fallible_t())) {
    NS_WARNING("Out of memory?");
@@ -1474,7 +1446,7 @@ IDBObjectStore::ReadBlobOrFile(JSStructuredCloneReader* aReader,
    NS_WARNING("Failed to read size!");
    return false;
  }
  aRetval->size = SwapBytes(size);
  aRetval->size = NativeEndian::swapFromLittleEndian(size);

  nsCString type;
  if (!StructuredCloneReadString(aReader, type)) {
@@ -1490,12 +1462,17 @@ IDBObjectStore::ReadBlobOrFile(JSStructuredCloneReader* aReader,
  NS_ASSERTION(aTag == SCTAG_DOM_FILE ||
               aTag == SCTAG_DOM_FILE_WITHOUT_LASTMODIFIEDDATE, "Huh?!");

  uint64_t lastModifiedDate = UINT64_MAX;
  if (aTag != SCTAG_DOM_FILE_WITHOUT_LASTMODIFIEDDATE &&
      !JS_ReadBytes(aReader, &lastModifiedDate, sizeof(lastModifiedDate))) {
  uint64_t lastModifiedDate;
  if (aTag == SCTAG_DOM_FILE_WITHOUT_LASTMODIFIEDDATE) {
    lastModifiedDate = UINT64_MAX;
  }
  else {
    if(!JS_ReadBytes(aReader, &lastModifiedDate, sizeof(lastModifiedDate))) {
      NS_WARNING("Failed to read lastModifiedDate");
      return false;
    }
    lastModifiedDate = NativeEndian::swapFromLittleEndian(lastModifiedDate);
  }
  aRetval->lastModifiedDate = lastModifiedDate;

  nsCString name;
@@ -1585,6 +1562,7 @@ IDBObjectStore::StructuredCloneWriteCallback(JSContext* aCx,
    cloneWriteInfo->mOffsetToKeyProp = js_GetSCOffset(aWriter);

    uint64_t value = 0;
    // Omit endian swap
    return JS_WriteBytes(aWriter, &value, sizeof(value));
  }

@@ -1602,10 +1580,10 @@ IDBObjectStore::StructuredCloneWriteCallback(JSContext* aCx,
    }

    NS_ConvertUTF16toUTF8 convType(fileHandle->Type());
    uint32_t convTypeLength = SwapBytes(convType.Length());
    uint32_t convTypeLength = NativeEndian::swapToLittleEndian(convType.Length());

    NS_ConvertUTF16toUTF8 convName(fileHandle->Name());
    uint32_t convNameLength = SwapBytes(convName.Length());
    uint32_t convNameLength = NativeEndian::swapToLittleEndian(convName.Length());

    if (!JS_WriteUint32Pair(aWriter, SCTAG_DOM_FILEHANDLE,
                            cloneWriteInfo->mFiles.Length()) ||
@@ -1660,7 +1638,7 @@ IDBObjectStore::StructuredCloneWriteCallback(JSContext* aCx,
        NS_WARNING("Failed to get size!");
        return false;
      }
      size = SwapBytes(size);
      size = NativeEndian::swapToLittleEndian(size);

      nsString type;
      if (NS_FAILED(blob->GetType(type))) {
@@ -1668,7 +1646,7 @@ IDBObjectStore::StructuredCloneWriteCallback(JSContext* aCx,
        return false;
      }
      NS_ConvertUTF16toUTF8 convType(type);
      uint32_t convTypeLength = SwapBytes(convType.Length());
      uint32_t convTypeLength = NativeEndian::swapToLittleEndian(convType.Length());

      nsCOMPtr<nsIDOMFile> file = do_QueryInterface(blob);

@@ -1687,7 +1665,7 @@ IDBObjectStore::StructuredCloneWriteCallback(JSContext* aCx,
          return false;
        }

        lastModifiedDate = SwapBytes(lastModifiedDate);
        lastModifiedDate = NativeEndian::swapToLittleEndian(lastModifiedDate);

        nsString name;
        if (NS_FAILED(file->GetName(name))) {
@@ -1695,7 +1673,7 @@ IDBObjectStore::StructuredCloneWriteCallback(JSContext* aCx,
          return false;
        }
        NS_ConvertUTF16toUTF8 convName(name);
        uint32_t convNameLength = SwapBytes(convName.Length());
        uint32_t convNameLength = NativeEndian::swapToLittleEndian(convName.Length());

        if (!JS_WriteBytes(aWriter, &lastModifiedDate, sizeof(lastModifiedDate)) || 
            !JS_WriteBytes(aWriter, &convNameLength, sizeof(convNameLength)) ||
@@ -3201,7 +3179,10 @@ AddHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
        uint64_t u;
      } pun;
    
      pun.d = SwapBytes(static_cast<uint64_t>(autoIncrementNum));
      NS_ASSERTION(autoIncrementNum > 0,
                   "Generated key must always a positive integer");
      pun.d = static_cast<double>(autoIncrementNum);
      pun.u = NativeEndian::swapToLittleEndian(pun.u);

      JSAutoStructuredCloneBuffer& buffer = mCloneWriteInfo.mCloneBuffer;
      uint64_t offsetToKeyProp = mCloneWriteInfo.mOffsetToKeyProp;