LCOV - code coverage report
Current view: top level - xpcom/base - nsUUIDGenerator.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 41 47 87.2 %
Date: 2017-07-14 16:53:18 Functions: 7 8 87.5 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
       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/. */
       6             : 
       7             : #if defined(XP_WIN)
       8             : #include <windows.h>
       9             : #include <objbase.h>
      10             : #elif defined(XP_MACOSX)
      11             : #include <CoreFoundation/CoreFoundation.h>
      12             : #else
      13             : #include <stdlib.h>
      14             : #include "prrng.h"
      15             : #endif
      16             : 
      17             : #include "nsUUIDGenerator.h"
      18             : 
      19             : #ifdef ANDROID
      20             : extern "C" NS_EXPORT void arc4random_buf(void*, size_t);
      21             : #endif
      22             : 
      23             : using namespace mozilla;
      24             : 
      25        1219 : NS_IMPL_ISUPPORTS(nsUUIDGenerator, nsIUUIDGenerator)
      26             : 
      27           3 : nsUUIDGenerator::nsUUIDGenerator()
      28           3 :   : mLock("nsUUIDGenerator.mLock")
      29             : {
      30           3 : }
      31             : 
      32           0 : nsUUIDGenerator::~nsUUIDGenerator()
      33             : {
      34           0 : }
      35             : 
      36             : nsresult
      37           3 : nsUUIDGenerator::Init()
      38             : {
      39             :   // We're a service, so we're guaranteed that Init() is not going
      40             :   // to be reentered while we're inside Init().
      41             : 
      42             : #if !defined(XP_WIN) && !defined(XP_MACOSX) && !defined(HAVE_ARC4RANDOM)
      43             :   /* initialize random number generator using NSPR random noise */
      44             :   unsigned int seed;
      45             : 
      46           3 :   size_t bytes = 0;
      47           9 :   while (bytes < sizeof(seed)) {
      48           3 :     size_t nbytes = PR_GetRandomNoise(((unsigned char*)&seed) + bytes,
      49           3 :                                       sizeof(seed) - bytes);
      50           3 :     if (nbytes == 0) {
      51           0 :       return NS_ERROR_FAILURE;
      52             :     }
      53           3 :     bytes += nbytes;
      54             :   }
      55             : 
      56             :   /* Initialize a new RNG state, and immediately switch
      57             :    * back to the previous one -- we want to use mState
      58             :    * only for our own calls to random().
      59             :    */
      60           3 :   mSavedState = initstate(seed, mState, sizeof(mState));
      61           3 :   setstate(mSavedState);
      62             : 
      63           3 :   mRBytes = 4;
      64             : #ifdef RAND_MAX
      65             :   if ((unsigned long)RAND_MAX < 0xffffffffUL) {
      66           3 :     mRBytes = 3;
      67             :   }
      68             :   if ((unsigned long)RAND_MAX < 0x00ffffffUL) {
      69             :     mRBytes = 2;
      70             :   }
      71             :   if ((unsigned long)RAND_MAX < 0x0000ffffUL) {
      72             :     mRBytes = 1;
      73             :   }
      74             :   if ((unsigned long)RAND_MAX < 0x000000ffUL) {
      75             :     return NS_ERROR_FAILURE;
      76             :   }
      77             : #endif
      78             : 
      79             : #endif /* non XP_WIN and non XP_MACOSX and non ARC4RANDOM */
      80             : 
      81           3 :   return NS_OK;
      82             : }
      83             : 
      84             : NS_IMETHODIMP
      85           5 : nsUUIDGenerator::GenerateUUID(nsID** aRet)
      86             : {
      87           5 :   nsID* id = static_cast<nsID*>(moz_xmalloc(sizeof(nsID)));
      88           5 :   if (!id) {
      89           0 :     return NS_ERROR_OUT_OF_MEMORY;
      90             :   }
      91             : 
      92           5 :   nsresult rv = GenerateUUIDInPlace(id);
      93           5 :   if (NS_FAILED(rv)) {
      94           0 :     free(id);
      95           0 :     return rv;
      96             :   }
      97             : 
      98           5 :   *aRet = id;
      99           5 :   return rv;
     100             : }
     101             : 
     102             : NS_IMETHODIMP
     103         151 : nsUUIDGenerator::GenerateUUIDInPlace(nsID* aId)
     104             : {
     105             :   // The various code in this method is probably not threadsafe, so lock
     106             :   // across the whole method.
     107         302 :   MutexAutoLock lock(mLock);
     108             : 
     109             : #if defined(XP_WIN)
     110             :   HRESULT hr = CoCreateGuid((GUID*)aId);
     111             :   if (FAILED(hr)) {
     112             :     return NS_ERROR_FAILURE;
     113             :   }
     114             : #elif defined(XP_MACOSX)
     115             :   CFUUIDRef uuid = CFUUIDCreate(kCFAllocatorDefault);
     116             :   if (!uuid) {
     117             :     return NS_ERROR_FAILURE;
     118             :   }
     119             : 
     120             :   CFUUIDBytes bytes = CFUUIDGetUUIDBytes(uuid);
     121             :   memcpy(aId, &bytes, sizeof(nsID));
     122             : 
     123             :   CFRelease(uuid);
     124             : #else /* not windows or OS X; generate randomness using random(). */
     125             :   /* XXX we should be saving the return of setstate here and switching
     126             :    * back to it; instead, we use the value returned when we called
     127             :    * initstate, since older glibc's have broken setstate() return values
     128             :    */
     129             : #ifndef HAVE_ARC4RANDOM
     130         151 :   setstate(mState);
     131             : #endif
     132             : 
     133             : #ifdef HAVE_ARC4RANDOM_BUF
     134             :   arc4random_buf(aId, sizeof(nsID));
     135             : #else /* HAVE_ARC4RANDOM_BUF */
     136         151 :   size_t bytesLeft = sizeof(nsID);
     137        1963 :   while (bytesLeft > 0) {
     138             : #ifdef HAVE_ARC4RANDOM
     139             :     long rval = arc4random();
     140             :     const size_t mRBytes = 4;
     141             : #else
     142         906 :     long rval = random();
     143             : #endif
     144             : 
     145             : 
     146         906 :     uint8_t* src = (uint8_t*)&rval;
     147             :     // We want to grab the mRBytes least significant bytes of rval, since
     148             :     // mRBytes less than sizeof(rval) means the high bytes are 0.
     149             : #ifdef IS_BIG_ENDIAN
     150             :     src += sizeof(rval) - mRBytes;
     151             : #endif
     152         906 :     uint8_t* dst = ((uint8_t*)aId) + (sizeof(nsID) - bytesLeft);
     153         906 :     size_t toWrite = (bytesLeft < mRBytes ? bytesLeft : mRBytes);
     154        3322 :     for (size_t i = 0; i < toWrite; i++) {
     155        2416 :       dst[i] = src[i];
     156             :     }
     157             : 
     158         906 :     bytesLeft -= toWrite;
     159             :   }
     160             : #endif /* HAVE_ARC4RANDOM_BUF */
     161             : 
     162             :   /* Put in the version */
     163         151 :   aId->m2 &= 0x0fff;
     164         151 :   aId->m2 |= 0x4000;
     165             : 
     166             :   /* Put in the variant */
     167         151 :   aId->m3[0] &= 0x3f;
     168         151 :   aId->m3[0] |= 0x80;
     169             : 
     170             : #ifndef HAVE_ARC4RANDOM
     171             :   /* Restore the previous RNG state */
     172         151 :   setstate(mSavedState);
     173             : #endif
     174             : #endif
     175             : 
     176         302 :   return NS_OK;
     177             : }

Generated by: LCOV version 1.13