security/nss/lib/base/utf8.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this
     3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     5 /*
     6  * utf8.c
     7  *
     8  * This file contains some additional utility routines required for
     9  * handling UTF8 strings.
    10  */
    12 #ifndef BASE_H
    13 #include "base.h"
    14 #endif /* BASE_H */
    16 #include "plstr.h"
    18 /*
    19  * NOTES:
    20  *
    21  * There's an "is hex string" function in pki1/atav.c.  If we need
    22  * it in more places, pull that one out.
    23  */
    25 /*
    26  * nssUTF8_CaseIgnoreMatch
    27  * 
    28  * Returns true if the two UTF8-encoded strings pointed to by the 
    29  * two specified NSSUTF8 pointers differ only in typcase.
    30  *
    31  * The error may be one of the following values:
    32  *  NSS_ERROR_INVALID_POINTER
    33  *
    34  * Return value:
    35  *  PR_TRUE if the strings match, ignoring case
    36  *  PR_FALSE if they don't
    37  *  PR_FALSE upon error
    38  */
    40 NSS_IMPLEMENT PRBool
    41 nssUTF8_CaseIgnoreMatch
    42 (
    43   const NSSUTF8 *a,
    44   const NSSUTF8 *b,
    45   PRStatus *statusOpt
    46 )
    47 {
    48 #ifdef NSSDEBUG
    49   if( ((const NSSUTF8 *)NULL == a) ||
    50       ((const NSSUTF8 *)NULL == b) ) {
    51     nss_SetError(NSS_ERROR_INVALID_POINTER);
    52     if( (PRStatus *)NULL != statusOpt ) {
    53       *statusOpt = PR_FAILURE;
    54     }
    55     return PR_FALSE;
    56   }
    57 #endif /* NSSDEBUG */
    59   if( (PRStatus *)NULL != statusOpt ) {
    60     *statusOpt = PR_SUCCESS;
    61   }
    63   /*
    64    * XXX fgmr
    65    *
    66    * This is, like, so wrong!
    67    */
    68   if( 0 == PL_strcasecmp((const char *)a, (const char *)b) ) {
    69     return PR_TRUE;
    70   } else {
    71     return PR_FALSE;
    72   }
    73 }
    75 /*
    76  * nssUTF8_PrintableMatch
    77  *
    78  * Returns true if the two Printable strings pointed to by the 
    79  * two specified NSSUTF8 pointers match when compared with the 
    80  * rules for Printable String (leading and trailing spaces are 
    81  * disregarded, extents of whitespace match irregardless of length, 
    82  * and case is not significant), then PR_TRUE will be returned.
    83  * Otherwise, PR_FALSE will be returned.  Upon failure, PR_FALSE
    84  * will be returned.  If the optional statusOpt argument is not
    85  * NULL, then PR_SUCCESS or PR_FAILURE will be stored in that
    86  * location.
    87  *
    88  * The error may be one of the following values:
    89  *  NSS_ERROR_INVALID_POINTER
    90  *
    91  * Return value:
    92  *  PR_TRUE if the strings match, ignoring case
    93  *  PR_FALSE if they don't
    94  *  PR_FALSE upon error
    95  */
    97 NSS_IMPLEMENT PRBool
    98 nssUTF8_PrintableMatch
    99 (
   100   const NSSUTF8 *a,
   101   const NSSUTF8 *b,
   102   PRStatus *statusOpt
   103 )
   104 {
   105   PRUint8 *c;
   106   PRUint8 *d;
   108 #ifdef NSSDEBUG
   109   if( ((const NSSUTF8 *)NULL == a) ||
   110       ((const NSSUTF8 *)NULL == b) ) {
   111     nss_SetError(NSS_ERROR_INVALID_POINTER);
   112     if( (PRStatus *)NULL != statusOpt ) {
   113       *statusOpt = PR_FAILURE;
   114     }
   115     return PR_FALSE;
   116   }
   117 #endif /* NSSDEBUG */
   119   if( (PRStatus *)NULL != statusOpt ) {
   120     *statusOpt = PR_SUCCESS;
   121   }
   123   c = (PRUint8 *)a;
   124   d = (PRUint8 *)b;
   126   while( ' ' == *c ) {
   127     c++;
   128   }
   130   while( ' ' == *d ) {
   131     d++;
   132   }
   134   while( ('\0' != *c) && ('\0' != *d) ) {
   135     PRUint8 e, f;
   137     e = *c;
   138     f = *d;
   140     if( ('a' <= e) && (e <= 'z') ) {
   141       e -= ('a' - 'A');
   142     }
   144     if( ('a' <= f) && (f <= 'z') ) {
   145       f -= ('a' - 'A');
   146     }
   148     if( e != f ) {
   149       return PR_FALSE;
   150     }
   152     c++;
   153     d++;
   155     if( ' ' == *c ) {
   156       while( ' ' == *c ) {
   157         c++;
   158       }
   159       c--;
   160     }
   162     if( ' ' == *d ) {
   163       while( ' ' == *d ) {
   164         d++;
   165       }
   166       d--;
   167     }
   168   }
   170   while( ' ' == *c ) {
   171     c++;
   172   }
   174   while( ' ' == *d ) {
   175     d++;
   176   }
   178   if( *c == *d ) {
   179     /* And both '\0', btw */
   180     return PR_TRUE;
   181   } else {
   182     return PR_FALSE;
   183   }
   184 }
   186 /*
   187  * nssUTF8_Duplicate
   188  *
   189  * This routine duplicates the UTF8-encoded string pointed to by the
   190  * specified NSSUTF8 pointer.  If the optional arenaOpt argument is
   191  * not null, the memory required will be obtained from that arena;
   192  * otherwise, the memory required will be obtained from the heap.
   193  * A pointer to the new string will be returned.  In case of error,
   194  * an error will be placed on the error stack and NULL will be 
   195  * returned.
   196  *
   197  * The error may be one of the following values:
   198  *  NSS_ERROR_INVALID_POINTER
   199  *  NSS_ERROR_INVALID_ARENA
   200  *  NSS_ERROR_NO_MEMORY
   201  */
   203 NSS_IMPLEMENT NSSUTF8 *
   204 nssUTF8_Duplicate
   205 (
   206   const NSSUTF8 *s,
   207   NSSArena *arenaOpt
   208 )
   209 {
   210   NSSUTF8 *rv;
   211   PRUint32 len;
   213 #ifdef NSSDEBUG
   214   if( (const NSSUTF8 *)NULL == s ) {
   215     nss_SetError(NSS_ERROR_INVALID_POINTER);
   216     return (NSSUTF8 *)NULL;
   217   }
   219   if( (NSSArena *)NULL != arenaOpt ) {
   220     if( PR_SUCCESS != nssArena_verifyPointer(arenaOpt) ) {
   221       return (NSSUTF8 *)NULL;
   222     }
   223   }
   224 #endif /* NSSDEBUG */
   226   len = PL_strlen((const char *)s);
   227 #ifdef PEDANTIC
   228   if( '\0' != ((const char *)s)[ len ] ) {
   229     /* must have wrapped, e.g., too big for PRUint32 */
   230     nss_SetError(NSS_ERROR_NO_MEMORY);
   231     return (NSSUTF8 *)NULL;
   232   }
   233 #endif /* PEDANTIC */
   234   len++; /* zero termination */
   236   rv = nss_ZAlloc(arenaOpt, len);
   237   if( (void *)NULL == rv ) {
   238     return (NSSUTF8 *)NULL;
   239   }
   241   (void)nsslibc_memcpy(rv, s, len);
   242   return rv;
   243 }
   245 /*
   246  * nssUTF8_Size
   247  *
   248  * This routine returns the length in bytes (including the terminating
   249  * null) of the UTF8-encoded string pointed to by the specified
   250  * NSSUTF8 pointer.  Zero is returned on error.
   251  *
   252  * The error may be one of the following values:
   253  *  NSS_ERROR_INVALID_POINTER
   254  *  NSS_ERROR_VALUE_TOO_LARGE
   255  *
   256  * Return value:
   257  *  0 on error
   258  *  nonzero length of the string.
   259  */
   261 NSS_IMPLEMENT PRUint32
   262 nssUTF8_Size
   263 (
   264   const NSSUTF8 *s,
   265   PRStatus *statusOpt
   266 )
   267 {
   268   PRUint32 sv;
   270 #ifdef NSSDEBUG
   271   if( (const NSSUTF8 *)NULL == s ) {
   272     nss_SetError(NSS_ERROR_INVALID_POINTER);
   273     if( (PRStatus *)NULL != statusOpt ) {
   274       *statusOpt = PR_FAILURE;
   275     }
   276     return 0;
   277   }
   278 #endif /* NSSDEBUG */
   280   sv = PL_strlen((const char *)s) + 1;
   281 #ifdef PEDANTIC
   282   if( '\0' != ((const char *)s)[ sv-1 ] ) {
   283     /* wrapped */
   284     nss_SetError(NSS_ERROR_VALUE_TOO_LARGE);
   285     if( (PRStatus *)NULL != statusOpt ) {
   286       *statusOpt = PR_FAILURE;
   287     }
   288     return 0;
   289   }
   290 #endif /* PEDANTIC */
   292   if( (PRStatus *)NULL != statusOpt ) {
   293     *statusOpt = PR_SUCCESS;
   294   }
   296   return sv;
   297 }
   299 /*
   300  * nssUTF8_Length
   301  *
   302  * This routine returns the length in characters (not including the
   303  * terminating null) of the UTF8-encoded string pointed to by the
   304  * specified NSSUTF8 pointer.
   305  *
   306  * The error may be one of the following values:
   307  *  NSS_ERROR_INVALID_POINTER
   308  *  NSS_ERROR_VALUE_TOO_LARGE
   309  *  NSS_ERROR_INVALID_STRING
   310  *
   311  * Return value:
   312  *  length of the string (which may be zero)
   313  *  0 on error
   314  */
   316 NSS_IMPLEMENT PRUint32
   317 nssUTF8_Length
   318 (
   319   const NSSUTF8 *s,
   320   PRStatus *statusOpt
   321 )
   322 {
   323   PRUint32 l = 0;
   324   const PRUint8 *c = (const PRUint8 *)s;
   326 #ifdef NSSDEBUG
   327   if( (const NSSUTF8 *)NULL == s ) {
   328     nss_SetError(NSS_ERROR_INVALID_POINTER);
   329     goto loser;
   330   }
   331 #endif /* NSSDEBUG */
   333   /*
   334    * From RFC 2044:
   335    *
   336    * UCS-4 range (hex.)           UTF-8 octet sequence (binary)
   337    * 0000 0000-0000 007F   0xxxxxxx
   338    * 0000 0080-0000 07FF   110xxxxx 10xxxxxx
   339    * 0000 0800-0000 FFFF   1110xxxx 10xxxxxx 10xxxxxx
   340    * 0001 0000-001F FFFF   11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
   341    * 0020 0000-03FF FFFF   111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
   342    * 0400 0000-7FFF FFFF   1111110x 10xxxxxx ... 10xxxxxx
   343    */  
   345   while( 0 != *c ) {
   346     PRUint32 incr;
   347     if( (*c & 0x80) == 0 ) {
   348       incr = 1;
   349     } else if( (*c & 0xE0) == 0xC0 ) {
   350       incr = 2;
   351     } else if( (*c & 0xF0) == 0xE0 ) {
   352       incr = 3;
   353     } else if( (*c & 0xF8) == 0xF0 ) {
   354       incr = 4;
   355     } else if( (*c & 0xFC) == 0xF8 ) {
   356       incr = 5;
   357     } else if( (*c & 0xFE) == 0xFC ) {
   358       incr = 6;
   359     } else {
   360       nss_SetError(NSS_ERROR_INVALID_STRING);
   361       goto loser;
   362     }
   364     l += incr;
   366 #ifdef PEDANTIC
   367     if( l < incr ) {
   368       /* Wrapped-- too big */
   369       nss_SetError(NSS_ERROR_VALUE_TOO_LARGE);
   370       goto loser;
   371     }
   373     {
   374       PRUint8 *d;
   375       for( d = &c[1]; d < &c[incr]; d++ ) {
   376         if( (*d & 0xC0) != 0xF0 ) {
   377           nss_SetError(NSS_ERROR_INVALID_STRING);
   378           goto loser;
   379         }
   380       }
   381     }
   382 #endif /* PEDANTIC */
   384     c += incr;
   385   }
   387   if( (PRStatus *)NULL != statusOpt ) {
   388     *statusOpt = PR_SUCCESS;
   389   }
   391   return l;
   393  loser:
   394   if( (PRStatus *)NULL != statusOpt ) {
   395     *statusOpt = PR_FAILURE;
   396   }
   398   return 0;
   399 }
   402 /*
   403  * nssUTF8_Create
   404  *
   405  * This routine creates a UTF8 string from a string in some other
   406  * format.  Some types of string may include embedded null characters,
   407  * so for them the length parameter must be used.  For string types
   408  * that are null-terminated, the length parameter is optional; if it
   409  * is zero, it will be ignored.  If the optional arena argument is
   410  * non-null, the memory used for the new string will be obtained from
   411  * that arena, otherwise it will be obtained from the heap.  This
   412  * routine may return NULL upon error, in which case it will have
   413  * placed an error on the error stack.
   414  *
   415  * The error may be one of the following:
   416  *  NSS_ERROR_INVALID_POINTER
   417  *  NSS_ERROR_NO_MEMORY
   418  *  NSS_ERROR_UNSUPPORTED_TYPE
   419  *
   420  * Return value:
   421  *  NULL upon error
   422  *  A non-null pointer to a new UTF8 string otherwise
   423  */
   425 extern const NSSError NSS_ERROR_INTERNAL_ERROR; /* XXX fgmr */
   427 NSS_IMPLEMENT NSSUTF8 *
   428 nssUTF8_Create
   429 (
   430   NSSArena *arenaOpt,
   431   nssStringType type,
   432   const void *inputString,
   433   PRUint32 size /* in bytes, not characters */
   434 )
   435 {
   436   NSSUTF8 *rv = NULL;
   438 #ifdef NSSDEBUG
   439   if( (NSSArena *)NULL != arenaOpt ) {
   440     if( PR_SUCCESS != nssArena_verifyPointer(arenaOpt) ) {
   441       return (NSSUTF8 *)NULL;
   442     }
   443   }
   445   if( (const void *)NULL == inputString ) {
   446     nss_SetError(NSS_ERROR_INVALID_POINTER);
   447     return (NSSUTF8 *)NULL;
   448   }
   449 #endif /* NSSDEBUG */
   451   switch( type ) {
   452   case nssStringType_DirectoryString:
   453     /* This is a composite type requiring BER */
   454     nss_SetError(NSS_ERROR_UNSUPPORTED_TYPE);
   455     break;
   456   case nssStringType_TeletexString:
   457     /*
   458      * draft-ietf-pkix-ipki-part1-11 says in part:
   459      *
   460      * In addition, many legacy implementations support names encoded 
   461      * in the ISO 8859-1 character set (Latin1String) but tag them as 
   462      * TeletexString.  The Latin1String includes characters used in 
   463      * Western European countries which are not part of the 
   464      * TeletexString charcter set.  Implementations that process 
   465      * TeletexString SHOULD be prepared to handle the entire ISO 
   466      * 8859-1 character set.[ISO 8859-1].
   467      */
   468     nss_SetError(NSS_ERROR_INTERNAL_ERROR); /* unimplemented */
   469     break;
   470   case nssStringType_PrintableString:
   471     /*
   472      * PrintableString consists of A-Za-z0-9 ,()+,-./:=?
   473      * This is a subset of ASCII, which is a subset of UTF8.
   474      * So we can just duplicate the string over.
   475      */
   477     if( 0 == size ) {
   478       rv = nssUTF8_Duplicate((const NSSUTF8 *)inputString, arenaOpt);
   479     } else {
   480       rv = nss_ZAlloc(arenaOpt, size+1);
   481       if( (NSSUTF8 *)NULL == rv ) {
   482         return (NSSUTF8 *)NULL;
   483       }
   485       (void)nsslibc_memcpy(rv, inputString, size);
   486     }
   488     break;
   489   case nssStringType_UniversalString:
   490     /* 4-byte unicode */
   491     nss_SetError(NSS_ERROR_INTERNAL_ERROR); /* unimplemented */
   492     break;
   493   case nssStringType_BMPString:
   494     /* Base Multilingual Plane of Unicode */
   495     nss_SetError(NSS_ERROR_INTERNAL_ERROR); /* unimplemented */
   496     break;
   497   case nssStringType_UTF8String:
   498     if( 0 == size ) {
   499       rv = nssUTF8_Duplicate((const NSSUTF8 *)inputString, arenaOpt);
   500     } else {
   501       rv = nss_ZAlloc(arenaOpt, size+1);
   502       if( (NSSUTF8 *)NULL == rv ) {
   503         return (NSSUTF8 *)NULL;
   504       }
   506       (void)nsslibc_memcpy(rv, inputString, size);
   507     }
   509     break;
   510   case nssStringType_PHGString:
   511     /* 
   512      * PHGString is an IA5String (with case-insensitive comparisons).
   513      * IA5 is ~almost~ ascii; ascii has dollar-sign where IA5 has
   514      * currency symbol.
   515      */
   516     nss_SetError(NSS_ERROR_INTERNAL_ERROR); /* unimplemented */
   517     break;
   518   case nssStringType_GeneralString:
   519     nss_SetError(NSS_ERROR_INTERNAL_ERROR); /* unimplemented */
   520     break;
   521   default:
   522     nss_SetError(NSS_ERROR_UNSUPPORTED_TYPE);
   523     break;
   524   }
   526   return rv;
   527 }
   529 NSS_IMPLEMENT NSSItem *
   530 nssUTF8_GetEncoding
   531 (
   532   NSSArena *arenaOpt,
   533   NSSItem *rvOpt,
   534   nssStringType type,
   535   NSSUTF8 *string
   536 )
   537 {
   538   NSSItem *rv = (NSSItem *)NULL;
   539   PRStatus status = PR_SUCCESS;
   541 #ifdef NSSDEBUG
   542   if( (NSSArena *)NULL != arenaOpt ) {
   543     if( PR_SUCCESS != nssArena_verifyPointer(arenaOpt) ) {
   544       return (NSSItem *)NULL;
   545     }
   546   }
   548   if( (NSSUTF8 *)NULL == string ) {
   549     nss_SetError(NSS_ERROR_INVALID_POINTER);
   550     return (NSSItem *)NULL;
   551   }
   552 #endif /* NSSDEBUG */
   554   switch( type ) {
   555   case nssStringType_DirectoryString:
   556     nss_SetError(NSS_ERROR_INTERNAL_ERROR); /* unimplemented */
   557     break;
   558   case nssStringType_TeletexString:
   559     nss_SetError(NSS_ERROR_INTERNAL_ERROR); /* unimplemented */
   560     break;
   561   case nssStringType_PrintableString:
   562     nss_SetError(NSS_ERROR_INTERNAL_ERROR); /* unimplemented */
   563     break;
   564   case nssStringType_UniversalString:
   565     nss_SetError(NSS_ERROR_INTERNAL_ERROR); /* unimplemented */
   566     break;
   567   case nssStringType_BMPString:
   568     nss_SetError(NSS_ERROR_INTERNAL_ERROR); /* unimplemented */
   569     break;
   570   case nssStringType_UTF8String:
   571     {
   572       NSSUTF8 *dup = nssUTF8_Duplicate(string, arenaOpt);
   573       if( (NSSUTF8 *)NULL == dup ) {
   574         return (NSSItem *)NULL;
   575       }
   577       if( (NSSItem *)NULL == rvOpt ) {
   578         rv = nss_ZNEW(arenaOpt, NSSItem);
   579         if( (NSSItem *)NULL == rv ) {
   580           (void)nss_ZFreeIf(dup);
   581           return (NSSItem *)NULL;
   582         }
   583       } else {
   584         rv = rvOpt;
   585       }
   587       rv->data = dup;
   588       dup = (NSSUTF8 *)NULL;
   589       rv->size = nssUTF8_Size(rv->data, &status);
   590       if( (0 == rv->size) && (PR_SUCCESS != status) ) {
   591         if( (NSSItem *)NULL == rvOpt ) {
   592           (void)nss_ZFreeIf(rv);
   593         }
   594         return (NSSItem *)NULL;
   595       }
   596     }
   597     break;
   598   case nssStringType_PHGString:
   599     nss_SetError(NSS_ERROR_INTERNAL_ERROR); /* unimplemented */
   600     break;
   601   default:
   602     nss_SetError(NSS_ERROR_UNSUPPORTED_TYPE);
   603     break;
   604   }
   606   return rv;
   607 }
   609 /*
   610  * nssUTF8_CopyIntoFixedBuffer
   611  *
   612  * This will copy a UTF8 string into a fixed-length buffer, making 
   613  * sure that the all characters are valid.  Any remaining space will
   614  * be padded with the specified ASCII character, typically either 
   615  * null or space.
   616  *
   617  * Blah, blah, blah.
   618  */
   620 NSS_IMPLEMENT PRStatus
   621 nssUTF8_CopyIntoFixedBuffer
   622 (
   623   NSSUTF8 *string,
   624   char *buffer,
   625   PRUint32 bufferSize,
   626   char pad
   627 )
   628 {
   629   PRUint32 stringSize = 0;
   631 #ifdef NSSDEBUG
   632   if( (char *)NULL == buffer ) {
   633     nss_SetError(NSS_ERROR_INVALID_POINTER);
   634     return PR_FALSE;
   635   }
   637   if( 0 == bufferSize ) {
   638     nss_SetError(NSS_ERROR_INVALID_ARGUMENT);
   639     return PR_FALSE;
   640   }
   642   if( (pad & 0x80) != 0x00 ) {
   643     nss_SetError(NSS_ERROR_INVALID_ARGUMENT);
   644     return PR_FALSE;
   645   }
   646 #endif /* NSSDEBUG */
   648   if( (NSSUTF8 *)NULL == string ) {
   649     string = (NSSUTF8 *) "";
   650   }
   652   stringSize = nssUTF8_Size(string, (PRStatus *)NULL);
   653   stringSize--; /* don't count the trailing null */
   654   if( stringSize > bufferSize ) {
   655     PRUint32 bs = bufferSize;
   656     (void)nsslibc_memcpy(buffer, string, bufferSize);
   658     if( (            ((buffer[ bs-1 ] & 0x80) == 0x00)) ||
   659         ((bs > 1) && ((buffer[ bs-2 ] & 0xE0) == 0xC0)) ||
   660         ((bs > 2) && ((buffer[ bs-3 ] & 0xF0) == 0xE0)) ||
   661         ((bs > 3) && ((buffer[ bs-4 ] & 0xF8) == 0xF0)) ||
   662         ((bs > 4) && ((buffer[ bs-5 ] & 0xFC) == 0xF8)) ||
   663         ((bs > 5) && ((buffer[ bs-6 ] & 0xFE) == 0xFC)) ) {
   664       /* It fit exactly */
   665       return PR_SUCCESS;
   666     }
   668     /* Too long.  We have to trim the last character */
   669     for( /*bs*/; bs != 0; bs-- ) {
   670       if( (buffer[bs-1] & 0xC0) != 0x80 ) {
   671         buffer[bs-1] = pad;
   672         break;
   673       } else {
   674         buffer[bs-1] = pad;
   675       }
   676     }      
   677   } else {
   678     (void)nsslibc_memset(buffer, pad, bufferSize);
   679     (void)nsslibc_memcpy(buffer, string, stringSize);
   680   }
   682   return PR_SUCCESS;
   683 }
   685 /*
   686  * nssUTF8_Equal
   687  *
   688  */
   690 NSS_IMPLEMENT PRBool
   691 nssUTF8_Equal
   692 (
   693   const NSSUTF8 *a,
   694   const NSSUTF8 *b,
   695   PRStatus *statusOpt
   696 )
   697 {
   698   PRUint32 la, lb;
   700 #ifdef NSSDEBUG
   701   if( ((const NSSUTF8 *)NULL == a) ||
   702       ((const NSSUTF8 *)NULL == b) ) {
   703     nss_SetError(NSS_ERROR_INVALID_POINTER);
   704     if( (PRStatus *)NULL != statusOpt ) {
   705       *statusOpt = PR_FAILURE;
   706     }
   707     return PR_FALSE;
   708   }
   709 #endif /* NSSDEBUG */
   711   la = nssUTF8_Size(a, statusOpt);
   712   if( 0 == la ) {
   713     return PR_FALSE;
   714   }
   716   lb = nssUTF8_Size(b, statusOpt);
   717   if( 0 == lb ) {
   718     return PR_FALSE;
   719   }
   721   if( la != lb ) {
   722     return PR_FALSE;
   723   }
   725   return nsslibc_memequal(a, b, la, statusOpt);
   726 }

mercurial