Coverage Report

Created: 2025-07-01 06:25

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