mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-10-19 21:57:30 +09:00
import FIREFOX_52_6_0esr_RELEASE from mozilla-esr52 hg repo
This commit is contained in:
commit
dcd9973243
150858 changed files with 23884658 additions and 0 deletions
11
security/nss/lib/base/Makefile
Normal file
11
security/nss/lib/base/Makefile
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
#
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
include manifest.mn
|
||||
include $(CORE_DEPTH)/coreconf/config.mk
|
||||
include config.mk
|
||||
include $(CORE_DEPTH)/coreconf/rules.mk
|
||||
|
||||
export:: private_export
|
||||
1143
security/nss/lib/base/arena.c
Normal file
1143
security/nss/lib/base/arena.c
Normal file
File diff suppressed because it is too large
Load diff
32
security/nss/lib/base/base.gyp
Normal file
32
security/nss/lib/base/base.gyp
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
{
|
||||
'includes': [
|
||||
'../../coreconf/config.gypi'
|
||||
],
|
||||
'targets': [
|
||||
{
|
||||
'target_name': 'nssb',
|
||||
'type': 'static_library',
|
||||
'sources': [
|
||||
'arena.c',
|
||||
'error.c',
|
||||
'errorval.c',
|
||||
'hash.c',
|
||||
'hashops.c',
|
||||
'item.c',
|
||||
'libc.c',
|
||||
'list.c',
|
||||
'tracker.c',
|
||||
'utf8.c'
|
||||
],
|
||||
'dependencies': [
|
||||
'<(DEPTH)/exports.gyp:nss_exports'
|
||||
]
|
||||
}
|
||||
],
|
||||
'variables': {
|
||||
'module': 'nss'
|
||||
}
|
||||
}
|
||||
1106
security/nss/lib/base/base.h
Normal file
1106
security/nss/lib/base/base.h
Normal file
File diff suppressed because it is too large
Load diff
124
security/nss/lib/base/baset.h
Normal file
124
security/nss/lib/base/baset.h
Normal file
|
|
@ -0,0 +1,124 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef BASET_H
|
||||
#define BASET_H
|
||||
|
||||
/*
|
||||
* baset.h
|
||||
*
|
||||
* This file contains definitions for the basic types used throughout
|
||||
* nss but not available publicly.
|
||||
*/
|
||||
|
||||
#ifndef NSSBASET_H
|
||||
#include "nssbaset.h"
|
||||
#endif /* NSSBASET_H */
|
||||
|
||||
#include "plhash.h"
|
||||
|
||||
PR_BEGIN_EXTERN_C
|
||||
|
||||
/*
|
||||
* nssArenaMark
|
||||
*
|
||||
* This type is used to mark the current state of an NSSArena.
|
||||
*/
|
||||
|
||||
struct nssArenaMarkStr;
|
||||
typedef struct nssArenaMarkStr nssArenaMark;
|
||||
|
||||
#ifdef DEBUG
|
||||
/*
|
||||
* ARENA_THREADMARK
|
||||
*
|
||||
* Optionally, this arena implementation can be compiled with some
|
||||
* runtime checking enabled, which will catch the situation where
|
||||
* one thread "marks" the arena, another thread allocates memory,
|
||||
* and then the mark is released. Usually this is a surprise to
|
||||
* the second thread, and this leads to weird runtime errors.
|
||||
* Define ARENA_THREADMARK to catch these cases; we define it for all
|
||||
* (internal and external) debug builds.
|
||||
*/
|
||||
#define ARENA_THREADMARK
|
||||
|
||||
/*
|
||||
* ARENA_DESTRUCTOR_LIST
|
||||
*
|
||||
* Unfortunately, our pointer-tracker facility, used in debug
|
||||
* builds to agressively fight invalid pointers, requries that
|
||||
* pointers be deregistered when objects are destroyed. This
|
||||
* conflicts with the standard arena usage where "memory-only"
|
||||
* objects (that don't hold onto resources outside the arena)
|
||||
* can be allocated in an arena, and never destroyed other than
|
||||
* when the arena is destroyed. Therefore we have added a
|
||||
* destructor-registratio facility to our arenas. This was not
|
||||
* a simple decision, since we're getting ever-further away from
|
||||
* the original arena philosophy. However, it was felt that
|
||||
* adding this in debug builds wouldn't be so bad; as it would
|
||||
* discourage them from being used for "serious" purposes.
|
||||
* This facility requires ARENA_THREADMARK to be defined.
|
||||
*/
|
||||
#ifdef ARENA_THREADMARK
|
||||
#define ARENA_DESTRUCTOR_LIST
|
||||
#endif /* ARENA_THREADMARK */
|
||||
|
||||
#endif /* DEBUG */
|
||||
|
||||
typedef struct nssListStr nssList;
|
||||
typedef struct nssListIteratorStr nssListIterator;
|
||||
typedef PRBool (*nssListCompareFunc)(void *a, void *b);
|
||||
typedef PRIntn (*nssListSortFunc)(void *a, void *b);
|
||||
typedef void (*nssListElementDestructorFunc)(void *el);
|
||||
|
||||
typedef struct nssHashStr nssHash;
|
||||
typedef void(PR_CALLBACK *nssHashIterator)(const void *key, void *value,
|
||||
void *arg);
|
||||
|
||||
/*
|
||||
* nssPointerTracker
|
||||
*
|
||||
* This type is used in debug builds (both external and internal) to
|
||||
* track our object pointers. Objects of this type must be statically
|
||||
* allocated, which means the structure size must be available to the
|
||||
* compiler. Therefore we must expose the contents of this structure.
|
||||
* But please don't access elements directly; use the accessors.
|
||||
*/
|
||||
|
||||
#ifdef DEBUG
|
||||
struct nssPointerTrackerStr {
|
||||
PRCallOnceType once;
|
||||
PZLock *lock;
|
||||
PLHashTable *table;
|
||||
};
|
||||
typedef struct nssPointerTrackerStr nssPointerTracker;
|
||||
#endif /* DEBUG */
|
||||
|
||||
/*
|
||||
* nssStringType
|
||||
*
|
||||
* There are several types of strings in the real world. We try to
|
||||
* use only UTF8 and avoid the rest, but that's not always possible.
|
||||
* So we have a couple converter routines to go to and from the other
|
||||
* string types. We have to be able to specify those string types,
|
||||
* so we have this enumeration.
|
||||
*/
|
||||
|
||||
enum nssStringTypeEnum {
|
||||
nssStringType_DirectoryString,
|
||||
nssStringType_TeletexString, /* Not "teletext" with trailing 't' */
|
||||
nssStringType_PrintableString,
|
||||
nssStringType_UniversalString,
|
||||
nssStringType_BMPString,
|
||||
nssStringType_UTF8String,
|
||||
nssStringType_PHGString,
|
||||
nssStringType_GeneralString,
|
||||
|
||||
nssStringType_Unknown = -1
|
||||
};
|
||||
typedef enum nssStringTypeEnum nssStringType;
|
||||
|
||||
PR_END_EXTERN_C
|
||||
|
||||
#endif /* BASET_H */
|
||||
19
security/nss/lib/base/config.mk
Normal file
19
security/nss/lib/base/config.mk
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
#
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
ifdef BUILD_IDG
|
||||
DEFINES += -DNSSDEBUG
|
||||
endif
|
||||
|
||||
#
|
||||
# Override TARGETS variable so that only static libraries
|
||||
# are specifed as dependencies within rules.mk.
|
||||
#
|
||||
|
||||
TARGETS = $(LIBRARY)
|
||||
SHARED_LIBRARY =
|
||||
IMPORT_LIBRARY =
|
||||
PROGRAM =
|
||||
|
||||
269
security/nss/lib/base/error.c
Normal file
269
security/nss/lib/base/error.c
Normal file
|
|
@ -0,0 +1,269 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/*
|
||||
* error.c
|
||||
*
|
||||
* This file contains the code implementing the per-thread error
|
||||
* stacks upon which most NSS routines report their errors.
|
||||
*/
|
||||
|
||||
#ifndef BASE_H
|
||||
#include "base.h"
|
||||
#endif /* BASE_H */
|
||||
#include <limits.h> /* for UINT_MAX */
|
||||
#include <string.h> /* for memmove */
|
||||
|
||||
#define NSS_MAX_ERROR_STACK_COUNT 16 /* error codes */
|
||||
|
||||
/*
|
||||
* The stack itself has a header, and a sequence of integers.
|
||||
* The header records the amount of space (as measured in stack
|
||||
* slots) already allocated for the stack, and the count of the
|
||||
* number of records currently being used.
|
||||
*/
|
||||
|
||||
struct stack_header_str {
|
||||
PRUint16 space;
|
||||
PRUint16 count;
|
||||
};
|
||||
|
||||
struct error_stack_str {
|
||||
struct stack_header_str header;
|
||||
PRInt32 stack[1];
|
||||
};
|
||||
typedef struct error_stack_str error_stack;
|
||||
|
||||
/*
|
||||
* error_stack_index
|
||||
*
|
||||
* Thread-private data must be indexed. This is that index.
|
||||
* See PR_NewThreadPrivateIndex for more information.
|
||||
*
|
||||
* Thread-private data indexes are in the range [0, 127].
|
||||
*/
|
||||
|
||||
#define INVALID_TPD_INDEX UINT_MAX
|
||||
static PRUintn error_stack_index = INVALID_TPD_INDEX;
|
||||
|
||||
/*
|
||||
* call_once
|
||||
*
|
||||
* The thread-private index must be obtained (once!) at runtime.
|
||||
* This block is used for that one-time call.
|
||||
*/
|
||||
|
||||
static PRCallOnceType error_call_once;
|
||||
|
||||
/*
|
||||
* error_once_function
|
||||
*
|
||||
* This is the once-called callback.
|
||||
*/
|
||||
static PRStatus
|
||||
error_once_function(void)
|
||||
{
|
||||
return PR_NewThreadPrivateIndex(&error_stack_index, PR_Free);
|
||||
}
|
||||
|
||||
/*
|
||||
* error_get_my_stack
|
||||
*
|
||||
* This routine returns the calling thread's error stack, creating
|
||||
* it if necessary. It may return NULL upon error, which implicitly
|
||||
* means that it ran out of memory.
|
||||
*/
|
||||
|
||||
static error_stack *
|
||||
error_get_my_stack(void)
|
||||
{
|
||||
PRStatus st;
|
||||
error_stack *rv;
|
||||
PRUintn new_size;
|
||||
PRUint32 new_bytes;
|
||||
error_stack *new_stack;
|
||||
|
||||
if (INVALID_TPD_INDEX == error_stack_index) {
|
||||
st = PR_CallOnce(&error_call_once, error_once_function);
|
||||
if (PR_SUCCESS != st) {
|
||||
return (error_stack *)NULL;
|
||||
}
|
||||
}
|
||||
|
||||
rv = (error_stack *)PR_GetThreadPrivate(error_stack_index);
|
||||
if ((error_stack *)NULL == rv) {
|
||||
/* Doesn't exist; create one */
|
||||
new_size = 16;
|
||||
} else if (rv->header.count == rv->header.space &&
|
||||
rv->header.count < NSS_MAX_ERROR_STACK_COUNT) {
|
||||
/* Too small, expand it */
|
||||
new_size = PR_MIN(rv->header.space * 2, NSS_MAX_ERROR_STACK_COUNT);
|
||||
} else {
|
||||
/* Okay, return it */
|
||||
return rv;
|
||||
}
|
||||
|
||||
new_bytes = (new_size * sizeof(PRInt32)) + sizeof(error_stack);
|
||||
/* Use NSPR's calloc/realloc, not NSS's, to avoid loops! */
|
||||
new_stack = PR_Calloc(1, new_bytes);
|
||||
|
||||
if ((error_stack *)NULL != new_stack) {
|
||||
if ((error_stack *)NULL != rv) {
|
||||
(void)nsslibc_memcpy(new_stack, rv, rv->header.space);
|
||||
}
|
||||
new_stack->header.space = new_size;
|
||||
}
|
||||
|
||||
/* Set the value, whether or not the allocation worked */
|
||||
PR_SetThreadPrivate(error_stack_index, new_stack);
|
||||
return new_stack;
|
||||
}
|
||||
|
||||
/*
|
||||
* The error stack
|
||||
*
|
||||
* The public methods relating to the error stack are:
|
||||
*
|
||||
* NSS_GetError
|
||||
* NSS_GetErrorStack
|
||||
*
|
||||
* The nonpublic methods relating to the error stack are:
|
||||
*
|
||||
* nss_SetError
|
||||
* nss_ClearErrorStack
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* NSS_GetError
|
||||
*
|
||||
* This routine returns the highest-level (most general) error set
|
||||
* by the most recent NSS library routine called by the same thread
|
||||
* calling this routine.
|
||||
*
|
||||
* This routine cannot fail. However, it may return zero, which
|
||||
* indicates that the previous NSS library call did not set an error.
|
||||
*
|
||||
* Return value:
|
||||
* 0 if no error has been set
|
||||
* A nonzero error number
|
||||
*/
|
||||
|
||||
NSS_IMPLEMENT PRInt32
|
||||
NSS_GetError(void)
|
||||
{
|
||||
error_stack *es = error_get_my_stack();
|
||||
|
||||
if ((error_stack *)NULL == es) {
|
||||
return NSS_ERROR_NO_MEMORY; /* Good guess! */
|
||||
}
|
||||
|
||||
if (0 == es->header.count) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return es->stack[es->header.count - 1];
|
||||
}
|
||||
|
||||
/*
|
||||
* NSS_GetErrorStack
|
||||
*
|
||||
* This routine returns a pointer to an array of integers, containing
|
||||
* the entire sequence or "stack" of errors set by the most recent NSS
|
||||
* library routine called by the same thread calling this routine.
|
||||
* NOTE: the caller DOES NOT OWN the memory pointed to by the return
|
||||
* value. The pointer will remain valid until the calling thread
|
||||
* calls another NSS routine. The lowest-level (most specific) error
|
||||
* is first in the array, and the highest-level is last. The array is
|
||||
* zero-terminated. This routine may return NULL upon error; this
|
||||
* indicates a low-memory situation.
|
||||
*
|
||||
* Return value:
|
||||
* NULL upon error, which is an implied NSS_ERROR_NO_MEMORY
|
||||
* A NON-caller-owned pointer to an array of integers
|
||||
*/
|
||||
|
||||
NSS_IMPLEMENT PRInt32 *
|
||||
NSS_GetErrorStack(void)
|
||||
{
|
||||
error_stack *es = error_get_my_stack();
|
||||
|
||||
if ((error_stack *)NULL == es) {
|
||||
return (PRInt32 *)NULL;
|
||||
}
|
||||
|
||||
/* Make sure it's terminated */
|
||||
es->stack[es->header.count] = 0;
|
||||
|
||||
return es->stack;
|
||||
}
|
||||
|
||||
/*
|
||||
* nss_SetError
|
||||
*
|
||||
* This routine places a new error code on the top of the calling
|
||||
* thread's error stack. Calling this routine wiht an error code
|
||||
* of zero will clear the error stack.
|
||||
*/
|
||||
|
||||
NSS_IMPLEMENT void
|
||||
nss_SetError(PRUint32 error)
|
||||
{
|
||||
error_stack *es;
|
||||
|
||||
if (0 == error) {
|
||||
nss_ClearErrorStack();
|
||||
return;
|
||||
}
|
||||
|
||||
es = error_get_my_stack();
|
||||
if ((error_stack *)NULL == es) {
|
||||
/* Oh, well. */
|
||||
return;
|
||||
}
|
||||
|
||||
if (es->header.count < es->header.space) {
|
||||
es->stack[es->header.count++] = error;
|
||||
} else {
|
||||
memmove(es->stack, es->stack + 1,
|
||||
(es->header.space - 1) * (sizeof es->stack[0]));
|
||||
es->stack[es->header.space - 1] = error;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* nss_ClearErrorStack
|
||||
*
|
||||
* This routine clears the calling thread's error stack.
|
||||
*/
|
||||
|
||||
NSS_IMPLEMENT void
|
||||
nss_ClearErrorStack(void)
|
||||
{
|
||||
error_stack *es = error_get_my_stack();
|
||||
if ((error_stack *)NULL == es) {
|
||||
/* Oh, well. */
|
||||
return;
|
||||
}
|
||||
|
||||
es->header.count = 0;
|
||||
es->stack[0] = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* nss_DestroyErrorStack
|
||||
*
|
||||
* This routine frees the calling thread's error stack.
|
||||
*/
|
||||
|
||||
NSS_IMPLEMENT void
|
||||
nss_DestroyErrorStack(void)
|
||||
{
|
||||
if (INVALID_TPD_INDEX != error_stack_index) {
|
||||
PR_SetThreadPrivate(error_stack_index, NULL);
|
||||
}
|
||||
return;
|
||||
}
|
||||
65
security/nss/lib/base/errorval.c
Normal file
65
security/nss/lib/base/errorval.c
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/*
|
||||
* errorval.c
|
||||
*
|
||||
* This file contains the actual error constants used in NSS.
|
||||
*/
|
||||
|
||||
#ifndef NSSBASET_H
|
||||
#include "nssbaset.h"
|
||||
#endif /* NSSBASET_H */
|
||||
|
||||
/* clang-format off */
|
||||
|
||||
const NSSError NSS_ERROR_NO_ERROR = 0;
|
||||
const NSSError NSS_ERROR_INTERNAL_ERROR = 1;
|
||||
const NSSError NSS_ERROR_NO_MEMORY = 2;
|
||||
const NSSError NSS_ERROR_INVALID_POINTER = 3;
|
||||
const NSSError NSS_ERROR_INVALID_ARENA = 4;
|
||||
const NSSError NSS_ERROR_INVALID_ARENA_MARK = 5;
|
||||
const NSSError NSS_ERROR_DUPLICATE_POINTER = 6;
|
||||
const NSSError NSS_ERROR_POINTER_NOT_REGISTERED = 7;
|
||||
const NSSError NSS_ERROR_TRACKER_NOT_EMPTY = 8;
|
||||
const NSSError NSS_ERROR_TRACKER_NOT_INITIALIZED = 9;
|
||||
const NSSError NSS_ERROR_ARENA_MARKED_BY_ANOTHER_THREAD = 10;
|
||||
const NSSError NSS_ERROR_VALUE_TOO_LARGE = 11;
|
||||
const NSSError NSS_ERROR_UNSUPPORTED_TYPE = 12;
|
||||
const NSSError NSS_ERROR_BUFFER_TOO_SHORT = 13;
|
||||
const NSSError NSS_ERROR_INVALID_ATOB_CONTEXT = 14;
|
||||
const NSSError NSS_ERROR_INVALID_BASE64 = 15;
|
||||
const NSSError NSS_ERROR_INVALID_BTOA_CONTEXT = 16;
|
||||
const NSSError NSS_ERROR_INVALID_ITEM = 17;
|
||||
const NSSError NSS_ERROR_INVALID_STRING = 18;
|
||||
const NSSError NSS_ERROR_INVALID_ASN1ENCODER = 19;
|
||||
const NSSError NSS_ERROR_INVALID_ASN1DECODER = 20;
|
||||
|
||||
const NSSError NSS_ERROR_INVALID_BER = 21;
|
||||
const NSSError NSS_ERROR_INVALID_ATAV = 22;
|
||||
const NSSError NSS_ERROR_INVALID_ARGUMENT = 23;
|
||||
const NSSError NSS_ERROR_INVALID_UTF8 = 24;
|
||||
const NSSError NSS_ERROR_INVALID_NSSOID = 25;
|
||||
const NSSError NSS_ERROR_UNKNOWN_ATTRIBUTE = 26;
|
||||
|
||||
const NSSError NSS_ERROR_NOT_FOUND = 27;
|
||||
|
||||
const NSSError NSS_ERROR_INVALID_PASSWORD = 28;
|
||||
const NSSError NSS_ERROR_USER_CANCELED = 29;
|
||||
|
||||
const NSSError NSS_ERROR_MAXIMUM_FOUND = 30;
|
||||
|
||||
const NSSError NSS_ERROR_CERTIFICATE_ISSUER_NOT_FOUND = 31;
|
||||
|
||||
const NSSError NSS_ERROR_CERTIFICATE_IN_CACHE = 32;
|
||||
|
||||
const NSSError NSS_ERROR_HASH_COLLISION = 33;
|
||||
const NSSError NSS_ERROR_DEVICE_ERROR = 34;
|
||||
const NSSError NSS_ERROR_INVALID_CERTIFICATE = 35;
|
||||
const NSSError NSS_ERROR_BUSY = 36;
|
||||
const NSSError NSS_ERROR_ALREADY_INITIALIZED = 37;
|
||||
|
||||
const NSSError NSS_ERROR_PKCS11 = 38;
|
||||
|
||||
/* clang-format on */
|
||||
33
security/nss/lib/base/exports.gyp
Normal file
33
security/nss/lib/base/exports.gyp
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
{
|
||||
'includes': [
|
||||
'../../coreconf/config.gypi'
|
||||
],
|
||||
'targets': [
|
||||
{
|
||||
'target_name': 'lib_base_exports',
|
||||
'type': 'none',
|
||||
'copies': [
|
||||
{
|
||||
'files': [
|
||||
'nssbase.h',
|
||||
'nssbaset.h'
|
||||
],
|
||||
'destination': '<(nss_public_dist_dir)/<(module)'
|
||||
},
|
||||
{
|
||||
'files': [
|
||||
'base.h',
|
||||
'baset.h'
|
||||
],
|
||||
'destination': '<(nss_private_dist_dir)/<(module)'
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
'variables': {
|
||||
'module': 'nss'
|
||||
}
|
||||
}
|
||||
314
security/nss/lib/base/hash.c
Normal file
314
security/nss/lib/base/hash.c
Normal file
|
|
@ -0,0 +1,314 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/*
|
||||
* hash.c
|
||||
*
|
||||
* This is merely a couple wrappers around NSPR's PLHashTable, using
|
||||
* the identity hash and arena-aware allocators.
|
||||
* This is a copy of ckfw/hash.c, with modifications to use NSS types
|
||||
* (not Cryptoki types). Would like for this to be a single implementation,
|
||||
* but doesn't seem like it will work.
|
||||
*/
|
||||
|
||||
#ifndef BASE_H
|
||||
#include "base.h"
|
||||
#endif /* BASE_H */
|
||||
|
||||
#include "prbit.h"
|
||||
|
||||
/*
|
||||
* nssHash
|
||||
*
|
||||
* nssHash_Create
|
||||
* nssHash_Destroy
|
||||
* nssHash_Add
|
||||
* nssHash_Remove
|
||||
* nssHash_Count
|
||||
* nssHash_Exists
|
||||
* nssHash_Lookup
|
||||
* nssHash_Iterate
|
||||
*/
|
||||
|
||||
struct nssHashStr {
|
||||
NSSArena *arena;
|
||||
PRBool i_alloced_arena;
|
||||
PRLock *mutex;
|
||||
|
||||
/*
|
||||
* The invariant that mutex protects is:
|
||||
* The count accurately reflects the hashtable state.
|
||||
*/
|
||||
|
||||
PLHashTable *plHashTable;
|
||||
PRUint32 count;
|
||||
};
|
||||
|
||||
static PLHashNumber
|
||||
nss_identity_hash(const void *key)
|
||||
{
|
||||
return (PLHashNumber)((char *)key - (char *)NULL);
|
||||
}
|
||||
|
||||
static PLHashNumber
|
||||
nss_item_hash(const void *key)
|
||||
{
|
||||
unsigned int i;
|
||||
PLHashNumber h;
|
||||
NSSItem *it = (NSSItem *)key;
|
||||
h = 0;
|
||||
for (i = 0; i < it->size; i++)
|
||||
h = PR_ROTATE_LEFT32(h, 4) ^ ((unsigned char *)it->data)[i];
|
||||
return h;
|
||||
}
|
||||
|
||||
static int
|
||||
nss_compare_items(const void *v1, const void *v2)
|
||||
{
|
||||
PRStatus ignore;
|
||||
return (int)nssItem_Equal((NSSItem *)v1, (NSSItem *)v2, &ignore);
|
||||
}
|
||||
|
||||
/*
|
||||
* nssHash_create
|
||||
*
|
||||
*/
|
||||
NSS_IMPLEMENT nssHash *
|
||||
nssHash_Create(NSSArena *arenaOpt, PRUint32 numBuckets, PLHashFunction keyHash,
|
||||
PLHashComparator keyCompare, PLHashComparator valueCompare)
|
||||
{
|
||||
nssHash *rv;
|
||||
NSSArena *arena;
|
||||
PRBool i_alloced;
|
||||
|
||||
#ifdef NSSDEBUG
|
||||
if (arenaOpt && PR_SUCCESS != nssArena_verifyPointer(arenaOpt)) {
|
||||
nss_SetError(NSS_ERROR_INVALID_POINTER);
|
||||
return (nssHash *)NULL;
|
||||
}
|
||||
#endif /* NSSDEBUG */
|
||||
|
||||
if (arenaOpt) {
|
||||
arena = arenaOpt;
|
||||
i_alloced = PR_FALSE;
|
||||
} else {
|
||||
arena = nssArena_Create();
|
||||
i_alloced = PR_TRUE;
|
||||
}
|
||||
|
||||
rv = nss_ZNEW(arena, nssHash);
|
||||
if ((nssHash *)NULL == rv) {
|
||||
goto loser;
|
||||
}
|
||||
|
||||
rv->mutex = PZ_NewLock(nssILockOther);
|
||||
if ((PZLock *)NULL == rv->mutex) {
|
||||
goto loser;
|
||||
}
|
||||
|
||||
rv->plHashTable =
|
||||
PL_NewHashTable(numBuckets, keyHash, keyCompare, valueCompare,
|
||||
&nssArenaHashAllocOps, arena);
|
||||
if ((PLHashTable *)NULL == rv->plHashTable) {
|
||||
(void)PZ_DestroyLock(rv->mutex);
|
||||
goto loser;
|
||||
}
|
||||
|
||||
rv->count = 0;
|
||||
rv->arena = arena;
|
||||
rv->i_alloced_arena = i_alloced;
|
||||
|
||||
return rv;
|
||||
loser:
|
||||
(void)nss_ZFreeIf(rv);
|
||||
return (nssHash *)NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* nssHash_CreatePointer
|
||||
*
|
||||
*/
|
||||
NSS_IMPLEMENT nssHash *
|
||||
nssHash_CreatePointer(NSSArena *arenaOpt, PRUint32 numBuckets)
|
||||
{
|
||||
return nssHash_Create(arenaOpt, numBuckets, nss_identity_hash,
|
||||
PL_CompareValues, PL_CompareValues);
|
||||
}
|
||||
|
||||
/*
|
||||
* nssHash_CreateString
|
||||
*
|
||||
*/
|
||||
NSS_IMPLEMENT nssHash *
|
||||
nssHash_CreateString(NSSArena *arenaOpt, PRUint32 numBuckets)
|
||||
{
|
||||
return nssHash_Create(arenaOpt, numBuckets, PL_HashString,
|
||||
PL_CompareStrings, PL_CompareStrings);
|
||||
}
|
||||
|
||||
/*
|
||||
* nssHash_CreateItem
|
||||
*
|
||||
*/
|
||||
NSS_IMPLEMENT nssHash *
|
||||
nssHash_CreateItem(NSSArena *arenaOpt, PRUint32 numBuckets)
|
||||
{
|
||||
return nssHash_Create(arenaOpt, numBuckets, nss_item_hash,
|
||||
nss_compare_items, PL_CompareValues);
|
||||
}
|
||||
|
||||
/*
|
||||
* nssHash_Destroy
|
||||
*
|
||||
*/
|
||||
NSS_IMPLEMENT void
|
||||
nssHash_Destroy(nssHash *hash)
|
||||
{
|
||||
(void)PZ_DestroyLock(hash->mutex);
|
||||
PL_HashTableDestroy(hash->plHashTable);
|
||||
if (hash->i_alloced_arena) {
|
||||
nssArena_Destroy(hash->arena);
|
||||
} else {
|
||||
nss_ZFreeIf(hash);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* nssHash_Add
|
||||
*
|
||||
*/
|
||||
NSS_IMPLEMENT PRStatus
|
||||
nssHash_Add(nssHash *hash, const void *key, const void *value)
|
||||
{
|
||||
PRStatus error = PR_FAILURE;
|
||||
PLHashEntry *he;
|
||||
|
||||
PZ_Lock(hash->mutex);
|
||||
|
||||
he = PL_HashTableAdd(hash->plHashTable, key, (void *)value);
|
||||
if ((PLHashEntry *)NULL == he) {
|
||||
nss_SetError(NSS_ERROR_NO_MEMORY);
|
||||
} else if (he->value != value) {
|
||||
nss_SetError(NSS_ERROR_HASH_COLLISION);
|
||||
} else {
|
||||
hash->count++;
|
||||
error = PR_SUCCESS;
|
||||
}
|
||||
|
||||
(void)PZ_Unlock(hash->mutex);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
/*
|
||||
* nssHash_Remove
|
||||
*
|
||||
*/
|
||||
NSS_IMPLEMENT void
|
||||
nssHash_Remove(nssHash *hash, const void *it)
|
||||
{
|
||||
PRBool found;
|
||||
|
||||
PZ_Lock(hash->mutex);
|
||||
|
||||
found = PL_HashTableRemove(hash->plHashTable, it);
|
||||
if (found) {
|
||||
hash->count--;
|
||||
}
|
||||
|
||||
(void)PZ_Unlock(hash->mutex);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* nssHash_Count
|
||||
*
|
||||
*/
|
||||
NSS_IMPLEMENT PRUint32
|
||||
nssHash_Count(nssHash *hash)
|
||||
{
|
||||
PRUint32 count;
|
||||
|
||||
PZ_Lock(hash->mutex);
|
||||
|
||||
count = hash->count;
|
||||
|
||||
(void)PZ_Unlock(hash->mutex);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/*
|
||||
* nssHash_Exists
|
||||
*
|
||||
*/
|
||||
NSS_IMPLEMENT PRBool
|
||||
nssHash_Exists(nssHash *hash, const void *it)
|
||||
{
|
||||
void *value;
|
||||
|
||||
PZ_Lock(hash->mutex);
|
||||
|
||||
value = PL_HashTableLookup(hash->plHashTable, it);
|
||||
|
||||
(void)PZ_Unlock(hash->mutex);
|
||||
|
||||
if ((void *)NULL == value) {
|
||||
return PR_FALSE;
|
||||
} else {
|
||||
return PR_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* nssHash_Lookup
|
||||
*
|
||||
*/
|
||||
NSS_IMPLEMENT void *
|
||||
nssHash_Lookup(nssHash *hash, const void *it)
|
||||
{
|
||||
void *rv;
|
||||
|
||||
PZ_Lock(hash->mutex);
|
||||
|
||||
rv = PL_HashTableLookup(hash->plHashTable, it);
|
||||
|
||||
(void)PZ_Unlock(hash->mutex);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
struct arg_str {
|
||||
nssHashIterator fcn;
|
||||
void *closure;
|
||||
};
|
||||
|
||||
static PRIntn
|
||||
nss_hash_enumerator(PLHashEntry *he, PRIntn index, void *arg)
|
||||
{
|
||||
struct arg_str *as = (struct arg_str *)arg;
|
||||
as->fcn(he->key, he->value, as->closure);
|
||||
return HT_ENUMERATE_NEXT;
|
||||
}
|
||||
|
||||
/*
|
||||
* nssHash_Iterate
|
||||
*
|
||||
* NOTE that the iteration function will be called with the hashtable locked.
|
||||
*/
|
||||
NSS_IMPLEMENT void
|
||||
nssHash_Iterate(nssHash *hash, nssHashIterator fcn, void *closure)
|
||||
{
|
||||
struct arg_str as;
|
||||
as.fcn = fcn;
|
||||
as.closure = closure;
|
||||
|
||||
PZ_Lock(hash->mutex);
|
||||
|
||||
PL_HashTableEnumerateEntries(hash->plHashTable, nss_hash_enumerator, &as);
|
||||
|
||||
(void)PZ_Unlock(hash->mutex);
|
||||
|
||||
return;
|
||||
}
|
||||
64
security/nss/lib/base/hashops.c
Normal file
64
security/nss/lib/base/hashops.c
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/*
|
||||
* hashops.c
|
||||
*
|
||||
* This file includes a set of PLHashAllocOps that use NSSArenas.
|
||||
*/
|
||||
|
||||
#ifndef BASE_H
|
||||
#include "base.h"
|
||||
#endif /* BASE_H */
|
||||
|
||||
static void *PR_CALLBACK
|
||||
nss_arena_hash_alloc_table(void *pool, PRSize size)
|
||||
{
|
||||
NSSArena *arena = (NSSArena *)NULL;
|
||||
|
||||
#ifdef NSSDEBUG
|
||||
if ((void *)NULL != arena) {
|
||||
if (PR_SUCCESS != nssArena_verifyPointer(arena)) {
|
||||
return (void *)NULL;
|
||||
}
|
||||
}
|
||||
#endif /* NSSDEBUG */
|
||||
|
||||
return nss_ZAlloc(arena, size);
|
||||
}
|
||||
|
||||
static void PR_CALLBACK
|
||||
nss_arena_hash_free_table(void *pool, void *item)
|
||||
{
|
||||
(void)nss_ZFreeIf(item);
|
||||
}
|
||||
|
||||
static PLHashEntry *PR_CALLBACK
|
||||
nss_arena_hash_alloc_entry(void *pool, const void *key)
|
||||
{
|
||||
NSSArena *arena = NULL;
|
||||
|
||||
#ifdef NSSDEBUG
|
||||
if ((void *)NULL != arena) {
|
||||
if (PR_SUCCESS != nssArena_verifyPointer(arena)) {
|
||||
return (void *)NULL;
|
||||
}
|
||||
}
|
||||
#endif /* NSSDEBUG */
|
||||
|
||||
return nss_ZNEW(arena, PLHashEntry);
|
||||
}
|
||||
|
||||
static void PR_CALLBACK
|
||||
nss_arena_hash_free_entry(void *pool, PLHashEntry *he, PRUintn flag)
|
||||
{
|
||||
if (HT_FREE_ENTRY == flag) {
|
||||
(void)nss_ZFreeIf(he);
|
||||
}
|
||||
}
|
||||
|
||||
NSS_IMPLEMENT_DATA PLHashAllocOps nssArenaHashAllocOps = {
|
||||
nss_arena_hash_alloc_table, nss_arena_hash_free_table,
|
||||
nss_arena_hash_alloc_entry, nss_arena_hash_free_entry
|
||||
};
|
||||
186
security/nss/lib/base/item.c
Normal file
186
security/nss/lib/base/item.c
Normal file
|
|
@ -0,0 +1,186 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/*
|
||||
* item.c
|
||||
*
|
||||
* This contains some item-manipulation code.
|
||||
*/
|
||||
|
||||
#ifndef BASE_H
|
||||
#include "base.h"
|
||||
#endif /* BASE_H */
|
||||
|
||||
/*
|
||||
* nssItem_Create
|
||||
*
|
||||
* -- fgmr comments --
|
||||
*
|
||||
* The error may be one of the following values:
|
||||
* NSS_ERROR_INVALID_ARENA
|
||||
* NSS_ERROR_NO_MEMORY
|
||||
* NSS_ERROR_ARENA_MARKED_BY_ANOTHER_THREAD
|
||||
* NSS_ERROR_INVALID_POINTER
|
||||
*
|
||||
* Return value:
|
||||
* A pointer to an NSSItem upon success
|
||||
* NULL upon failure
|
||||
*/
|
||||
|
||||
NSS_IMPLEMENT NSSItem *
|
||||
nssItem_Create(NSSArena *arenaOpt, NSSItem *rvOpt, PRUint32 length,
|
||||
const void *data)
|
||||
{
|
||||
NSSItem *rv = (NSSItem *)NULL;
|
||||
|
||||
#ifdef DEBUG
|
||||
if ((NSSArena *)NULL != arenaOpt) {
|
||||
if (PR_SUCCESS != nssArena_verifyPointer(arenaOpt)) {
|
||||
return (NSSItem *)NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if ((const void *)NULL == data) {
|
||||
if (length > 0) {
|
||||
nss_SetError(NSS_ERROR_INVALID_POINTER);
|
||||
return (NSSItem *)NULL;
|
||||
}
|
||||
}
|
||||
#endif /* DEBUG */
|
||||
|
||||
if ((NSSItem *)NULL == rvOpt) {
|
||||
rv = (NSSItem *)nss_ZNEW(arenaOpt, NSSItem);
|
||||
if ((NSSItem *)NULL == rv) {
|
||||
goto loser;
|
||||
}
|
||||
} else {
|
||||
rv = rvOpt;
|
||||
}
|
||||
|
||||
rv->size = length;
|
||||
rv->data = nss_ZAlloc(arenaOpt, length);
|
||||
if ((void *)NULL == rv->data) {
|
||||
goto loser;
|
||||
}
|
||||
|
||||
if (length > 0) {
|
||||
(void)nsslibc_memcpy(rv->data, data, length);
|
||||
}
|
||||
|
||||
return rv;
|
||||
|
||||
loser:
|
||||
if (rv != rvOpt) {
|
||||
nss_ZFreeIf(rv);
|
||||
}
|
||||
|
||||
return (NSSItem *)NULL;
|
||||
}
|
||||
|
||||
NSS_IMPLEMENT void
|
||||
nssItem_Destroy(NSSItem *item)
|
||||
{
|
||||
nss_ClearErrorStack();
|
||||
|
||||
nss_ZFreeIf(item->data);
|
||||
nss_ZFreeIf(item);
|
||||
}
|
||||
|
||||
/*
|
||||
* nssItem_Duplicate
|
||||
*
|
||||
* -- fgmr comments --
|
||||
*
|
||||
* The error may be one of the following values:
|
||||
* NSS_ERROR_INVALID_ARENA
|
||||
* NSS_ERROR_NO_MEMORY
|
||||
* NSS_ERROR_ARENA_MARKED_BY_ANOTHER_THREAD
|
||||
* NSS_ERROR_INVALID_ITEM
|
||||
*
|
||||
* Return value:
|
||||
* A pointer to an NSSItem upon success
|
||||
* NULL upon failure
|
||||
*/
|
||||
|
||||
NSS_IMPLEMENT NSSItem *
|
||||
nssItem_Duplicate(NSSItem *obj, NSSArena *arenaOpt, NSSItem *rvOpt)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
if ((NSSArena *)NULL != arenaOpt) {
|
||||
if (PR_SUCCESS != nssArena_verifyPointer(arenaOpt)) {
|
||||
return (NSSItem *)NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if ((NSSItem *)NULL == obj) {
|
||||
nss_SetError(NSS_ERROR_INVALID_ITEM);
|
||||
return (NSSItem *)NULL;
|
||||
}
|
||||
#endif /* DEBUG */
|
||||
|
||||
return nssItem_Create(arenaOpt, rvOpt, obj->size, obj->data);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
/*
|
||||
* nssItem_verifyPointer
|
||||
*
|
||||
* -- fgmr comments --
|
||||
*
|
||||
* The error may be one of the following values:
|
||||
* NSS_ERROR_INVALID_ITEM
|
||||
*
|
||||
* Return value:
|
||||
* PR_SUCCESS upon success
|
||||
* PR_FAILURE upon failure
|
||||
*/
|
||||
|
||||
NSS_IMPLEMENT PRStatus
|
||||
nssItem_verifyPointer(const NSSItem *item)
|
||||
{
|
||||
if (((const NSSItem *)NULL == item) ||
|
||||
(((void *)NULL == item->data) && (item->size > 0))) {
|
||||
nss_SetError(NSS_ERROR_INVALID_ITEM);
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
return PR_SUCCESS;
|
||||
}
|
||||
#endif /* DEBUG */
|
||||
|
||||
/*
|
||||
* nssItem_Equal
|
||||
*
|
||||
* -- fgmr comments --
|
||||
*
|
||||
* The error may be one of the following values:
|
||||
* NSS_ERROR_INVALID_ITEM
|
||||
*
|
||||
* Return value:
|
||||
* PR_TRUE if the items are identical
|
||||
* PR_FALSE if they aren't
|
||||
* PR_FALSE upon error
|
||||
*/
|
||||
|
||||
NSS_IMPLEMENT PRBool
|
||||
nssItem_Equal(const NSSItem *one, const NSSItem *two, PRStatus *statusOpt)
|
||||
{
|
||||
if ((PRStatus *)NULL != statusOpt) {
|
||||
*statusOpt = PR_SUCCESS;
|
||||
}
|
||||
|
||||
if (((const NSSItem *)NULL == one) && ((const NSSItem *)NULL == two)) {
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
if (((const NSSItem *)NULL == one) || ((const NSSItem *)NULL == two)) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
if (one->size != two->size) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
return nsslibc_memequal(one->data, two->data, one->size, statusOpt);
|
||||
}
|
||||
143
security/nss/lib/base/libc.c
Normal file
143
security/nss/lib/base/libc.c
Normal file
|
|
@ -0,0 +1,143 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/*
|
||||
* libc.c
|
||||
*
|
||||
* This file contains our wrappers/reimplementations for "standard"
|
||||
* libc functions. Things like "memcpy." We add to this as we need
|
||||
* it. Oh, and let's keep it in alphabetical order, should it ever
|
||||
* get large. Most string/character stuff should be in utf8.c, not
|
||||
* here. This file (and maybe utf8.c) should be the only ones in
|
||||
* NSS to include files with angle brackets.
|
||||
*/
|
||||
|
||||
#ifndef BASE_H
|
||||
#include "base.h"
|
||||
#endif /* BASE_H */
|
||||
|
||||
#include <string.h> /* memcpy, memset */
|
||||
|
||||
/*
|
||||
* nsslibc_memcpy
|
||||
* nsslibc_memset
|
||||
* nsslibc_offsetof
|
||||
* nsslibc_memequal
|
||||
*/
|
||||
|
||||
/*
|
||||
* nsslibc_memcpy
|
||||
*
|
||||
* Errors:
|
||||
* NSS_ERROR_INVALID_POINTER
|
||||
*
|
||||
* Return value:
|
||||
* NULL on error
|
||||
* The destination pointer on success
|
||||
*/
|
||||
|
||||
NSS_IMPLEMENT void *
|
||||
nsslibc_memcpy(void *dest, const void *source, PRUint32 n)
|
||||
{
|
||||
#ifdef NSSDEBUG
|
||||
if (((void *)NULL == dest) || ((const void *)NULL == source)) {
|
||||
nss_SetError(NSS_ERROR_INVALID_POINTER);
|
||||
return (void *)NULL;
|
||||
}
|
||||
#endif /* NSSDEBUG */
|
||||
|
||||
return memcpy(dest, source, (size_t)n);
|
||||
}
|
||||
|
||||
/*
|
||||
* nsslibc_memset
|
||||
*
|
||||
* Errors:
|
||||
* NSS_ERROR_INVALID_POINTER
|
||||
*
|
||||
* Return value:
|
||||
* NULL on error
|
||||
* The destination pointer on success
|
||||
*/
|
||||
|
||||
NSS_IMPLEMENT void *
|
||||
nsslibc_memset(void *dest, PRUint8 byte, PRUint32 n)
|
||||
{
|
||||
#ifdef NSSDEBUG
|
||||
if (((void *)NULL == dest)) {
|
||||
nss_SetError(NSS_ERROR_INVALID_POINTER);
|
||||
return (void *)NULL;
|
||||
}
|
||||
#endif /* NSSDEBUG */
|
||||
|
||||
return memset(dest, (int)byte, (size_t)n);
|
||||
}
|
||||
|
||||
/*
|
||||
* nsslibc_memequal
|
||||
*
|
||||
* Errors:
|
||||
* NSS_ERROR_INVALID_POINTER
|
||||
*
|
||||
* Return value:
|
||||
* PR_TRUE if they match
|
||||
* PR_FALSE if they don't
|
||||
* PR_FALSE upon error
|
||||
*/
|
||||
|
||||
NSS_IMPLEMENT PRBool
|
||||
nsslibc_memequal(const void *a, const void *b, PRUint32 len,
|
||||
PRStatus *statusOpt)
|
||||
{
|
||||
#ifdef NSSDEBUG
|
||||
if ((((void *)NULL == a) || ((void *)NULL == b))) {
|
||||
nss_SetError(NSS_ERROR_INVALID_POINTER);
|
||||
if ((PRStatus *)NULL != statusOpt) {
|
||||
*statusOpt = PR_FAILURE;
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
#endif /* NSSDEBUG */
|
||||
|
||||
if ((PRStatus *)NULL != statusOpt) {
|
||||
*statusOpt = PR_SUCCESS;
|
||||
}
|
||||
|
||||
if (0 == memcmp(a, b, len)) {
|
||||
return PR_TRUE;
|
||||
} else {
|
||||
return PR_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* nsslibc_memcmp
|
||||
*/
|
||||
|
||||
NSS_IMPLEMENT PRInt32
|
||||
nsslibc_memcmp(const void *a, const void *b, PRUint32 len, PRStatus *statusOpt)
|
||||
{
|
||||
int v;
|
||||
|
||||
#ifdef NSSDEBUG
|
||||
if ((((void *)NULL == a) || ((void *)NULL == b))) {
|
||||
nss_SetError(NSS_ERROR_INVALID_POINTER);
|
||||
if ((PRStatus *)NULL != statusOpt) {
|
||||
*statusOpt = PR_FAILURE;
|
||||
}
|
||||
return -2;
|
||||
}
|
||||
#endif /* NSSDEBUG */
|
||||
|
||||
if ((PRStatus *)NULL != statusOpt) {
|
||||
*statusOpt = PR_SUCCESS;
|
||||
}
|
||||
|
||||
v = memcmp(a, b, len);
|
||||
return (PRInt32)v;
|
||||
}
|
||||
|
||||
/*
|
||||
* offsetof is a preprocessor definition
|
||||
*/
|
||||
405
security/nss/lib/base/list.c
Normal file
405
security/nss/lib/base/list.c
Normal file
|
|
@ -0,0 +1,405 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/*
|
||||
* list.c
|
||||
*
|
||||
* This contains the implementation of NSS's thread-safe linked list.
|
||||
*/
|
||||
|
||||
#ifndef BASE_H
|
||||
#include "base.h"
|
||||
#endif /* BASE_H */
|
||||
|
||||
struct nssListElementStr {
|
||||
PRCList link;
|
||||
void *data;
|
||||
};
|
||||
|
||||
typedef struct nssListElementStr nssListElement;
|
||||
|
||||
struct nssListStr {
|
||||
NSSArena *arena;
|
||||
PZLock *lock;
|
||||
nssListElement *head;
|
||||
PRUint32 count;
|
||||
nssListCompareFunc compareFunc;
|
||||
nssListSortFunc sortFunc;
|
||||
PRBool i_alloced_arena;
|
||||
};
|
||||
|
||||
struct nssListIteratorStr {
|
||||
PZLock *lock;
|
||||
nssList *list;
|
||||
nssListElement *current;
|
||||
};
|
||||
|
||||
#define NSSLIST_LOCK_IF(list) \
|
||||
if ((list)->lock) \
|
||||
PZ_Lock((list)->lock)
|
||||
|
||||
#define NSSLIST_UNLOCK_IF(list) \
|
||||
if ((list)->lock) \
|
||||
PZ_Unlock((list)->lock)
|
||||
|
||||
static PRBool
|
||||
pointer_compare(void *a, void *b)
|
||||
{
|
||||
return (PRBool)(a == b);
|
||||
}
|
||||
|
||||
static nssListElement *
|
||||
nsslist_get_matching_element(nssList *list, void *data)
|
||||
{
|
||||
nssListElement *node;
|
||||
node = list->head;
|
||||
if (!node) {
|
||||
return NULL;
|
||||
}
|
||||
while (node) {
|
||||
/* using a callback slows things down when it's just compare ... */
|
||||
if (list->compareFunc(node->data, data)) {
|
||||
break;
|
||||
}
|
||||
if (&node->link == PR_LIST_TAIL(&list->head->link)) {
|
||||
node = NULL;
|
||||
break;
|
||||
}
|
||||
node = (nssListElement *)PR_NEXT_LINK(&node->link);
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
NSS_IMPLEMENT nssList *
|
||||
nssList_Create(NSSArena *arenaOpt, PRBool threadSafe)
|
||||
{
|
||||
NSSArena *arena;
|
||||
nssList *list;
|
||||
PRBool i_alloced;
|
||||
if (arenaOpt) {
|
||||
arena = arenaOpt;
|
||||
i_alloced = PR_FALSE;
|
||||
} else {
|
||||
arena = nssArena_Create();
|
||||
i_alloced = PR_TRUE;
|
||||
}
|
||||
if (!arena) {
|
||||
return (nssList *)NULL;
|
||||
}
|
||||
list = nss_ZNEW(arena, nssList);
|
||||
if (!list) {
|
||||
if (!arenaOpt) {
|
||||
NSSArena_Destroy(arena);
|
||||
}
|
||||
return (nssList *)NULL;
|
||||
}
|
||||
if (threadSafe) {
|
||||
list->lock = PZ_NewLock(nssILockOther);
|
||||
if (!list->lock) {
|
||||
if (arenaOpt) {
|
||||
nss_ZFreeIf(list);
|
||||
} else {
|
||||
NSSArena_Destroy(arena);
|
||||
}
|
||||
return (nssList *)NULL;
|
||||
}
|
||||
}
|
||||
list->arena = arena;
|
||||
list->i_alloced_arena = i_alloced;
|
||||
list->compareFunc = pointer_compare;
|
||||
return list;
|
||||
}
|
||||
|
||||
NSS_IMPLEMENT PRStatus
|
||||
nssList_Destroy(nssList *list)
|
||||
{
|
||||
if (!list) {
|
||||
return PR_SUCCESS;
|
||||
}
|
||||
if (!list->i_alloced_arena) {
|
||||
nssList_Clear(list, NULL);
|
||||
}
|
||||
if (list->lock) {
|
||||
(void)PZ_DestroyLock(list->lock);
|
||||
}
|
||||
if (list->i_alloced_arena) {
|
||||
NSSArena_Destroy(list->arena);
|
||||
list = NULL;
|
||||
}
|
||||
nss_ZFreeIf(list);
|
||||
return PR_SUCCESS;
|
||||
}
|
||||
|
||||
NSS_IMPLEMENT void
|
||||
nssList_SetCompareFunction(nssList *list, nssListCompareFunc compareFunc)
|
||||
{
|
||||
list->compareFunc = compareFunc;
|
||||
}
|
||||
|
||||
NSS_IMPLEMENT void
|
||||
nssList_SetSortFunction(nssList *list, nssListSortFunc sortFunc)
|
||||
{
|
||||
/* XXX if list already has elements, sort them */
|
||||
list->sortFunc = sortFunc;
|
||||
}
|
||||
|
||||
NSS_IMPLEMENT nssListCompareFunc
|
||||
nssList_GetCompareFunction(nssList *list)
|
||||
{
|
||||
return list->compareFunc;
|
||||
}
|
||||
|
||||
NSS_IMPLEMENT void
|
||||
nssList_Clear(nssList *list, nssListElementDestructorFunc destructor)
|
||||
{
|
||||
PRCList *link;
|
||||
nssListElement *node, *tmp;
|
||||
if (!list) {
|
||||
return;
|
||||
}
|
||||
NSSLIST_LOCK_IF(list);
|
||||
node = list->head;
|
||||
list->head = NULL;
|
||||
while (node && list->count > 0) {
|
||||
if (destructor)
|
||||
(*destructor)(node->data);
|
||||
link = &node->link;
|
||||
tmp = (nssListElement *)PR_NEXT_LINK(link);
|
||||
PR_REMOVE_LINK(link);
|
||||
nss_ZFreeIf(node);
|
||||
node = tmp;
|
||||
--list->count;
|
||||
}
|
||||
NSSLIST_UNLOCK_IF(list);
|
||||
}
|
||||
|
||||
static PRStatus
|
||||
nsslist_add_element(nssList *list, void *data)
|
||||
{
|
||||
nssListElement *node = nss_ZNEW(list->arena, nssListElement);
|
||||
if (!node) {
|
||||
return PR_FAILURE;
|
||||
}
|
||||
PR_INIT_CLIST(&node->link);
|
||||
node->data = data;
|
||||
if (list->head) {
|
||||
if (list->sortFunc) {
|
||||
PRCList *link;
|
||||
nssListElement *currNode;
|
||||
currNode = list->head;
|
||||
/* insert in ordered list */
|
||||
while (currNode) {
|
||||
link = &currNode->link;
|
||||
if (list->sortFunc(data, currNode->data) <= 0) {
|
||||
/* new element goes before current node */
|
||||
PR_INSERT_BEFORE(&node->link, link);
|
||||
/* reset head if this is first */
|
||||
if (currNode == list->head)
|
||||
list->head = node;
|
||||
break;
|
||||
}
|
||||
if (link == PR_LIST_TAIL(&list->head->link)) {
|
||||
/* reached end of list, append */
|
||||
PR_INSERT_AFTER(&node->link, link);
|
||||
break;
|
||||
}
|
||||
currNode = (nssListElement *)PR_NEXT_LINK(&currNode->link);
|
||||
}
|
||||
} else {
|
||||
/* not sorting */
|
||||
PR_APPEND_LINK(&node->link, &list->head->link);
|
||||
}
|
||||
} else {
|
||||
list->head = node;
|
||||
}
|
||||
++list->count;
|
||||
return PR_SUCCESS;
|
||||
}
|
||||
|
||||
NSS_IMPLEMENT PRStatus
|
||||
nssList_Add(nssList *list, void *data)
|
||||
{
|
||||
NSSLIST_LOCK_IF(list);
|
||||
(void)nsslist_add_element(list, data);
|
||||
NSSLIST_UNLOCK_IF(list);
|
||||
return PR_SUCCESS;
|
||||
}
|
||||
|
||||
NSS_IMPLEMENT PRStatus
|
||||
nssList_AddUnique(nssList *list, void *data)
|
||||
{
|
||||
PRStatus nssrv;
|
||||
nssListElement *node;
|
||||
NSSLIST_LOCK_IF(list);
|
||||
node = nsslist_get_matching_element(list, data);
|
||||
if (node) {
|
||||
/* already in, finish */
|
||||
NSSLIST_UNLOCK_IF(list);
|
||||
return PR_SUCCESS;
|
||||
}
|
||||
nssrv = nsslist_add_element(list, data);
|
||||
NSSLIST_UNLOCK_IF(list);
|
||||
return nssrv;
|
||||
}
|
||||
|
||||
NSS_IMPLEMENT PRStatus
|
||||
nssList_Remove(nssList *list, void *data)
|
||||
{
|
||||
nssListElement *node;
|
||||
NSSLIST_LOCK_IF(list);
|
||||
node = nsslist_get_matching_element(list, data);
|
||||
if (node) {
|
||||
if (node == list->head) {
|
||||
list->head = (nssListElement *)PR_NEXT_LINK(&node->link);
|
||||
}
|
||||
PR_REMOVE_LINK(&node->link);
|
||||
nss_ZFreeIf(node);
|
||||
if (--list->count == 0) {
|
||||
list->head = NULL;
|
||||
}
|
||||
}
|
||||
NSSLIST_UNLOCK_IF(list);
|
||||
return PR_SUCCESS;
|
||||
}
|
||||
|
||||
NSS_IMPLEMENT void *
|
||||
nssList_Get(nssList *list, void *data)
|
||||
{
|
||||
nssListElement *node;
|
||||
NSSLIST_LOCK_IF(list);
|
||||
node = nsslist_get_matching_element(list, data);
|
||||
NSSLIST_UNLOCK_IF(list);
|
||||
return (node) ? node->data : NULL;
|
||||
}
|
||||
|
||||
NSS_IMPLEMENT PRUint32
|
||||
nssList_Count(nssList *list)
|
||||
{
|
||||
return list->count;
|
||||
}
|
||||
|
||||
NSS_IMPLEMENT PRStatus
|
||||
nssList_GetArray(nssList *list, void **rvArray, PRUint32 maxElements)
|
||||
{
|
||||
nssListElement *node;
|
||||
PRUint32 i = 0;
|
||||
PR_ASSERT(maxElements > 0);
|
||||
node = list->head;
|
||||
if (!node) {
|
||||
return PR_SUCCESS;
|
||||
}
|
||||
NSSLIST_LOCK_IF(list);
|
||||
while (node) {
|
||||
rvArray[i++] = node->data;
|
||||
if (i == maxElements)
|
||||
break;
|
||||
node = (nssListElement *)PR_NEXT_LINK(&node->link);
|
||||
if (node == list->head) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
NSSLIST_UNLOCK_IF(list);
|
||||
return PR_SUCCESS;
|
||||
}
|
||||
|
||||
NSS_IMPLEMENT nssList *
|
||||
nssList_Clone(nssList *list)
|
||||
{
|
||||
nssList *rvList;
|
||||
nssListElement *node;
|
||||
rvList = nssList_Create(NULL, (list->lock != NULL));
|
||||
if (!rvList) {
|
||||
return NULL;
|
||||
}
|
||||
NSSLIST_LOCK_IF(list);
|
||||
if (list->count > 0) {
|
||||
node = list->head;
|
||||
while (PR_TRUE) {
|
||||
nssList_Add(rvList, node->data);
|
||||
node = (nssListElement *)PR_NEXT_LINK(&node->link);
|
||||
if (node == list->head) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
NSSLIST_UNLOCK_IF(list);
|
||||
return rvList;
|
||||
}
|
||||
|
||||
NSS_IMPLEMENT nssListIterator *
|
||||
nssList_CreateIterator(nssList *list)
|
||||
{
|
||||
nssListIterator *rvIterator;
|
||||
rvIterator = nss_ZNEW(NULL, nssListIterator);
|
||||
if (!rvIterator) {
|
||||
return NULL;
|
||||
}
|
||||
rvIterator->list = nssList_Clone(list);
|
||||
if (!rvIterator->list) {
|
||||
nss_ZFreeIf(rvIterator);
|
||||
return NULL;
|
||||
}
|
||||
rvIterator->current = rvIterator->list->head;
|
||||
if (list->lock) {
|
||||
rvIterator->lock = PZ_NewLock(nssILockOther);
|
||||
if (!rvIterator->lock) {
|
||||
nssList_Destroy(rvIterator->list);
|
||||
nss_ZFreeIf(rvIterator);
|
||||
rvIterator = NULL;
|
||||
}
|
||||
}
|
||||
return rvIterator;
|
||||
}
|
||||
|
||||
NSS_IMPLEMENT void
|
||||
nssListIterator_Destroy(nssListIterator *iter)
|
||||
{
|
||||
if (iter->lock) {
|
||||
(void)PZ_DestroyLock(iter->lock);
|
||||
}
|
||||
if (iter->list) {
|
||||
nssList_Destroy(iter->list);
|
||||
}
|
||||
nss_ZFreeIf(iter);
|
||||
}
|
||||
|
||||
NSS_IMPLEMENT void *
|
||||
nssListIterator_Start(nssListIterator *iter)
|
||||
{
|
||||
NSSLIST_LOCK_IF(iter);
|
||||
if (iter->list->count == 0) {
|
||||
return NULL;
|
||||
}
|
||||
iter->current = iter->list->head;
|
||||
return iter->current->data;
|
||||
}
|
||||
|
||||
NSS_IMPLEMENT void *
|
||||
nssListIterator_Next(nssListIterator *iter)
|
||||
{
|
||||
nssListElement *node;
|
||||
PRCList *link;
|
||||
if (iter->list->count == 1 || iter->current == NULL) {
|
||||
/* Reached the end of the list. Don't change the state, force to
|
||||
* user to call nssList_Finish to clean up.
|
||||
*/
|
||||
return NULL;
|
||||
}
|
||||
node = (nssListElement *)PR_NEXT_LINK(&iter->current->link);
|
||||
link = &node->link;
|
||||
if (link == PR_LIST_TAIL(&iter->list->head->link)) {
|
||||
/* Signal the end of the list. */
|
||||
iter->current = NULL;
|
||||
return node->data;
|
||||
}
|
||||
iter->current = node;
|
||||
return node->data;
|
||||
}
|
||||
|
||||
NSS_IMPLEMENT PRStatus
|
||||
nssListIterator_Finish(nssListIterator *iter)
|
||||
{
|
||||
iter->current = iter->list->head;
|
||||
return (iter->lock) ? PZ_Unlock(iter->lock) : PR_SUCCESS;
|
||||
}
|
||||
38
security/nss/lib/base/manifest.mn
Normal file
38
security/nss/lib/base/manifest.mn
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
#
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
CORE_DEPTH = ../..
|
||||
|
||||
PRIVATE_EXPORTS = \
|
||||
baset.h \
|
||||
base.h \
|
||||
$(NULL)
|
||||
|
||||
EXPORTS = \
|
||||
nssbaset.h \
|
||||
nssbase.h \
|
||||
$(NULL)
|
||||
|
||||
MODULE = nss
|
||||
|
||||
CSRCS = \
|
||||
arena.c \
|
||||
error.c \
|
||||
errorval.c \
|
||||
hashops.c \
|
||||
libc.c \
|
||||
tracker.c \
|
||||
item.c \
|
||||
utf8.c \
|
||||
list.c \
|
||||
hash.c \
|
||||
$(NULL)
|
||||
|
||||
REQUIRES = nspr
|
||||
|
||||
LIBRARY_NAME = nssb
|
||||
|
||||
# This part of the code, including all sub-dirs, can be optimized for size
|
||||
export ALLOW_OPT_CODE_SIZE = 1
|
||||
233
security/nss/lib/base/nssbase.h
Normal file
233
security/nss/lib/base/nssbase.h
Normal file
|
|
@ -0,0 +1,233 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef NSSBASE_H
|
||||
#define NSSBASE_H
|
||||
|
||||
/*
|
||||
* nssbase.h
|
||||
*
|
||||
* This header file contains the prototypes of the basic public
|
||||
* NSS routines.
|
||||
*/
|
||||
|
||||
#ifndef NSSBASET_H
|
||||
#include "nssbaset.h"
|
||||
#endif /* NSSBASET_H */
|
||||
|
||||
PR_BEGIN_EXTERN_C
|
||||
|
||||
/*
|
||||
* NSSArena
|
||||
*
|
||||
* The public methods relating to this type are:
|
||||
*
|
||||
* NSSArena_Create -- constructor
|
||||
* NSSArena_Destroy
|
||||
* NSS_ZAlloc
|
||||
* NSS_ZRealloc
|
||||
* NSS_ZFreeIf
|
||||
*/
|
||||
|
||||
/*
|
||||
* NSSArena_Create
|
||||
*
|
||||
* This routine creates a new memory arena. This routine may return
|
||||
* NULL upon error, in which case it will have created an error stack.
|
||||
*
|
||||
* The top-level error may be one of the following values:
|
||||
* NSS_ERROR_NO_MEMORY
|
||||
*
|
||||
* Return value:
|
||||
* NULL upon error
|
||||
* A pointer to an NSSArena upon success
|
||||
*/
|
||||
|
||||
NSS_EXTERN NSSArena *NSSArena_Create(void);
|
||||
|
||||
extern const NSSError NSS_ERROR_NO_MEMORY;
|
||||
|
||||
/*
|
||||
* NSSArena_Destroy
|
||||
*
|
||||
* This routine will destroy the specified arena, freeing all memory
|
||||
* allocated from it. This routine returns a PRStatus value; if
|
||||
* successful, it will return PR_SUCCESS. If unsuccessful, it will
|
||||
* create an error stack and return PR_FAILURE.
|
||||
*
|
||||
* The top-level error may be one of the following values:
|
||||
* NSS_ERROR_INVALID_ARENA
|
||||
*
|
||||
* Return value:
|
||||
* PR_SUCCESS upon success
|
||||
* PR_FAILURE upon failure
|
||||
*/
|
||||
|
||||
NSS_EXTERN PRStatus NSSArena_Destroy(NSSArena *arena);
|
||||
|
||||
extern const NSSError NSS_ERROR_INVALID_ARENA;
|
||||
|
||||
/*
|
||||
* The error stack
|
||||
*
|
||||
* The public methods relating to the error stack are:
|
||||
*
|
||||
* NSS_GetError
|
||||
* NSS_GetErrorStack
|
||||
*/
|
||||
|
||||
/*
|
||||
* NSS_GetError
|
||||
*
|
||||
* This routine returns the highest-level (most general) error set
|
||||
* by the most recent NSS library routine called by the same thread
|
||||
* calling this routine.
|
||||
*
|
||||
* This routine cannot fail. It may return NSS_ERROR_NO_ERROR, which
|
||||
* indicates that the previous NSS library call did not set an error.
|
||||
*
|
||||
* Return value:
|
||||
* 0 if no error has been set
|
||||
* A nonzero error number
|
||||
*/
|
||||
|
||||
NSS_EXTERN NSSError NSS_GetError(void);
|
||||
|
||||
extern const NSSError NSS_ERROR_NO_ERROR;
|
||||
|
||||
/*
|
||||
* NSS_GetErrorStack
|
||||
*
|
||||
* This routine returns a pointer to an array of NSSError values,
|
||||
* containingthe entire sequence or "stack" of errors set by the most
|
||||
* recent NSS library routine called by the same thread calling this
|
||||
* routine. NOTE: the caller DOES NOT OWN the memory pointed to by
|
||||
* the return value. The pointer will remain valid until the calling
|
||||
* thread calls another NSS routine. The lowest-level (most specific)
|
||||
* error is first in the array, and the highest-level is last. The
|
||||
* array is zero-terminated. This routine may return NULL upon error;
|
||||
* this indicates a low-memory situation.
|
||||
*
|
||||
* Return value:
|
||||
* NULL upon error, which is an implied NSS_ERROR_NO_MEMORY
|
||||
* A NON-caller-owned pointer to an array of NSSError values
|
||||
*/
|
||||
|
||||
NSS_EXTERN NSSError *NSS_GetErrorStack(void);
|
||||
|
||||
/*
|
||||
* NSS_ZNEW
|
||||
*
|
||||
* This preprocessor macro will allocate memory for a new object
|
||||
* of the specified type with nss_ZAlloc, and will cast the
|
||||
* return value appropriately. If the optional arena argument is
|
||||
* non-null, the memory will be obtained from that arena; otherwise,
|
||||
* the memory will be obtained from the heap. This routine may
|
||||
* return NULL upon error, in which case it will have set an error
|
||||
* upon the error stack.
|
||||
*
|
||||
* The error may be one of the following values:
|
||||
* NSS_ERROR_INVALID_ARENA
|
||||
* NSS_ERROR_NO_MEMORY
|
||||
*
|
||||
* Return value:
|
||||
* NULL upon error
|
||||
* A pointer to the new segment of zeroed memory
|
||||
*/
|
||||
|
||||
#define NSS_ZNEW(arenaOpt, type) ((type *)NSS_ZAlloc((arenaOpt), sizeof(type)))
|
||||
|
||||
/*
|
||||
* NSS_ZNEWARRAY
|
||||
*
|
||||
* This preprocessor macro will allocate memory for an array of
|
||||
* new objects, and will cast the return value appropriately.
|
||||
* If the optional arena argument is non-null, the memory will
|
||||
* be obtained from that arena; otherwise, the memory will be
|
||||
* obtained from the heap. This routine may return NULL upon
|
||||
* error, in which case it will have set an error upon the error
|
||||
* stack. The array size may be specified as zero.
|
||||
*
|
||||
* The error may be one of the following values:
|
||||
* NSS_ERROR_INVALID_ARENA
|
||||
* NSS_ERROR_NO_MEMORY
|
||||
*
|
||||
* Return value:
|
||||
* NULL upon error
|
||||
* A pointer to the new segment of zeroed memory
|
||||
*/
|
||||
|
||||
#define NSS_ZNEWARRAY(arenaOpt, type, quantity) \
|
||||
((type *)NSS_ZAlloc((arenaOpt), sizeof(type) * (quantity)))
|
||||
|
||||
/*
|
||||
* NSS_ZAlloc
|
||||
*
|
||||
* This routine allocates and zeroes a section of memory of the
|
||||
* size, and returns to the caller a pointer to that memory. If
|
||||
* the optional arena argument is non-null, the memory will be
|
||||
* obtained from that arena; otherwise, the memory will be obtained
|
||||
* from the heap. This routine may return NULL upon error, in
|
||||
* which case it will have set an error upon the error stack. The
|
||||
* value specified for size may be zero; in which case a valid
|
||||
* zero-length block of memory will be allocated. This block may
|
||||
* be expanded by calling NSS_ZRealloc.
|
||||
*
|
||||
* The error may be one of the following values:
|
||||
* NSS_ERROR_INVALID_ARENA
|
||||
* NSS_ERROR_NO_MEMORY
|
||||
* NSS_ERROR_ARENA_MARKED_BY_ANOTHER_THREAD
|
||||
*
|
||||
* Return value:
|
||||
* NULL upon error
|
||||
* A pointer to the new segment of zeroed memory
|
||||
*/
|
||||
|
||||
NSS_EXTERN void *NSS_ZAlloc(NSSArena *arenaOpt, PRUint32 size);
|
||||
|
||||
/*
|
||||
* NSS_ZRealloc
|
||||
*
|
||||
* This routine reallocates a block of memory obtained by calling
|
||||
* nss_ZAlloc or nss_ZRealloc. The portion of memory
|
||||
* between the new and old sizes -- which is either being newly
|
||||
* obtained or released -- is in either case zeroed. This routine
|
||||
* may return NULL upon failure, in which case it will have placed
|
||||
* an error on the error stack.
|
||||
*
|
||||
* The error may be one of the following values:
|
||||
* NSS_ERROR_INVALID_POINTER
|
||||
* NSS_ERROR_NO_MEMORY
|
||||
* NSS_ERROR_ARENA_MARKED_BY_ANOTHER_THREAD
|
||||
*
|
||||
* Return value:
|
||||
* NULL upon error
|
||||
* A pointer to the replacement segment of memory
|
||||
*/
|
||||
|
||||
NSS_EXTERN void *NSS_ZRealloc(void *pointer, PRUint32 newSize);
|
||||
|
||||
/*
|
||||
* NSS_ZFreeIf
|
||||
*
|
||||
* If the specified pointer is non-null, then the region of memory
|
||||
* to which it points -- which must have been allocated with
|
||||
* nss_ZAlloc -- will be zeroed and released. This routine
|
||||
* returns a PRStatus value; if successful, it will return PR_SUCCESS.
|
||||
* If unsuccessful, it will set an error on the error stack and return
|
||||
* PR_FAILURE.
|
||||
*
|
||||
* The error may be one of the following values:
|
||||
* NSS_ERROR_INVALID_POINTER
|
||||
*
|
||||
* Return value:
|
||||
* PR_SUCCESS
|
||||
* PR_FAILURE
|
||||
*/
|
||||
|
||||
NSS_EXTERN PRStatus NSS_ZFreeIf(void *pointer);
|
||||
|
||||
PR_END_EXTERN_C
|
||||
|
||||
#endif /* NSSBASE_H */
|
||||
118
security/nss/lib/base/nssbaset.h
Normal file
118
security/nss/lib/base/nssbaset.h
Normal file
|
|
@ -0,0 +1,118 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef NSSBASET_H
|
||||
#define NSSBASET_H
|
||||
|
||||
/*
|
||||
* nssbaset.h
|
||||
*
|
||||
* This file contains the most low-level, fundamental public types.
|
||||
*/
|
||||
|
||||
#include "nspr.h"
|
||||
#include "nssilock.h"
|
||||
|
||||
/*
|
||||
* NSS_EXTERN, NSS_IMPLEMENT, NSS_EXTERN_DATA, NSS_IMPLEMENT_DATA
|
||||
*
|
||||
* NSS has its own versions of these NSPR macros, in a form which
|
||||
* does not confuse ctags and other related utilities. NSPR
|
||||
* defines these macros to take the type as an argument, because
|
||||
* of certain OS requirements on platforms not supported by NSS.
|
||||
*/
|
||||
|
||||
#define DUMMY /* dummy */
|
||||
#define NSS_EXTERN extern
|
||||
#define NSS_EXTERN_DATA extern
|
||||
#define NSS_IMPLEMENT
|
||||
#define NSS_IMPLEMENT_DATA
|
||||
|
||||
PR_BEGIN_EXTERN_C
|
||||
|
||||
/*
|
||||
* NSSError
|
||||
*
|
||||
* Calls to NSS routines may result in one or more errors being placed
|
||||
* on the calling thread's "error stack." Every possible error that
|
||||
* may be returned from a function is declared where the function is
|
||||
* prototyped. All errors are of the following type.
|
||||
*/
|
||||
|
||||
typedef PRInt32 NSSError;
|
||||
|
||||
/*
|
||||
* NSSArena
|
||||
*
|
||||
* Arenas are logical sets of heap memory, from which memory may be
|
||||
* allocated. When an arena is destroyed, all memory allocated within
|
||||
* that arena is implicitly freed. These arenas are thread-safe:
|
||||
* an arena pointer may be used by multiple threads simultaneously.
|
||||
* However, as they are not backed by shared memory, they may only be
|
||||
* used within one process.
|
||||
*/
|
||||
|
||||
struct NSSArenaStr;
|
||||
typedef struct NSSArenaStr NSSArena;
|
||||
|
||||
/*
|
||||
* NSSItem
|
||||
*
|
||||
* This is the basic type used to refer to an unconstrained datum of
|
||||
* arbitrary size.
|
||||
*/
|
||||
|
||||
struct NSSItemStr {
|
||||
void *data;
|
||||
PRUint32 size;
|
||||
};
|
||||
typedef struct NSSItemStr NSSItem;
|
||||
|
||||
/*
|
||||
* NSSBER
|
||||
*
|
||||
* Data packed according to the Basic Encoding Rules of ASN.1.
|
||||
*/
|
||||
|
||||
typedef NSSItem NSSBER;
|
||||
|
||||
/*
|
||||
* NSSDER
|
||||
*
|
||||
* Data packed according to the Distinguished Encoding Rules of ASN.1;
|
||||
* this form is also known as the Canonical Encoding Rules form (CER).
|
||||
*/
|
||||
|
||||
typedef NSSBER NSSDER;
|
||||
|
||||
/*
|
||||
* NSSBitString
|
||||
*
|
||||
* Some ASN.1 types use "bit strings," which are passed around as
|
||||
* octet strings but whose length is counted in bits. We use this
|
||||
* typedef of NSSItem to point out the occasions when the length
|
||||
* is counted in bits, not octets.
|
||||
*/
|
||||
|
||||
typedef NSSItem NSSBitString;
|
||||
|
||||
/*
|
||||
* NSSUTF8
|
||||
*
|
||||
* Character strings encoded in UTF-8, as defined by RFC 2279.
|
||||
*/
|
||||
|
||||
typedef char NSSUTF8;
|
||||
|
||||
/*
|
||||
* NSSASCII7
|
||||
*
|
||||
* Character strings guaranteed to be 7-bit ASCII.
|
||||
*/
|
||||
|
||||
typedef char NSSASCII7;
|
||||
|
||||
PR_END_EXTERN_C
|
||||
|
||||
#endif /* NSSBASET_H */
|
||||
378
security/nss/lib/base/tracker.c
Normal file
378
security/nss/lib/base/tracker.c
Normal file
|
|
@ -0,0 +1,378 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/*
|
||||
* tracker.c
|
||||
*
|
||||
* This file contains the code used by the pointer-tracking calls used
|
||||
* in the debug builds to catch bad pointers. The entire contents are
|
||||
* only available in debug builds (both internal and external builds).
|
||||
*/
|
||||
|
||||
#ifndef BASE_H
|
||||
#include "base.h"
|
||||
#endif /* BASE_H */
|
||||
|
||||
#ifdef DEBUG
|
||||
/*
|
||||
* identity_hash
|
||||
*
|
||||
* This static callback is a PLHashFunction as defined in plhash.h
|
||||
* It merely returns the value of the object pointer as its hash.
|
||||
* There are no possible errors.
|
||||
*/
|
||||
|
||||
static PLHashNumber PR_CALLBACK
|
||||
identity_hash(const void *key)
|
||||
{
|
||||
return (PLHashNumber)((char *)key - (char *)NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* trackerOnceFunc
|
||||
*
|
||||
* This function is called once, using the nssCallOnce function above.
|
||||
* It creates a new pointer tracker object; initialising its hash
|
||||
* table and protective lock.
|
||||
*/
|
||||
|
||||
static PRStatus
|
||||
trackerOnceFunc(void *arg)
|
||||
{
|
||||
nssPointerTracker *tracker = (nssPointerTracker *)arg;
|
||||
|
||||
tracker->lock = PZ_NewLock(nssILockOther);
|
||||
if ((PZLock *)NULL == tracker->lock) {
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
tracker->table =
|
||||
PL_NewHashTable(0, identity_hash, PL_CompareValues, PL_CompareValues,
|
||||
(PLHashAllocOps *)NULL, (void *)NULL);
|
||||
if ((PLHashTable *)NULL == tracker->table) {
|
||||
PZ_DestroyLock(tracker->lock);
|
||||
tracker->lock = (PZLock *)NULL;
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
return PR_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* nssPointerTracker_initialize
|
||||
*
|
||||
* This method is only present in debug builds.
|
||||
*
|
||||
* This routine initializes an nssPointerTracker object. Note that
|
||||
* the object must have been declared *static* to guarantee that it
|
||||
* is in a zeroed state initially. This routine is idempotent, and
|
||||
* may even be safely called by multiple threads simultaneously with
|
||||
* the same argument. This routine returns a PRStatus value; if
|
||||
* successful, it will return PR_SUCCESS. On failure it will set an
|
||||
* error on the error stack and return PR_FAILURE.
|
||||
*
|
||||
* The error may be one of the following values:
|
||||
* NSS_ERROR_NO_MEMORY
|
||||
*
|
||||
* Return value:
|
||||
* PR_SUCCESS
|
||||
* PR_FAILURE
|
||||
*/
|
||||
|
||||
NSS_IMPLEMENT PRStatus
|
||||
nssPointerTracker_initialize(nssPointerTracker *tracker)
|
||||
{
|
||||
PRStatus rv = PR_CallOnceWithArg(&tracker->once, trackerOnceFunc, tracker);
|
||||
if (PR_SUCCESS != rv) {
|
||||
nss_SetError(NSS_ERROR_NO_MEMORY);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
#ifdef DONT_DESTROY_EMPTY_TABLES
|
||||
/* See same #ifdef below */
|
||||
/*
|
||||
* count_entries
|
||||
*
|
||||
* This static routine is a PLHashEnumerator, as defined in plhash.h.
|
||||
* It merely causes the enumeration function to count the number of
|
||||
* entries.
|
||||
*/
|
||||
|
||||
static PRIntn PR_CALLBACK
|
||||
count_entries(PLHashEntry *he, PRIntn index, void *arg)
|
||||
{
|
||||
return HT_ENUMERATE_NEXT;
|
||||
}
|
||||
#endif /* DONT_DESTROY_EMPTY_TABLES */
|
||||
|
||||
/*
|
||||
* zero_once
|
||||
*
|
||||
* This is a guaranteed zeroed once block. It's used to help clear
|
||||
* the tracker.
|
||||
*/
|
||||
|
||||
static const PRCallOnceType zero_once;
|
||||
|
||||
/*
|
||||
* nssPointerTracker_finalize
|
||||
*
|
||||
* This method is only present in debug builds.
|
||||
*
|
||||
* This routine returns the nssPointerTracker object to the pre-
|
||||
* initialized state, releasing all resources used by the object.
|
||||
* It will *NOT* destroy the objects being tracked by the pointer
|
||||
* (should any remain), and therefore cannot be used to "sweep up"
|
||||
* remaining objects. This routine returns a PRStatus value; if
|
||||
* successful, it will return PR_SUCCES. On failure it will set an
|
||||
* error on the error stack and return PR_FAILURE. If any objects
|
||||
* remain in the tracker when it is finalized, that will be treated
|
||||
* as an error.
|
||||
*
|
||||
* The error may be one of the following values:
|
||||
* NSS_ERROR_INVALID_POINTER
|
||||
* NSS_ERROR_TRACKER_NOT_INITIALIZED
|
||||
* NSS_ERROR_TRACKER_NOT_EMPTY
|
||||
*
|
||||
* Return value:
|
||||
* PR_SUCCESS
|
||||
* PR_FAILURE
|
||||
*/
|
||||
|
||||
NSS_IMPLEMENT PRStatus
|
||||
nssPointerTracker_finalize(nssPointerTracker *tracker)
|
||||
{
|
||||
PZLock *lock;
|
||||
|
||||
if ((nssPointerTracker *)NULL == tracker) {
|
||||
nss_SetError(NSS_ERROR_INVALID_POINTER);
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
if ((PZLock *)NULL == tracker->lock) {
|
||||
nss_SetError(NSS_ERROR_TRACKER_NOT_INITIALIZED);
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
lock = tracker->lock;
|
||||
PZ_Lock(lock);
|
||||
|
||||
if ((PLHashTable *)NULL == tracker->table) {
|
||||
PZ_Unlock(lock);
|
||||
nss_SetError(NSS_ERROR_TRACKER_NOT_INITIALIZED);
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
#ifdef DONT_DESTROY_EMPTY_TABLES
|
||||
/*
|
||||
* I changed my mind; I think we don't want this after all.
|
||||
* Comments?
|
||||
*/
|
||||
count = PL_HashTableEnumerateEntries(tracker->table, count_entries,
|
||||
(void *)NULL);
|
||||
|
||||
if (0 != count) {
|
||||
PZ_Unlock(lock);
|
||||
nss_SetError(NSS_ERROR_TRACKER_NOT_EMPTY);
|
||||
return PR_FAILURE;
|
||||
}
|
||||
#endif /* DONT_DESTROY_EMPTY_TABLES */
|
||||
|
||||
PL_HashTableDestroy(tracker->table);
|
||||
/* memset(tracker, 0, sizeof(nssPointerTracker)); */
|
||||
tracker->once = zero_once;
|
||||
tracker->lock = (PZLock *)NULL;
|
||||
tracker->table = (PLHashTable *)NULL;
|
||||
|
||||
PZ_Unlock(lock);
|
||||
PZ_DestroyLock(lock);
|
||||
|
||||
return PR_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* nssPointerTracker_add
|
||||
*
|
||||
* This method is only present in debug builds.
|
||||
*
|
||||
* This routine adds the specified pointer to the nssPointerTracker
|
||||
* object. It should be called in constructor objects to register
|
||||
* new valid objects. The nssPointerTracker is threadsafe, but this
|
||||
* call is not idempotent. This routine returns a PRStatus value;
|
||||
* if successful it will return PR_SUCCESS. On failure it will set
|
||||
* an error on the error stack and return PR_FAILURE.
|
||||
*
|
||||
* The error may be one of the following values:
|
||||
* NSS_ERROR_INVALID_POINTER
|
||||
* NSS_ERROR_NO_MEMORY
|
||||
* NSS_ERROR_TRACKER_NOT_INITIALIZED
|
||||
* NSS_ERROR_DUPLICATE_POINTER
|
||||
*
|
||||
* Return value:
|
||||
* PR_SUCCESS
|
||||
* PR_FAILURE
|
||||
*/
|
||||
|
||||
NSS_IMPLEMENT PRStatus
|
||||
nssPointerTracker_add(nssPointerTracker *tracker, const void *pointer)
|
||||
{
|
||||
void *check;
|
||||
PLHashEntry *entry;
|
||||
|
||||
if ((nssPointerTracker *)NULL == tracker) {
|
||||
nss_SetError(NSS_ERROR_INVALID_POINTER);
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
if ((PZLock *)NULL == tracker->lock) {
|
||||
nss_SetError(NSS_ERROR_TRACKER_NOT_INITIALIZED);
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
PZ_Lock(tracker->lock);
|
||||
|
||||
if ((PLHashTable *)NULL == tracker->table) {
|
||||
PZ_Unlock(tracker->lock);
|
||||
nss_SetError(NSS_ERROR_TRACKER_NOT_INITIALIZED);
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
check = PL_HashTableLookup(tracker->table, pointer);
|
||||
if ((void *)NULL != check) {
|
||||
PZ_Unlock(tracker->lock);
|
||||
nss_SetError(NSS_ERROR_DUPLICATE_POINTER);
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
entry = PL_HashTableAdd(tracker->table, pointer, (void *)pointer);
|
||||
|
||||
PZ_Unlock(tracker->lock);
|
||||
|
||||
if ((PLHashEntry *)NULL == entry) {
|
||||
nss_SetError(NSS_ERROR_NO_MEMORY);
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
return PR_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* nssPointerTracker_remove
|
||||
*
|
||||
* This method is only present in debug builds.
|
||||
*
|
||||
* This routine removes the specified pointer from the
|
||||
* nssPointerTracker object. It does not call any destructor for the
|
||||
* object; rather, this should be called from the object's destructor.
|
||||
* The nssPointerTracker is threadsafe, but this call is not
|
||||
* idempotent. This routine returns a PRStatus value; if successful
|
||||
* it will return PR_SUCCESS. On failure it will set an error on the
|
||||
* error stack and return PR_FAILURE.
|
||||
*
|
||||
* The error may be one of the following values:
|
||||
* NSS_ERROR_INVALID_POINTER
|
||||
* NSS_ERROR_TRACKER_NOT_INITIALIZED
|
||||
* NSS_ERROR_POINTER_NOT_REGISTERED
|
||||
*
|
||||
* Return value:
|
||||
* PR_SUCCESS
|
||||
* PR_FAILURE
|
||||
*/
|
||||
|
||||
NSS_IMPLEMENT PRStatus
|
||||
nssPointerTracker_remove(nssPointerTracker *tracker, const void *pointer)
|
||||
{
|
||||
PRBool registered;
|
||||
|
||||
if ((nssPointerTracker *)NULL == tracker) {
|
||||
nss_SetError(NSS_ERROR_INVALID_POINTER);
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
if ((PZLock *)NULL == tracker->lock) {
|
||||
nss_SetError(NSS_ERROR_TRACKER_NOT_INITIALIZED);
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
PZ_Lock(tracker->lock);
|
||||
|
||||
if ((PLHashTable *)NULL == tracker->table) {
|
||||
PZ_Unlock(tracker->lock);
|
||||
nss_SetError(NSS_ERROR_TRACKER_NOT_INITIALIZED);
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
registered = PL_HashTableRemove(tracker->table, pointer);
|
||||
PZ_Unlock(tracker->lock);
|
||||
|
||||
if (!registered) {
|
||||
nss_SetError(NSS_ERROR_POINTER_NOT_REGISTERED);
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
return PR_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* nssPointerTracker_verify
|
||||
*
|
||||
* This method is only present in debug builds.
|
||||
*
|
||||
* This routine verifies that the specified pointer has been registered
|
||||
* with the nssPointerTracker object. The nssPointerTracker object is
|
||||
* threadsafe, and this call may be safely called from multiple threads
|
||||
* simultaneously with the same arguments. This routine returns a
|
||||
* PRStatus value; if the pointer is registered this will return
|
||||
* PR_SUCCESS. Otherwise it will set an error on the error stack and
|
||||
* return PR_FAILURE. Although the error is suitable for leaving on
|
||||
* the stack, callers may wish to augment the information available by
|
||||
* placing a more type-specific error on the stack.
|
||||
*
|
||||
* The error may be one of the following values:
|
||||
* NSS_ERROR_INVALID_POINTER
|
||||
* NSS_ERROR_TRACKER_NOT_INITIALIZED
|
||||
* NSS_ERROR_POINTER_NOT_REGISTERED
|
||||
*
|
||||
* Return value:
|
||||
* PR_SUCCESS
|
||||
* PR_FAILRUE
|
||||
*/
|
||||
|
||||
NSS_IMPLEMENT PRStatus
|
||||
nssPointerTracker_verify(nssPointerTracker *tracker, const void *pointer)
|
||||
{
|
||||
void *check;
|
||||
|
||||
if ((nssPointerTracker *)NULL == tracker) {
|
||||
nss_SetError(NSS_ERROR_INVALID_POINTER);
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
if ((PZLock *)NULL == tracker->lock) {
|
||||
nss_SetError(NSS_ERROR_TRACKER_NOT_INITIALIZED);
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
PZ_Lock(tracker->lock);
|
||||
|
||||
if ((PLHashTable *)NULL == tracker->table) {
|
||||
PZ_Unlock(tracker->lock);
|
||||
nss_SetError(NSS_ERROR_TRACKER_NOT_INITIALIZED);
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
check = PL_HashTableLookup(tracker->table, pointer);
|
||||
PZ_Unlock(tracker->lock);
|
||||
|
||||
if ((void *)NULL == check) {
|
||||
nss_SetError(NSS_ERROR_POINTER_NOT_REGISTERED);
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
return PR_SUCCESS;
|
||||
}
|
||||
|
||||
#endif /* DEBUG */
|
||||
679
security/nss/lib/base/utf8.c
Normal file
679
security/nss/lib/base/utf8.c
Normal file
|
|
@ -0,0 +1,679 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/*
|
||||
* utf8.c
|
||||
*
|
||||
* This file contains some additional utility routines required for
|
||||
* handling UTF8 strings.
|
||||
*/
|
||||
|
||||
#ifndef BASE_H
|
||||
#include "base.h"
|
||||
#endif /* BASE_H */
|
||||
|
||||
#include "plstr.h"
|
||||
|
||||
/*
|
||||
* NOTES:
|
||||
*
|
||||
* There's an "is hex string" function in pki1/atav.c. If we need
|
||||
* it in more places, pull that one out.
|
||||
*/
|
||||
|
||||
/*
|
||||
* nssUTF8_CaseIgnoreMatch
|
||||
*
|
||||
* Returns true if the two UTF8-encoded strings pointed to by the
|
||||
* two specified NSSUTF8 pointers differ only in typcase.
|
||||
*
|
||||
* The error may be one of the following values:
|
||||
* NSS_ERROR_INVALID_POINTER
|
||||
*
|
||||
* Return value:
|
||||
* PR_TRUE if the strings match, ignoring case
|
||||
* PR_FALSE if they don't
|
||||
* PR_FALSE upon error
|
||||
*/
|
||||
|
||||
NSS_IMPLEMENT PRBool
|
||||
nssUTF8_CaseIgnoreMatch(const NSSUTF8 *a, const NSSUTF8 *b, PRStatus *statusOpt)
|
||||
{
|
||||
#ifdef NSSDEBUG
|
||||
if (((const NSSUTF8 *)NULL == a) || ((const NSSUTF8 *)NULL == b)) {
|
||||
nss_SetError(NSS_ERROR_INVALID_POINTER);
|
||||
if ((PRStatus *)NULL != statusOpt) {
|
||||
*statusOpt = PR_FAILURE;
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
#endif /* NSSDEBUG */
|
||||
|
||||
if ((PRStatus *)NULL != statusOpt) {
|
||||
*statusOpt = PR_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX fgmr
|
||||
*
|
||||
* This is, like, so wrong!
|
||||
*/
|
||||
if (0 == PL_strcasecmp((const char *)a, (const char *)b)) {
|
||||
return PR_TRUE;
|
||||
} else {
|
||||
return PR_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* nssUTF8_PrintableMatch
|
||||
*
|
||||
* Returns true if the two Printable strings pointed to by the
|
||||
* two specified NSSUTF8 pointers match when compared with the
|
||||
* rules for Printable String (leading and trailing spaces are
|
||||
* disregarded, extents of whitespace match irregardless of length,
|
||||
* and case is not significant), then PR_TRUE will be returned.
|
||||
* Otherwise, PR_FALSE will be returned. Upon failure, PR_FALSE
|
||||
* will be returned. If the optional statusOpt argument is not
|
||||
* NULL, then PR_SUCCESS or PR_FAILURE will be stored in that
|
||||
* location.
|
||||
*
|
||||
* The error may be one of the following values:
|
||||
* NSS_ERROR_INVALID_POINTER
|
||||
*
|
||||
* Return value:
|
||||
* PR_TRUE if the strings match, ignoring case
|
||||
* PR_FALSE if they don't
|
||||
* PR_FALSE upon error
|
||||
*/
|
||||
|
||||
NSS_IMPLEMENT PRBool
|
||||
nssUTF8_PrintableMatch(const NSSUTF8 *a, const NSSUTF8 *b, PRStatus *statusOpt)
|
||||
{
|
||||
PRUint8 *c;
|
||||
PRUint8 *d;
|
||||
|
||||
#ifdef NSSDEBUG
|
||||
if (((const NSSUTF8 *)NULL == a) || ((const NSSUTF8 *)NULL == b)) {
|
||||
nss_SetError(NSS_ERROR_INVALID_POINTER);
|
||||
if ((PRStatus *)NULL != statusOpt) {
|
||||
*statusOpt = PR_FAILURE;
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
#endif /* NSSDEBUG */
|
||||
|
||||
if ((PRStatus *)NULL != statusOpt) {
|
||||
*statusOpt = PR_SUCCESS;
|
||||
}
|
||||
|
||||
c = (PRUint8 *)a;
|
||||
d = (PRUint8 *)b;
|
||||
|
||||
while (' ' == *c) {
|
||||
c++;
|
||||
}
|
||||
|
||||
while (' ' == *d) {
|
||||
d++;
|
||||
}
|
||||
|
||||
while (('\0' != *c) && ('\0' != *d)) {
|
||||
PRUint8 e, f;
|
||||
|
||||
e = *c;
|
||||
f = *d;
|
||||
|
||||
if (('a' <= e) && (e <= 'z')) {
|
||||
e -= ('a' - 'A');
|
||||
}
|
||||
|
||||
if (('a' <= f) && (f <= 'z')) {
|
||||
f -= ('a' - 'A');
|
||||
}
|
||||
|
||||
if (e != f) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
c++;
|
||||
d++;
|
||||
|
||||
if (' ' == *c) {
|
||||
while (' ' == *c) {
|
||||
c++;
|
||||
}
|
||||
c--;
|
||||
}
|
||||
|
||||
if (' ' == *d) {
|
||||
while (' ' == *d) {
|
||||
d++;
|
||||
}
|
||||
d--;
|
||||
}
|
||||
}
|
||||
|
||||
while (' ' == *c) {
|
||||
c++;
|
||||
}
|
||||
|
||||
while (' ' == *d) {
|
||||
d++;
|
||||
}
|
||||
|
||||
if (*c == *d) {
|
||||
/* And both '\0', btw */
|
||||
return PR_TRUE;
|
||||
} else {
|
||||
return PR_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* nssUTF8_Duplicate
|
||||
*
|
||||
* This routine duplicates the UTF8-encoded string pointed to by the
|
||||
* specified NSSUTF8 pointer. If the optional arenaOpt argument is
|
||||
* not null, the memory required will be obtained from that arena;
|
||||
* otherwise, the memory required will be obtained from the heap.
|
||||
* A pointer to the new string will be returned. In case of error,
|
||||
* an error will be placed on the error stack and NULL will be
|
||||
* returned.
|
||||
*
|
||||
* The error may be one of the following values:
|
||||
* NSS_ERROR_INVALID_POINTER
|
||||
* NSS_ERROR_INVALID_ARENA
|
||||
* NSS_ERROR_NO_MEMORY
|
||||
*/
|
||||
|
||||
NSS_IMPLEMENT NSSUTF8 *
|
||||
nssUTF8_Duplicate(const NSSUTF8 *s, NSSArena *arenaOpt)
|
||||
{
|
||||
NSSUTF8 *rv;
|
||||
PRUint32 len;
|
||||
|
||||
#ifdef NSSDEBUG
|
||||
if ((const NSSUTF8 *)NULL == s) {
|
||||
nss_SetError(NSS_ERROR_INVALID_POINTER);
|
||||
return (NSSUTF8 *)NULL;
|
||||
}
|
||||
|
||||
if ((NSSArena *)NULL != arenaOpt) {
|
||||
if (PR_SUCCESS != nssArena_verifyPointer(arenaOpt)) {
|
||||
return (NSSUTF8 *)NULL;
|
||||
}
|
||||
}
|
||||
#endif /* NSSDEBUG */
|
||||
|
||||
len = PL_strlen((const char *)s);
|
||||
#ifdef PEDANTIC
|
||||
if ('\0' != ((const char *)s)[len]) {
|
||||
/* must have wrapped, e.g., too big for PRUint32 */
|
||||
nss_SetError(NSS_ERROR_NO_MEMORY);
|
||||
return (NSSUTF8 *)NULL;
|
||||
}
|
||||
#endif /* PEDANTIC */
|
||||
len++; /* zero termination */
|
||||
|
||||
rv = nss_ZAlloc(arenaOpt, len);
|
||||
if ((void *)NULL == rv) {
|
||||
return (NSSUTF8 *)NULL;
|
||||
}
|
||||
|
||||
(void)nsslibc_memcpy(rv, s, len);
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*
|
||||
* nssUTF8_Size
|
||||
*
|
||||
* This routine returns the length in bytes (including the terminating
|
||||
* null) of the UTF8-encoded string pointed to by the specified
|
||||
* NSSUTF8 pointer. Zero is returned on error.
|
||||
*
|
||||
* The error may be one of the following values:
|
||||
* NSS_ERROR_INVALID_POINTER
|
||||
* NSS_ERROR_VALUE_TOO_LARGE
|
||||
*
|
||||
* Return value:
|
||||
* 0 on error
|
||||
* nonzero length of the string.
|
||||
*/
|
||||
|
||||
NSS_IMPLEMENT PRUint32
|
||||
nssUTF8_Size(const NSSUTF8 *s, PRStatus *statusOpt)
|
||||
{
|
||||
PRUint32 sv;
|
||||
|
||||
#ifdef NSSDEBUG
|
||||
if ((const NSSUTF8 *)NULL == s) {
|
||||
nss_SetError(NSS_ERROR_INVALID_POINTER);
|
||||
if ((PRStatus *)NULL != statusOpt) {
|
||||
*statusOpt = PR_FAILURE;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif /* NSSDEBUG */
|
||||
|
||||
sv = PL_strlen((const char *)s) + 1;
|
||||
#ifdef PEDANTIC
|
||||
if ('\0' != ((const char *)s)[sv - 1]) {
|
||||
/* wrapped */
|
||||
nss_SetError(NSS_ERROR_VALUE_TOO_LARGE);
|
||||
if ((PRStatus *)NULL != statusOpt) {
|
||||
*statusOpt = PR_FAILURE;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif /* PEDANTIC */
|
||||
|
||||
if ((PRStatus *)NULL != statusOpt) {
|
||||
*statusOpt = PR_SUCCESS;
|
||||
}
|
||||
|
||||
return sv;
|
||||
}
|
||||
|
||||
/*
|
||||
* nssUTF8_Length
|
||||
*
|
||||
* This routine returns the length in characters (not including the
|
||||
* terminating null) of the UTF8-encoded string pointed to by the
|
||||
* specified NSSUTF8 pointer.
|
||||
*
|
||||
* The error may be one of the following values:
|
||||
* NSS_ERROR_INVALID_POINTER
|
||||
* NSS_ERROR_VALUE_TOO_LARGE
|
||||
* NSS_ERROR_INVALID_STRING
|
||||
*
|
||||
* Return value:
|
||||
* length of the string (which may be zero)
|
||||
* 0 on error
|
||||
*/
|
||||
|
||||
NSS_IMPLEMENT PRUint32
|
||||
nssUTF8_Length(const NSSUTF8 *s, PRStatus *statusOpt)
|
||||
{
|
||||
PRUint32 l = 0;
|
||||
const PRUint8 *c = (const PRUint8 *)s;
|
||||
|
||||
#ifdef NSSDEBUG
|
||||
if ((const NSSUTF8 *)NULL == s) {
|
||||
nss_SetError(NSS_ERROR_INVALID_POINTER);
|
||||
goto loser;
|
||||
}
|
||||
#endif /* NSSDEBUG */
|
||||
|
||||
/*
|
||||
* From RFC 2044:
|
||||
*
|
||||
* UCS-4 range (hex.) UTF-8 octet sequence (binary)
|
||||
* 0000 0000-0000 007F 0xxxxxxx
|
||||
* 0000 0080-0000 07FF 110xxxxx 10xxxxxx
|
||||
* 0000 0800-0000 FFFF 1110xxxx 10xxxxxx 10xxxxxx
|
||||
* 0001 0000-001F FFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
|
||||
* 0020 0000-03FF FFFF 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
|
||||
* 0400 0000-7FFF FFFF 1111110x 10xxxxxx ... 10xxxxxx
|
||||
*/
|
||||
|
||||
while (0 != *c) {
|
||||
PRUint32 incr;
|
||||
if ((*c & 0x80) == 0) {
|
||||
incr = 1;
|
||||
} else if ((*c & 0xE0) == 0xC0) {
|
||||
incr = 2;
|
||||
} else if ((*c & 0xF0) == 0xE0) {
|
||||
incr = 3;
|
||||
} else if ((*c & 0xF8) == 0xF0) {
|
||||
incr = 4;
|
||||
} else if ((*c & 0xFC) == 0xF8) {
|
||||
incr = 5;
|
||||
} else if ((*c & 0xFE) == 0xFC) {
|
||||
incr = 6;
|
||||
} else {
|
||||
nss_SetError(NSS_ERROR_INVALID_STRING);
|
||||
goto loser;
|
||||
}
|
||||
|
||||
l += incr;
|
||||
|
||||
#ifdef PEDANTIC
|
||||
if (l < incr) {
|
||||
/* Wrapped-- too big */
|
||||
nss_SetError(NSS_ERROR_VALUE_TOO_LARGE);
|
||||
goto loser;
|
||||
}
|
||||
|
||||
{
|
||||
PRUint8 *d;
|
||||
for (d = &c[1]; d < &c[incr]; d++) {
|
||||
if ((*d & 0xC0) != 0xF0) {
|
||||
nss_SetError(NSS_ERROR_INVALID_STRING);
|
||||
goto loser;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* PEDANTIC */
|
||||
|
||||
c += incr;
|
||||
}
|
||||
|
||||
if ((PRStatus *)NULL != statusOpt) {
|
||||
*statusOpt = PR_SUCCESS;
|
||||
}
|
||||
|
||||
return l;
|
||||
|
||||
loser:
|
||||
if ((PRStatus *)NULL != statusOpt) {
|
||||
*statusOpt = PR_FAILURE;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* nssUTF8_Create
|
||||
*
|
||||
* This routine creates a UTF8 string from a string in some other
|
||||
* format. Some types of string may include embedded null characters,
|
||||
* so for them the length parameter must be used. For string types
|
||||
* that are null-terminated, the length parameter is optional; if it
|
||||
* is zero, it will be ignored. If the optional arena argument is
|
||||
* non-null, the memory used for the new string will be obtained from
|
||||
* that arena, otherwise it will be obtained from the heap. This
|
||||
* routine may return NULL upon error, in which case it will have
|
||||
* placed an error on the error stack.
|
||||
*
|
||||
* The error may be one of the following:
|
||||
* NSS_ERROR_INVALID_POINTER
|
||||
* NSS_ERROR_NO_MEMORY
|
||||
* NSS_ERROR_UNSUPPORTED_TYPE
|
||||
*
|
||||
* Return value:
|
||||
* NULL upon error
|
||||
* A non-null pointer to a new UTF8 string otherwise
|
||||
*/
|
||||
|
||||
extern const NSSError NSS_ERROR_INTERNAL_ERROR; /* XXX fgmr */
|
||||
|
||||
NSS_IMPLEMENT NSSUTF8 *
|
||||
nssUTF8_Create(NSSArena *arenaOpt, nssStringType type, const void *inputString,
|
||||
PRUint32 size /* in bytes, not characters */
|
||||
)
|
||||
{
|
||||
NSSUTF8 *rv = NULL;
|
||||
|
||||
#ifdef NSSDEBUG
|
||||
if ((NSSArena *)NULL != arenaOpt) {
|
||||
if (PR_SUCCESS != nssArena_verifyPointer(arenaOpt)) {
|
||||
return (NSSUTF8 *)NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if ((const void *)NULL == inputString) {
|
||||
nss_SetError(NSS_ERROR_INVALID_POINTER);
|
||||
return (NSSUTF8 *)NULL;
|
||||
}
|
||||
#endif /* NSSDEBUG */
|
||||
|
||||
switch (type) {
|
||||
case nssStringType_DirectoryString:
|
||||
/* This is a composite type requiring BER */
|
||||
nss_SetError(NSS_ERROR_UNSUPPORTED_TYPE);
|
||||
break;
|
||||
case nssStringType_TeletexString:
|
||||
/*
|
||||
* draft-ietf-pkix-ipki-part1-11 says in part:
|
||||
*
|
||||
* In addition, many legacy implementations support names encoded
|
||||
* in the ISO 8859-1 character set (Latin1String) but tag them as
|
||||
* TeletexString. The Latin1String includes characters used in
|
||||
* Western European countries which are not part of the
|
||||
* TeletexString charcter set. Implementations that process
|
||||
* TeletexString SHOULD be prepared to handle the entire ISO
|
||||
* 8859-1 character set.[ISO 8859-1].
|
||||
*/
|
||||
nss_SetError(NSS_ERROR_INTERNAL_ERROR); /* unimplemented */
|
||||
break;
|
||||
case nssStringType_PrintableString:
|
||||
/*
|
||||
* PrintableString consists of A-Za-z0-9 ,()+,-./:=?
|
||||
* This is a subset of ASCII, which is a subset of UTF8.
|
||||
* So we can just duplicate the string over.
|
||||
*/
|
||||
|
||||
if (0 == size) {
|
||||
rv = nssUTF8_Duplicate((const NSSUTF8 *)inputString, arenaOpt);
|
||||
} else {
|
||||
rv = nss_ZAlloc(arenaOpt, size + 1);
|
||||
if ((NSSUTF8 *)NULL == rv) {
|
||||
return (NSSUTF8 *)NULL;
|
||||
}
|
||||
|
||||
(void)nsslibc_memcpy(rv, inputString, size);
|
||||
}
|
||||
|
||||
break;
|
||||
case nssStringType_UniversalString:
|
||||
/* 4-byte unicode */
|
||||
nss_SetError(NSS_ERROR_INTERNAL_ERROR); /* unimplemented */
|
||||
break;
|
||||
case nssStringType_BMPString:
|
||||
/* Base Multilingual Plane of Unicode */
|
||||
nss_SetError(NSS_ERROR_INTERNAL_ERROR); /* unimplemented */
|
||||
break;
|
||||
case nssStringType_UTF8String:
|
||||
if (0 == size) {
|
||||
rv = nssUTF8_Duplicate((const NSSUTF8 *)inputString, arenaOpt);
|
||||
} else {
|
||||
rv = nss_ZAlloc(arenaOpt, size + 1);
|
||||
if ((NSSUTF8 *)NULL == rv) {
|
||||
return (NSSUTF8 *)NULL;
|
||||
}
|
||||
|
||||
(void)nsslibc_memcpy(rv, inputString, size);
|
||||
}
|
||||
|
||||
break;
|
||||
case nssStringType_PHGString:
|
||||
/*
|
||||
* PHGString is an IA5String (with case-insensitive comparisons).
|
||||
* IA5 is ~almost~ ascii; ascii has dollar-sign where IA5 has
|
||||
* currency symbol.
|
||||
*/
|
||||
nss_SetError(NSS_ERROR_INTERNAL_ERROR); /* unimplemented */
|
||||
break;
|
||||
case nssStringType_GeneralString:
|
||||
nss_SetError(NSS_ERROR_INTERNAL_ERROR); /* unimplemented */
|
||||
break;
|
||||
default:
|
||||
nss_SetError(NSS_ERROR_UNSUPPORTED_TYPE);
|
||||
break;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
NSS_IMPLEMENT NSSItem *
|
||||
nssUTF8_GetEncoding(NSSArena *arenaOpt, NSSItem *rvOpt, nssStringType type,
|
||||
NSSUTF8 *string)
|
||||
{
|
||||
NSSItem *rv = (NSSItem *)NULL;
|
||||
PRStatus status = PR_SUCCESS;
|
||||
|
||||
#ifdef NSSDEBUG
|
||||
if ((NSSArena *)NULL != arenaOpt) {
|
||||
if (PR_SUCCESS != nssArena_verifyPointer(arenaOpt)) {
|
||||
return (NSSItem *)NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if ((NSSUTF8 *)NULL == string) {
|
||||
nss_SetError(NSS_ERROR_INVALID_POINTER);
|
||||
return (NSSItem *)NULL;
|
||||
}
|
||||
#endif /* NSSDEBUG */
|
||||
|
||||
switch (type) {
|
||||
case nssStringType_DirectoryString:
|
||||
nss_SetError(NSS_ERROR_INTERNAL_ERROR); /* unimplemented */
|
||||
break;
|
||||
case nssStringType_TeletexString:
|
||||
nss_SetError(NSS_ERROR_INTERNAL_ERROR); /* unimplemented */
|
||||
break;
|
||||
case nssStringType_PrintableString:
|
||||
nss_SetError(NSS_ERROR_INTERNAL_ERROR); /* unimplemented */
|
||||
break;
|
||||
case nssStringType_UniversalString:
|
||||
nss_SetError(NSS_ERROR_INTERNAL_ERROR); /* unimplemented */
|
||||
break;
|
||||
case nssStringType_BMPString:
|
||||
nss_SetError(NSS_ERROR_INTERNAL_ERROR); /* unimplemented */
|
||||
break;
|
||||
case nssStringType_UTF8String: {
|
||||
NSSUTF8 *dup = nssUTF8_Duplicate(string, arenaOpt);
|
||||
if ((NSSUTF8 *)NULL == dup) {
|
||||
return (NSSItem *)NULL;
|
||||
}
|
||||
|
||||
if ((NSSItem *)NULL == rvOpt) {
|
||||
rv = nss_ZNEW(arenaOpt, NSSItem);
|
||||
if ((NSSItem *)NULL == rv) {
|
||||
(void)nss_ZFreeIf(dup);
|
||||
return (NSSItem *)NULL;
|
||||
}
|
||||
} else {
|
||||
rv = rvOpt;
|
||||
}
|
||||
|
||||
rv->data = dup;
|
||||
dup = (NSSUTF8 *)NULL;
|
||||
rv->size = nssUTF8_Size(rv->data, &status);
|
||||
if ((0 == rv->size) && (PR_SUCCESS != status)) {
|
||||
if ((NSSItem *)NULL == rvOpt) {
|
||||
(void)nss_ZFreeIf(rv);
|
||||
}
|
||||
return (NSSItem *)NULL;
|
||||
}
|
||||
} break;
|
||||
case nssStringType_PHGString:
|
||||
nss_SetError(NSS_ERROR_INTERNAL_ERROR); /* unimplemented */
|
||||
break;
|
||||
default:
|
||||
nss_SetError(NSS_ERROR_UNSUPPORTED_TYPE);
|
||||
break;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*
|
||||
* nssUTF8_CopyIntoFixedBuffer
|
||||
*
|
||||
* This will copy a UTF8 string into a fixed-length buffer, making
|
||||
* sure that the all characters are valid. Any remaining space will
|
||||
* be padded with the specified ASCII character, typically either
|
||||
* null or space.
|
||||
*
|
||||
* Blah, blah, blah.
|
||||
*/
|
||||
|
||||
NSS_IMPLEMENT PRStatus
|
||||
nssUTF8_CopyIntoFixedBuffer(NSSUTF8 *string, char *buffer, PRUint32 bufferSize,
|
||||
char pad)
|
||||
{
|
||||
PRUint32 stringSize = 0;
|
||||
|
||||
#ifdef NSSDEBUG
|
||||
if ((char *)NULL == buffer) {
|
||||
nss_SetError(NSS_ERROR_INVALID_POINTER);
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
if (0 == bufferSize) {
|
||||
nss_SetError(NSS_ERROR_INVALID_ARGUMENT);
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
if ((pad & 0x80) != 0x00) {
|
||||
nss_SetError(NSS_ERROR_INVALID_ARGUMENT);
|
||||
return PR_FALSE;
|
||||
}
|
||||
#endif /* NSSDEBUG */
|
||||
|
||||
if ((NSSUTF8 *)NULL == string) {
|
||||
string = (NSSUTF8 *)"";
|
||||
}
|
||||
|
||||
stringSize = nssUTF8_Size(string, (PRStatus *)NULL);
|
||||
stringSize--; /* don't count the trailing null */
|
||||
if (stringSize > bufferSize) {
|
||||
PRUint32 bs = bufferSize;
|
||||
(void)nsslibc_memcpy(buffer, string, bufferSize);
|
||||
|
||||
if ((((buffer[bs - 1] & 0x80) == 0x00)) ||
|
||||
((bs > 1) && ((buffer[bs - 2] & 0xE0) == 0xC0)) ||
|
||||
((bs > 2) && ((buffer[bs - 3] & 0xF0) == 0xE0)) ||
|
||||
((bs > 3) && ((buffer[bs - 4] & 0xF8) == 0xF0)) ||
|
||||
((bs > 4) && ((buffer[bs - 5] & 0xFC) == 0xF8)) ||
|
||||
((bs > 5) && ((buffer[bs - 6] & 0xFE) == 0xFC))) {
|
||||
/* It fit exactly */
|
||||
return PR_SUCCESS;
|
||||
}
|
||||
|
||||
/* Too long. We have to trim the last character */
|
||||
for (/*bs*/; bs != 0; bs--) {
|
||||
if ((buffer[bs - 1] & 0xC0) != 0x80) {
|
||||
buffer[bs - 1] = pad;
|
||||
break;
|
||||
} else {
|
||||
buffer[bs - 1] = pad;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
(void)nsslibc_memset(buffer, pad, bufferSize);
|
||||
(void)nsslibc_memcpy(buffer, string, stringSize);
|
||||
}
|
||||
|
||||
return PR_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* nssUTF8_Equal
|
||||
*
|
||||
*/
|
||||
|
||||
NSS_IMPLEMENT PRBool
|
||||
nssUTF8_Equal(const NSSUTF8 *a, const NSSUTF8 *b, PRStatus *statusOpt)
|
||||
{
|
||||
PRUint32 la, lb;
|
||||
|
||||
#ifdef NSSDEBUG
|
||||
if (((const NSSUTF8 *)NULL == a) || ((const NSSUTF8 *)NULL == b)) {
|
||||
nss_SetError(NSS_ERROR_INVALID_POINTER);
|
||||
if ((PRStatus *)NULL != statusOpt) {
|
||||
*statusOpt = PR_FAILURE;
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
#endif /* NSSDEBUG */
|
||||
|
||||
la = nssUTF8_Size(a, statusOpt);
|
||||
if (0 == la) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
lb = nssUTF8_Size(b, statusOpt);
|
||||
if (0 == lb) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
if (la != lb) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
return nsslibc_memequal(a, b, la, statusOpt);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue