js/src/vm/Xdr.h

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
     2  * vim: set ts=8 sts=4 et sw=4 tw=99:
     3  * This Source Code Form is subject to the terms of the Mozilla Public
     4  * License, v. 2.0. If a copy of the MPL was not distributed with this
     5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     7 #ifndef vm_Xdr_h
     8 #define vm_Xdr_h
    10 #include "mozilla/Endian.h"
    11 #include "mozilla/TypeTraits.h"
    13 #include "jsatom.h"
    15 namespace js {
    17 /*
    18  * Bytecode version number. Increment the subtrahend whenever JS bytecode
    19  * changes incompatibly.
    20  *
    21  * This version number is XDR'd near the front of xdr bytecode and
    22  * aborts deserialization if there is a mismatch between the current
    23  * and saved versions. If deserialization fails, the data should be
    24  * invalidated if possible.
    25  */
    26 static const uint32_t XDR_BYTECODE_VERSION = uint32_t(0xb973c0de - 172);
    28 class XDRBuffer {
    29   public:
    30     XDRBuffer(JSContext *cx)
    31       : context(cx), base(nullptr), cursor(nullptr), limit(nullptr) { }
    33     JSContext *cx() const {
    34         return context;
    35     }
    37     void *getData(uint32_t *lengthp) const {
    38         JS_ASSERT(size_t(cursor - base) <= size_t(UINT32_MAX));
    39         *lengthp = uint32_t(cursor - base);
    40         return base;
    41     }
    43     void setData(const void *data, uint32_t length) {
    44         base = static_cast<uint8_t *>(const_cast<void *>(data));
    45         cursor = base;
    46         limit = base + length;
    47     }
    49     const uint8_t *read(size_t n) {
    50         JS_ASSERT(n <= size_t(limit - cursor));
    51         uint8_t *ptr = cursor;
    52         cursor += n;
    53         return ptr;
    54     }
    56     const char *readCString() {
    57         char *ptr = reinterpret_cast<char *>(cursor);
    58         cursor = reinterpret_cast<uint8_t *>(strchr(ptr, '\0')) + 1;
    59         JS_ASSERT(base < cursor);
    60         JS_ASSERT(cursor <= limit);
    61         return ptr;
    62     }
    64     uint8_t *write(size_t n) {
    65         if (n > size_t(limit - cursor)) {
    66             if (!grow(n))
    67                 return nullptr;
    68         }
    69         uint8_t *ptr = cursor;
    70         cursor += n;
    71         return ptr;
    72     }
    74     static bool isUint32Overflow(size_t n) {
    75         return size_t(-1) > size_t(UINT32_MAX) && n > size_t(UINT32_MAX);
    76     }
    78     void freeBuffer();
    80   private:
    81     bool grow(size_t n);
    83     JSContext   *const context;
    84     uint8_t     *base;
    85     uint8_t     *cursor;
    86     uint8_t     *limit;
    87 };
    89 /*
    90  * XDR serialization state.  All data is encoded in little endian.
    91  */
    92 template <XDRMode mode>
    93 class XDRState {
    94   public:
    95     XDRBuffer buf;
    97   protected:
    98     JSPrincipals *originPrincipals_;
   100     XDRState(JSContext *cx)
   101       : buf(cx), originPrincipals_(nullptr) {
   102     }
   104   public:
   105     JSContext *cx() const {
   106         return buf.cx();
   107     }
   109     JSPrincipals *originPrincipals() const {
   110         return originPrincipals_;
   111     }
   113     bool codeUint8(uint8_t *n) {
   114         if (mode == XDR_ENCODE) {
   115             uint8_t *ptr = buf.write(sizeof *n);
   116             if (!ptr)
   117                 return false;
   118             *ptr = *n;
   119         } else {
   120             *n = *buf.read(sizeof *n);
   121         }
   122         return true;
   123     }
   125     bool codeUint16(uint16_t *n) {
   126         if (mode == XDR_ENCODE) {
   127             uint8_t *ptr = buf.write(sizeof *n);
   128             if (!ptr)
   129                 return false;
   130             mozilla::LittleEndian::writeUint16(ptr, *n);
   131         } else {
   132             const uint8_t *ptr = buf.read(sizeof *n);
   133             *n = mozilla::LittleEndian::readUint16(ptr);
   134         }
   135         return true;
   136     }
   138     bool codeUint32(uint32_t *n) {
   139         if (mode == XDR_ENCODE) {
   140             uint8_t *ptr = buf.write(sizeof *n);
   141             if (!ptr)
   142                 return false;
   143             mozilla::LittleEndian::writeUint32(ptr, *n);
   144         } else {
   145             const uint8_t *ptr = buf.read(sizeof *n);
   146             *n = mozilla::LittleEndian::readUint32(ptr);
   147         }
   148         return true;
   149     }
   151     bool codeUint64(uint64_t *n) {
   152         if (mode == XDR_ENCODE) {
   153             uint8_t *ptr = buf.write(sizeof(*n));
   154             if (!ptr)
   155                 return false;
   156             mozilla::LittleEndian::writeUint64(ptr, *n);
   157         } else {
   158             const uint8_t *ptr = buf.read(sizeof(*n));
   159             *n = mozilla::LittleEndian::readUint64(ptr);
   160         }
   161         return true;
   162     }
   164     /*
   165      * Use SFINAE to refuse any specialization which is not an enum.  Uses of
   166      * this function do not have to specialize the type of the enumerated field
   167      * as C++ will extract the parameterized from the argument list.
   168      */
   169     template <typename T>
   170     bool codeEnum32(T *val, typename mozilla::EnableIf<mozilla::IsEnum<T>::value, T>::Type * = NULL)
   171     {
   172         uint32_t tmp;
   173         if (mode == XDR_ENCODE)
   174             tmp = *val;
   175         if (!codeUint32(&tmp))
   176             return false;
   177         if (mode == XDR_DECODE)
   178             *val = T(tmp);
   179         return true;
   180     }
   182     bool codeDouble(double *dp) {
   183         union DoublePun {
   184             double d;
   185             uint64_t u;
   186         } pun;
   187         if (mode == XDR_ENCODE)
   188             pun.d = *dp;
   189         if (!codeUint64(&pun.u))
   190             return false;
   191         if (mode == XDR_DECODE)
   192             *dp = pun.d;
   193         return true;
   194     }
   196     bool codeBytes(void *bytes, size_t len) {
   197         if (mode == XDR_ENCODE) {
   198             uint8_t *ptr = buf.write(len);
   199             if (!ptr)
   200                 return false;
   201             memcpy(ptr, bytes, len);
   202         } else {
   203             memcpy(bytes, buf.read(len), len);
   204         }
   205         return true;
   206     }
   208     /*
   209      * During encoding the string is written into the buffer together with its
   210      * terminating '\0'. During decoding the method returns a pointer into the
   211      * decoding buffer and the caller must copy the string if it will outlive
   212      * the decoding buffer.
   213      */
   214     bool codeCString(const char **sp) {
   215         if (mode == XDR_ENCODE) {
   216             size_t n = strlen(*sp) + 1;
   217             uint8_t *ptr = buf.write(n);
   218             if (!ptr)
   219                 return false;
   220             memcpy(ptr, *sp, n);
   221         } else {
   222             *sp = buf.readCString();
   223         }
   224         return true;
   225     }
   227     bool codeChars(jschar *chars, size_t nchars);
   229     bool codeFunction(JS::MutableHandleObject objp);
   230     bool codeScript(MutableHandleScript scriptp);
   231     bool codeConstValue(MutableHandleValue vp);
   232 };
   234 class XDREncoder : public XDRState<XDR_ENCODE> {
   235   public:
   236     XDREncoder(JSContext *cx)
   237       : XDRState<XDR_ENCODE>(cx) {
   238     }
   240     ~XDREncoder() {
   241         buf.freeBuffer();
   242     }
   244     const void *getData(uint32_t *lengthp) const {
   245         return buf.getData(lengthp);
   246     }
   248     void *forgetData(uint32_t *lengthp) {
   249         void *data = buf.getData(lengthp);
   250         buf.setData(nullptr, 0);
   251         return data;
   252     }
   253 };
   255 class XDRDecoder : public XDRState<XDR_DECODE> {
   256   public:
   257     XDRDecoder(JSContext *cx, const void *data, uint32_t length,
   258                JSPrincipals *originPrincipals);
   260 };
   262 } /* namespace js */
   264 #endif /* vm_Xdr_h */

mercurial