LCOV - app.info - js/src/jsxdrapi.cpp

LCOV - code coverage report
| Current view: | directory - js/src - jsxdrapi.cpp (source / functions) |  | Found | Hit | Coverage |
| Test: | app.info | Lines: | 307 | 232 | 75.6 %
| Date: | 2012-07-07 | Functions: | 30 | 28 | 93.3 %

           1                 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
           2                 :  *
           3                 :  * ***** BEGIN LICENSE BLOCK *****
           4                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
           5                 :  *
           6                 :  * The contents of this file are subject to the Mozilla Public License Version
           7                 :  * 1.1 (the "License"); you may not use this file except in compliance with
           8                 :  * the License. You may obtain a copy of the License at
           9                 :  * http://www.mozilla.org/MPL/
          10                 :  *
          11                 :  * Software distributed under the License is distributed on an "AS IS" basis,
          12                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
          13                 :  * for the specific language governing rights and limitations under the
          14                 :  * License.
          15                 :  *
          16                 :  * The Original Code is Mozilla Communicator client code, released
          17                 :  * March 31, 1998.
          18                 :  *
          19                 :  * The Initial Developer of the Original Code is
          20                 :  * Netscape Communications Corporation.
          21                 :  * Portions created by the Initial Developer are Copyright (C) 1998
          22                 :  * the Initial Developer. All Rights Reserved.
          23                 :  *
          24                 :  * Contributor(s):
          25                 :  *
          26                 :  * Alternatively, the contents of this file may be used under the terms of
          27                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
          28                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
          29                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
          30                 :  * of those above. If you wish to allow use of your version of this file only
          31                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
          32                 :  * use your version of this file under the terms of the MPL, indicate your
          33                 :  * decision by deleting the provisions above and replace them with the notice
          34                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
          35                 :  * the provisions above, a recipient may use your version of this file under
          36                 :  * the terms of any one of the MPL, the GPL or the LGPL.
          37                 :  *
          38                 :  * ***** END LICENSE BLOCK ***** */
          39                 :
          40                 : #include "mozilla/Util.h"
          41                 :
          42                 : #include "jsversion.h"
          43                 :
          44                 : #if JS_HAS_XDR
          45                 :
          46                 : #include <string.h>
          47                 : #include "jstypes.h"
          48                 : #include "jsutil.h"
          49                 : #include "jsdhash.h"
          50                 : #include "jsprf.h"
          51                 : #include "jsapi.h"
          52                 : #include "jscntxt.h"
          53                 : #include "jsnum.h"
          54                 : #include "jsscript.h"           /* js_XDRScript */
          55                 : #include "jsstr.h"
          56                 : #include "jsxdrapi.h"
          57                 : #include "vm/Debugger.h"
          58                 :
          59                 : #include "jsobjinlines.h"
          60                 :
          61                 : using namespace mozilla;
          62                 : using namespace js;
          63                 :
          64                 : #ifdef DEBUG
          65                 : #define DBG(x) x
          66                 : #else
          67                 : #define DBG(x) ((void)0)
          68                 : #endif
          69                 :
          70                 : typedef struct JSXDRMemState {
          71                 :     JSXDRState  state;
          72                 :     char        *base;
          73                 :     uint32_t    count;
          74                 :     uint32_t    limit;
          75                 : } JSXDRMemState;
          76                 :
          77                 : #define MEM_BLOCK       8192
          78                 : #define MEM_PRIV(xdr)   ((JSXDRMemState *)(xdr))
          79                 :
          80                 : #define MEM_BASE(xdr)   (MEM_PRIV(xdr)->base)
          81                 : #define MEM_COUNT(xdr)  (MEM_PRIV(xdr)->count)
          82                 : #define MEM_LIMIT(xdr)  (MEM_PRIV(xdr)->limit)
          83                 :
          84                 : #define MEM_LEFT(xdr, bytes)                                                  \
          85                 :     JS_BEGIN_MACRO                                                            \
          86                 :         if ((xdr)->mode == JSXDR_DECODE &&                                    \
          87                 :             MEM_COUNT(xdr) + bytes > MEM_LIMIT(xdr)) {                        \
          88                 :             JS_ReportErrorNumber((xdr)->cx, js_GetErrorMessage, NULL,         \
          89                 :                                  JSMSG_END_OF_DATA);                          \
          90                 :             return 0;                                                         \
          91                 :         }                                                                     \
          92                 :     JS_END_MACRO
          93                 :
          94                 : #define MEM_NEED(xdr, bytes)                                                  \
          95                 :     JS_BEGIN_MACRO                                                            \
          96                 :         if ((xdr)->mode == JSXDR_ENCODE) {                                    \
          97                 :             if (MEM_LIMIT(xdr) &&                                             \
          98                 :                 MEM_COUNT(xdr) + bytes > MEM_LIMIT(xdr)) {                    \
          99                 :                 uint32_t limit_ = JS_ROUNDUP(MEM_COUNT(xdr) + bytes, MEM_BLOCK);\
         100                 :                 void *data_ = (xdr)->cx->realloc_(MEM_BASE(xdr), limit_);      \
         101                 :                 if (!data_)                                                   \
         102                 :                     return 0;                                                 \
         103                 :                 MEM_BASE(xdr) = (char *) data_;                               \
         104                 :                 MEM_LIMIT(xdr) = limit_;                                      \
         105                 :             }                                                                 \
         106                 :         } else {                                                              \
         107                 :             MEM_LEFT(xdr, bytes);                                             \
         108                 :         }                                                                     \
         109                 :     JS_END_MACRO
         110                 :
         111                 : #define MEM_DATA(xdr)        ((void *)(MEM_BASE(xdr) + MEM_COUNT(xdr)))
         112                 : #define MEM_INCR(xdr,bytes)  (MEM_COUNT(xdr) += (bytes))
         113                 :
         114                 : static JSBool
         115         7118895 : mem_get32(JSXDRState *xdr, uint32_t *lp)
         116                 : {
         117         7118895 :     MEM_LEFT(xdr, 4);
         118         7118895 :     *lp = *(uint32_t *)MEM_DATA(xdr);
         119         7118895 :     MEM_INCR(xdr, 4);
         120         7118895 :     return JS_TRUE;
         121                 : }
         122                 :
         123                 : static JSBool
         124        19577410 : mem_set32(JSXDRState *xdr, uint32_t *lp)
         125                 : {
         126        19577410 :     MEM_NEED(xdr, 4);
         127        19577410 :     *(uint32_t *)MEM_DATA(xdr) = *lp;
         128        19577410 :     MEM_INCR(xdr, 4);
         129        19577410 :     return JS_TRUE;
         130                 : }
         131                 :
         132                 : static JSBool
         133          531276 : mem_getbytes(JSXDRState *xdr, char *bytes, uint32_t len)
         134                 : {
         135          531276 :     MEM_LEFT(xdr, len);
         136          531276 :     js_memcpy(bytes, MEM_DATA(xdr), len);
         137          531276 :     MEM_INCR(xdr, len);
         138          531276 :     return JS_TRUE;
         139                 : }
         140                 :
         141                 : static JSBool
         142         2491203 : mem_setbytes(JSXDRState *xdr, char *bytes, uint32_t len)
         143                 : {
         144         2491203 :     MEM_NEED(xdr, len);
         145         2491203 :     js_memcpy(MEM_DATA(xdr), bytes, len);
         146         2491203 :     MEM_INCR(xdr, len);
         147         2491203 :     return JS_TRUE;
         148                 : }
         149                 :
         150                 : static void *
         151        11400893 : mem_raw(JSXDRState *xdr, uint32_t len)
         152                 : {
         153                 :     void *data;
         154        11400893 :     if (xdr->mode == JSXDR_ENCODE) {
         155         8620524 :         MEM_NEED(xdr, len);
         156         2780369 :     } else if (xdr->mode == JSXDR_DECODE) {
         157         2780369 :         MEM_LEFT(xdr, len);
         158                 :     }
         159        11400893 :     data = MEM_DATA(xdr);
         160        11400893 :     MEM_INCR(xdr, len);
         161        11400893 :     return data;
         162                 : }
         163                 :
         164                 : static JSBool
         165          447472 : mem_seek(JSXDRState *xdr, int32_t offset, JSXDRWhence whence)
         166                 : {
         167          447472 :     switch (whence) {
         168                 :       case JSXDR_SEEK_CUR:
         169          447472 :         if ((int32_t)MEM_COUNT(xdr) + offset < 0) {
         170                 :             JS_ReportErrorNumber(xdr->cx, js_GetErrorMessage, NULL,
         171               0 :                                  JSMSG_SEEK_BEYOND_START);
         172               0 :             return JS_FALSE;
         173                 :         }
         174          447472 :         if (offset > 0)
         175          447472 :             MEM_NEED(xdr, offset);
         176          447472 :         MEM_COUNT(xdr) += offset;
         177          447472 :         return JS_TRUE;
         178                 :       case JSXDR_SEEK_SET:
         179               0 :         if (offset < 0) {
         180                 :             JS_ReportErrorNumber(xdr->cx, js_GetErrorMessage, NULL,
         181               0 :                                  JSMSG_SEEK_BEYOND_START);
         182               0 :             return JS_FALSE;
         183                 :         }
         184               0 :         if (xdr->mode == JSXDR_ENCODE) {
         185               0 :             if ((uint32_t)offset > MEM_COUNT(xdr))
         186               0 :                 MEM_NEED(xdr, offset - MEM_COUNT(xdr));
         187               0 :             MEM_COUNT(xdr) = offset;
         188                 :         } else {
         189               0 :             if ((uint32_t)offset > MEM_LIMIT(xdr)) {
         190                 :                 JS_ReportErrorNumber(xdr->cx, js_GetErrorMessage, NULL,
         191               0 :                                      JSMSG_SEEK_BEYOND_END);
         192               0 :                 return JS_FALSE;
         193                 :             }
         194               0 :             MEM_COUNT(xdr) = offset;
         195                 :         }
         196               0 :         return JS_TRUE;
         197                 :       case JSXDR_SEEK_END:
         198               0 :         if (offset >= 0 ||
         199                 :             xdr->mode == JSXDR_ENCODE ||
         200                 :             (int32_t)MEM_LIMIT(xdr) + offset < 0) {
         201                 :             JS_ReportErrorNumber(xdr->cx, js_GetErrorMessage, NULL,
         202               0 :                                  JSMSG_END_SEEK);
         203               0 :             return JS_FALSE;
         204                 :         }
         205               0 :         MEM_COUNT(xdr) = MEM_LIMIT(xdr) + offset;
         206               0 :         return JS_TRUE;
         207                 :       default: {
         208                 :         char numBuf[12];
         209               0 :         JS_snprintf(numBuf, sizeof numBuf, "%d", whence);
         210                 :         JS_ReportErrorNumber(xdr->cx, js_GetErrorMessage, NULL,
         211               0 :                              JSMSG_WHITHER_WHENCE, numBuf);
         212               0 :         return JS_FALSE;
         213                 :       }
         214                 :     }
         215                 : }
         216                 :
         217                 : static uint32_t
         218         1908693 : mem_tell(JSXDRState *xdr)
         219                 : {
         220         1908693 :     return MEM_COUNT(xdr);
         221                 : }
         222                 :
         223                 : static void
         224           12617 : mem_finalize(JSXDRState *xdr)
         225                 : {
         226           12617 :     xdr->cx->free_(MEM_BASE(xdr));
         227           12617 : }
         228                 :
         229                 : static JSXDROps xdrmem_ops = {
         230                 :     mem_get32,      mem_set32,      mem_getbytes,   mem_setbytes,
         231                 :     mem_raw,        mem_seek,       mem_tell,       mem_finalize
         232                 : };
         233                 :
         234                 : JS_PUBLIC_API(void)
         235           12617 : JS_XDRInitBase(JSXDRState *xdr, JSXDRMode mode, JSContext *cx)
         236                 : {
         237           12617 :     xdr->mode = mode;
         238           12617 :     xdr->cx = cx;
         239           12617 :     xdr->userdata = NULL;
         240           12617 :     xdr->sharedFilename = NULL;
         241           12617 :     xdr->principals = NULL;
         242           12617 :     xdr->originPrincipals = NULL;
         243           12617 : }
         244                 :
         245                 : JS_PUBLIC_API(JSXDRState *)
         246           12617 : JS_XDRNewMem(JSContext *cx, JSXDRMode mode)
         247                 : {
         248           12617 :     JSXDRState *xdr = (JSXDRState *) cx->malloc_(sizeof(JSXDRMemState));
         249           12617 :     if (!xdr)
         250               0 :         return NULL;
         251           12617 :     JS_XDRInitBase(xdr, mode, cx);
         252           12617 :     if (mode == JSXDR_ENCODE) {
         253            9675 :         if (!(MEM_BASE(xdr) = (char *) cx->malloc_(MEM_BLOCK))) {
         254               0 :             cx->free_(xdr);
         255               0 :             return NULL;
         256                 :         }
         257                 :     } else {
         258                 :         /* XXXbe ok, so better not deref MEM_BASE(xdr) if not ENCODE */
         259            2942 :         MEM_BASE(xdr) = NULL;
         260                 :     }
         261           12617 :     xdr->ops = &xdrmem_ops;
         262           12617 :     MEM_COUNT(xdr) = 0;
         263           12617 :     MEM_LIMIT(xdr) = MEM_BLOCK;
         264           12617 :     return xdr;
         265                 : }
         266                 :
         267                 : JS_PUBLIC_API(void *)
         268           18334 : JS_XDRMemGetData(JSXDRState *xdr, uint32_t *lp)
         269                 : {
         270           18334 :     if (xdr->ops != &xdrmem_ops)
         271               0 :         return NULL;
         272           18334 :     *lp = MEM_COUNT(xdr);
         273           18334 :     return MEM_BASE(xdr);
         274                 : }
         275                 :
         276                 : JS_PUBLIC_API(void)
         277            6505 : JS_XDRMemSetData(JSXDRState *xdr, void *data, uint32_t len)
         278                 : {
         279            6505 :     if (xdr->ops != &xdrmem_ops)
         280               0 :         return;
         281            6505 :     MEM_LIMIT(xdr) = len;
         282            6505 :     MEM_BASE(xdr) = (char *) data;
         283            6505 :     MEM_COUNT(xdr) = 0;
         284                 : }
         285                 :
         286                 : JS_PUBLIC_API(uint32_t)
         287             642 : JS_XDRMemDataLeft(JSXDRState *xdr)
         288                 : {
         289             642 :     if (xdr->ops != &xdrmem_ops)
         290               0 :         return 0;
         291             642 :     return MEM_LIMIT(xdr) - MEM_COUNT(xdr);
         292                 : }
         293                 :
         294                 : JS_PUBLIC_API(void)
         295            7375 : JS_XDRMemResetData(JSXDRState *xdr)
         296                 : {
         297            7375 :     if (xdr->ops != &xdrmem_ops)
         298               0 :         return;
         299            7375 :     MEM_COUNT(xdr) = 0;
         300                 : }
         301                 :
         302                 : JS_PUBLIC_API(void)
         303           12617 : JS_XDRDestroy(JSXDRState *xdr)
         304                 : {
         305           12617 :     JSContext *cx = xdr->cx;
         306           12617 :     xdr->ops->finalize(xdr);
         307           12617 :     cx->free_(xdr);
         308           12617 : }
         309                 :
         310                 : JS_PUBLIC_API(JSBool)
         311            8059 : JS_XDRUint8(JSXDRState *xdr, uint8_t *b)
         312                 : {
         313            8059 :     uint32_t l = *b;
         314            8059 :     if (!JS_XDRUint32(xdr, &l))
         315               0 :         return JS_FALSE;
         316            8059 :     *b = (uint8_t) l;
         317            8059 :     return JS_TRUE;
         318                 : }
         319                 :
         320                 : JS_PUBLIC_API(JSBool)
         321               0 : JS_XDRUint16(JSXDRState *xdr, uint16_t *s)
         322                 : {
         323               0 :     uint32_t l = *s;
         324               0 :     if (!JS_XDRUint32(xdr, &l))
         325               0 :         return JS_FALSE;
         326               0 :     *s = (uint16_t) l;
         327               0 :     return JS_TRUE;
         328                 : }
         329                 :
         330                 : JS_PUBLIC_API(JSBool)
         331        26696305 : JS_XDRUint32(JSXDRState *xdr, uint32_t *lp)
         332                 : {
         333        26696305 :     JSBool ok = JS_TRUE;
         334        26696305 :     if (xdr->mode == JSXDR_ENCODE) {
         335        19577410 :         uint32_t xl = JSXDR_SWAB32(*lp);
         336        19577410 :         ok = xdr->ops->set32(xdr, &xl);
         337         7118895 :     } else if (xdr->mode == JSXDR_DECODE) {
         338         7118895 :         ok = xdr->ops->get32(xdr, lp);
         339         7118895 :         *lp = JSXDR_SWAB32(*lp);
         340                 :     }
         341        26696305 :     return ok;
         342                 : }
         343                 :
         344                 : JS_PUBLIC_API(JSBool)
         345         1908693 : JS_XDRBytes(JSXDRState *xdr, char *bytes, uint32_t len)
         346                 : {
         347                 :     uint32_t padlen;
         348                 :     static char padbuf[JSXDR_ALIGN-1];
         349                 :
         350         1908693 :     if (xdr->mode == JSXDR_ENCODE) {
         351         1377417 :         if (!xdr->ops->setbytes(xdr, bytes, len))
         352               0 :             return JS_FALSE;
         353                 :     } else {
         354          531276 :         if (!xdr->ops->getbytes(xdr, bytes, len))
         355               0 :             return JS_FALSE;
         356                 :     }
         357         1908693 :     len = xdr->ops->tell(xdr);
         358         1908693 :     if (len % JSXDR_ALIGN) {
         359         1561258 :         padlen = JSXDR_ALIGN - (len % JSXDR_ALIGN);
         360         1561258 :         if (xdr->mode == JSXDR_ENCODE) {
         361         1113786 :             if (!xdr->ops->setbytes(xdr, padbuf, padlen))
         362               0 :                 return JS_FALSE;
         363                 :         } else {
         364          447472 :             if (!xdr->ops->seek(xdr, padlen, JSXDR_SEEK_CUR))
         365               0 :                 return JS_FALSE;
         366                 :         }
         367                 :     }
         368         1908693 :     return JS_TRUE;
         369                 : }
         370                 :
         371                 : /**
         372                 :  * Convert between a C string and the XDR representation:
         373                 :  * leading 32-bit count, then counted vector of chars,
         374                 :  * then possibly \0 padding to multiple of 4.
         375                 :  */
         376                 : JS_PUBLIC_API(JSBool)
         377          636231 : JS_XDRCString(JSXDRState *xdr, char **sp)
         378                 : {
         379                 :     uint32_t len;
         380                 :
         381          636231 :     if (xdr->mode == JSXDR_ENCODE)
         382          459139 :         len = strlen(*sp);
         383          636231 :     JS_XDRUint32(xdr, &len);
         384          636231 :     if (xdr->mode == JSXDR_DECODE) {
         385          177092 :         if (!(*sp = (char *) xdr->cx->malloc_(len + 1)))
         386               0 :             return JS_FALSE;
         387                 :     }
         388          636231 :     if (!JS_XDRBytes(xdr, *sp, len)) {
         389               0 :         if (xdr->mode == JSXDR_DECODE)
         390               0 :             xdr->cx->free_(*sp);
         391               0 :         return JS_FALSE;
         392                 :     }
         393          636231 :     if (xdr->mode == JSXDR_DECODE) {
         394          177092 :         (*sp)[len] = '\0';
         395                 :     }
         396          636231 :     return JS_TRUE;
         397                 : }
         398                 :
         399                 : static JSBool
         400        11400893 : XDRChars(JSXDRState *xdr, jschar *chars, uint32_t nchars)
         401                 : {
         402                 :     uint32_t i, padlen, nbytes;
         403                 :     jschar *raw;
         404                 :
         405        11400893 :     nbytes = nchars * sizeof(jschar);
         406        11400893 :     padlen = nbytes % JSXDR_ALIGN;
         407        11400893 :     if (padlen) {
         408         5359078 :         padlen = JSXDR_ALIGN - padlen;
         409         5359078 :         nbytes += padlen;
         410                 :     }
         411        11400893 :     if (!(raw = (jschar *) xdr->ops->raw(xdr, nbytes)))
         412               0 :         return JS_FALSE;
         413        11400893 :     if (xdr->mode == JSXDR_ENCODE) {
         414       328299099 :         for (i = 0; i != nchars; i++)
         415       319678575 :             raw[i] = JSXDR_SWAB16(chars[i]);
         416         8620524 :         if (padlen)
         417         4029547 :             memset((char *)raw + nbytes - padlen, 0, padlen);
         418         2780369 :     } else if (xdr->mode == JSXDR_DECODE) {
         419        41065010 :         for (i = 0; i != nchars; i++)
         420        38284641 :             chars[i] = JSXDR_SWAB16(raw[i]);
         421                 :     }
         422        11400893 :     return JS_TRUE;
         423                 : }
         424                 :
         425                 : /*
         426                 :  * Convert between a JS (Unicode) string and the XDR representation.
         427                 :  */
         428                 : JS_PUBLIC_API(JSBool)
         429         8622350 : JS_XDRString(JSXDRState *xdr, JSString **strp)
         430                 : {
         431                 :     uint32_t nchars;
         432                 :     jschar *chars;
         433                 :
         434         8622350 :     if (xdr->mode == JSXDR_ENCODE)
         435         8620524 :         nchars = (*strp)->length();
         436         8622350 :     if (!JS_XDRUint32(xdr, &nchars))
         437               0 :         return JS_FALSE;
         438                 :
         439         8622350 :     if (xdr->mode == JSXDR_DECODE)
         440            1826 :         chars = (jschar *) xdr->cx->malloc_((nchars + 1) * sizeof(jschar));
         441                 :     else
         442         8620524 :         chars = const_cast<jschar *>((*strp)->getChars(xdr->cx));
         443         8622350 :     if (!chars)
         444               0 :         return JS_FALSE;
         445                 :
         446         8622350 :     if (!XDRChars(xdr, chars, nchars))
         447               0 :         goto bad;
         448         8622350 :     if (xdr->mode == JSXDR_DECODE) {
         449            1826 :         chars[nchars] = 0;
         450            1826 :         *strp = JS_NewUCString(xdr->cx, chars, nchars);
         451            1826 :         if (!*strp)
         452               0 :             goto bad;
         453                 :     }
         454         8622350 :     return JS_TRUE;
         455                 :
         456                 : bad:
         457               0 :     if (xdr->mode == JSXDR_DECODE)
         458               0 :         xdr->cx->free_(chars);
         459               0 :     return JS_FALSE;
         460                 : }
         461                 :
         462                 : JS_PUBLIC_API(JSBool)
         463               0 : JS_XDRStringOrNull(JSXDRState *xdr, JSString **strp)
         464                 : {
         465               0 :     uint32_t null = (*strp == NULL);
         466               0 :     if (!JS_XDRUint32(xdr, &null))
         467               0 :         return JS_FALSE;
         468               0 :     if (null) {
         469               0 :         *strp = NULL;
         470               0 :         return JS_TRUE;
         471                 :     }
         472               0 :     return JS_XDRString(xdr, strp);
         473                 : }
         474                 :
         475                 : JS_PUBLIC_API(JSBool)
         476             975 : JS_XDRDouble(JSXDRState *xdr, double *dp)
         477                 : {
         478                 :     jsdpun u;
         479                 :
         480             975 :     u.d = (xdr->mode == JSXDR_ENCODE) ? *dp : 0.0;
         481             975 :     if (!JS_XDRUint32(xdr, &u.s.lo) || !JS_XDRUint32(xdr, &u.s.hi))
         482               0 :         return false;
         483             975 :     if (xdr->mode == JSXDR_DECODE)
         484               0 :         *dp = u.d;
         485             975 :     return true;
         486                 : }
         487                 :
         488                 : extern JSBool
         489        11375147 : js_XDRAtom(JSXDRState *xdr, JSAtom **atomp)
         490                 : {
         491                 :     JSString *str;
         492                 :     uint32_t nchars;
         493                 :     JSAtom *atom;
         494                 :     JSContext *cx;
         495                 :     jschar *chars;
         496                 :     jschar stackChars[256];
         497                 :
         498        11375147 :     if (xdr->mode == JSXDR_ENCODE) {
         499         8596604 :         str = *atomp;
         500         8596604 :         return JS_XDRString(xdr, &str);
         501                 :     }
         502                 :
         503                 :     /*
         504                 :      * Inline JS_XDRString when decoding to avoid JSString allocation
         505                 :      * for already existing atoms. See bug 321985.
         506                 :      */
         507         2778543 :     if (!JS_XDRUint32(xdr, &nchars))
         508               0 :         return JS_FALSE;
         509         2778543 :     atom = NULL;
         510         2778543 :     cx = xdr->cx;
         511         2778543 :     if (nchars <= ArrayLength(stackChars)) {
         512         2775067 :         chars = stackChars;
         513                 :     } else {
         514                 :         /*
         515                 :          * This is very uncommon. Don't use the tempLifoAlloc arena for this as
         516                 :          * most allocations here will be bigger than tempLifoAlloc's default
         517                 :          * chunk size.
         518                 :          */
         519            3476 :         chars = (jschar *) cx->malloc_(nchars * sizeof(jschar));
         520            3476 :         if (!chars)
         521               0 :             return JS_FALSE;
         522                 :     }
         523                 :
         524         2778543 :     if (XDRChars(xdr, chars, nchars))
         525         2778543 :         atom = js_AtomizeChars(cx, chars, nchars);
         526         2778543 :     if (chars != stackChars)
         527            3476 :         cx->free_(chars);
         528                 :
         529         2778543 :     if (!atom)
         530               0 :         return JS_FALSE;
         531         2778543 :     *atomp = atom;
         532         2778543 :     return JS_TRUE;
         533                 : }
         534                 :
         535                 : static bool
         536            8059 : XDRPrincipals(JSXDRState *xdr)
         537                 : {
         538            8059 :     const uint8_t HAS_PRINCIPALS   = 1;
         539            8059 :     const uint8_t HAS_ORIGIN       = 2;
         540                 :
         541            8059 :     uint8_t flags = 0;
         542            8059 :     if (xdr->mode == JSXDR_ENCODE) {
         543            7396 :         if (xdr->principals)
         544            7384 :             flags |= HAS_PRINCIPALS;
         545                 :
         546                 :         /*
         547                 :          * For the common case when principals == originPrincipals we want to
         548                 :          * avoid serializing the same principal twice. As originPrincipals are
         549                 :          * normalized and principals imply originPrincipals we simply set
         550                 :          * HAS_ORIGIN only if originPrincipals is set and different from
         551                 :          * principals. During decoding we re-normalize originPrincipals.
         552                 :          */
         553            7396 :         JS_ASSERT_IF(xdr->principals, xdr->originPrincipals);
         554            7396 :         if (xdr->originPrincipals && xdr->originPrincipals != xdr->principals)
         555               6 :             flags |= HAS_ORIGIN;
         556                 :     }
         557                 :
         558            8059 :     if (!JS_XDRUint8(xdr, &flags))
         559               0 :         return false;
         560                 :
         561            8059 :     if (flags & (HAS_PRINCIPALS | HAS_ORIGIN)) {
         562            8041 :         const JSSecurityCallbacks *scb = JS_GetSecurityCallbacks(xdr->cx->runtime);
         563            8041 :         if (xdr->mode == JSXDR_DECODE) {
         564             654 :             if (!scb || !scb->principalsTranscoder) {
         565                 :                 JS_ReportErrorNumber(xdr->cx, js_GetErrorMessage, NULL,
         566               0 :                                      JSMSG_CANT_DECODE_PRINCIPALS);
         567               0 :                 return false;
         568                 :             }
         569                 :         } else {
         570            7387 :             JS_ASSERT(scb);
         571            7387 :             JS_ASSERT(scb->principalsTranscoder);
         572                 :         }
         573                 :
         574            8041 :         if (flags & HAS_PRINCIPALS) {
         575            8035 :             if (!scb->principalsTranscoder(xdr, &xdr->principals))
         576               0 :                 return false;
         577                 :         }
         578                 :
         579            8041 :         if (flags & HAS_ORIGIN) {
         580              12 :             if (!scb->principalsTranscoder(xdr, &xdr->originPrincipals))
         581               0 :                 return false;
         582            8029 :         } else if (xdr->mode == JSXDR_DECODE && xdr->principals) {
         583             648 :             xdr->originPrincipals = xdr->principals;
         584             648 :             JS_HoldPrincipals(xdr->principals);
         585                 :         }
         586                 :     }
         587                 :
         588            8059 :     return true;
         589                 : }
         590                 :
         591                 : namespace {
         592                 :
         593                 : struct AutoDropXDRPrincipals {
         594                 :     JSXDRState *const xdr;
         595                 :
         596            8059 :     AutoDropXDRPrincipals(JSXDRState *xdr)
         597            8059 :       : xdr(xdr) { }
         598                 :
         599            8059 :     ~AutoDropXDRPrincipals() {
         600            8059 :         if (xdr->mode == JSXDR_DECODE) {
         601             663 :             if (xdr->principals)
         602             651 :                 JS_DropPrincipals(xdr->cx->runtime, xdr->principals);
         603             663 :             if (xdr->originPrincipals)
         604             654 :                 JS_DropPrincipals(xdr->cx->runtime, xdr->originPrincipals);
         605                 :         }
         606            8059 :         xdr->principals = NULL;
         607            8059 :         xdr->originPrincipals = NULL;
         608            8059 :     }
         609                 : };
         610                 :
         611                 : } /* namespace anonymous */
         612                 :
         613                 : JS_PUBLIC_API(JSBool)
         614              12 : JS_XDRFunctionObject(JSXDRState *xdr, JSObject **objp)
         615                 : {
         616              24 :     AutoDropXDRPrincipals drop(xdr);
         617              12 :     if (xdr->mode == JSXDR_ENCODE) {
         618               6 :         JSScript *script = (*objp)->toFunction()->script();
         619               6 :         xdr->principals = script->principals;
         620               6 :         xdr->originPrincipals = script->originPrincipals;
         621                 :     }
         622                 :
         623              12 :     return XDRPrincipals(xdr) && XDRFunctionObject(xdr, objp);
         624                 : }
         625                 :
         626                 : JS_PUBLIC_API(JSBool)
         627            8047 : JS_XDRScript(JSXDRState *xdr, JSScript **scriptp)
         628                 : {
         629                 :     JSScript *script;
         630                 :     uint32_t magic;
         631                 :     uint32_t bytecodeVer;
         632            8047 :     if (xdr->mode == JSXDR_DECODE) {
         633             657 :         script = NULL;
         634             657 :         *scriptp = NULL;
         635                 :     } else {
         636            7390 :         script = *scriptp;
         637            7390 :         magic = JSXDR_MAGIC_SCRIPT_CURRENT;
         638            7390 :         bytecodeVer = JSXDR_BYTECODE_VERSION;
         639                 :     }
         640                 :
         641            8047 :     if (!JS_XDRUint32(xdr, &magic))
         642               0 :         return false;
         643            8047 :     if (!JS_XDRUint32(xdr, &bytecodeVer))
         644               0 :         return false;
         645                 :
         646            8047 :     if (magic != JSXDR_MAGIC_SCRIPT_CURRENT ||
         647                 :         bytecodeVer != JSXDR_BYTECODE_VERSION) {
         648                 :         /* We do not provide binary compatibility with older scripts. */
         649               0 :         JS_ReportErrorNumber(xdr->cx, js_GetErrorMessage, NULL, JSMSG_BAD_SCRIPT_MAGIC);
         650               0 :         return false;
         651                 :     }
         652                 :
         653                 :     {
         654           16094 :         AutoDropXDRPrincipals drop(xdr);
         655            8047 :         if (xdr->mode == JSXDR_ENCODE) {
         656            7390 :             xdr->principals = script->principals;
         657            7390 :             xdr->originPrincipals = script->originPrincipals;
         658                 :         }
         659                 :
         660            8047 :         if (!XDRPrincipals(xdr) || !XDRScript(xdr, &script))
         661               0 :             return false;
         662                 :     }
         663                 :
         664            8047 :     if (xdr->mode == JSXDR_DECODE) {
         665             657 :         JS_ASSERT(!script->compileAndGo);
         666             657 :         script->globalObject = GetCurrentGlobal(xdr->cx);
         667             657 :         js_CallNewScriptHook(xdr->cx, script, NULL);
         668             657 :         Debugger::onNewScript(xdr->cx, script, NULL);
         669             657 :         *scriptp = script;
         670                 :     }
         671                 :
         672            8047 :     return true;
         673                 : }
         674                 :
         675                 : #endif /* JS_HAS_XDR */

Generated by: LCOV version 1.7