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-06-02 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         2507486 : mem_setbytes(JSXDRState *xdr, char *bytes, uint32_t len)
     143                 : {
     144         2507486 :     MEM_NEED(xdr, len);
     145         2507486 :     js_memcpy(MEM_DATA(xdr), bytes, len);
     146         2507486 :     MEM_INCR(xdr, len);
     147         2507486 :     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          447490 : mem_seek(JSXDRState *xdr, int32_t offset, JSXDRWhence whence)
     166                 : {
     167          447490 :     switch (whence) {
     168                 :       case JSXDR_SEEK_CUR:
     169          447490 :         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          447490 :         if (offset > 0)
     175          447490 :             MEM_NEED(xdr, offset);
     176          447490 :         MEM_COUNT(xdr) += offset;
     177          447490 :         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         1577559 :         padlen = JSXDR_ALIGN - (len % JSXDR_ALIGN);
     360         1577559 :         if (xdr->mode == JSXDR_ENCODE) {
     361         1130069 :             if (!xdr->ops->setbytes(xdr, padbuf, padlen))
     362               0 :                 return JS_FALSE;
     363                 :         } else {
     364          447490 :             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         5359204 :         padlen = JSXDR_ALIGN - padlen;
     409         5359204 :         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       328302569 :         for (i = 0; i != nchars; i++)
     415       319682045 :             raw[i] = JSXDR_SWAB16(chars[i]);
     416         8620524 :         if (padlen)
     417         4029673 :             memset((char *)raw + nbytes - padlen, 0, padlen);
     418         2780369 :     } else if (xdr->mode == JSXDR_DECODE) {
     419        41065098 :         for (i = 0; i != nchars; i++)
     420        38284729 :             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