Coverage Report

Created: 2025-07-04 06:19

/src/nss/lib/util/oidstring.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
#include <string.h>
6
#include "secitem.h"
7
#include "secport.h"
8
#include "secerr.h"
9
10
/* if to->data is not NULL, and to->len is large enough to hold the result,
11
 * then the resultant OID will be copyed into to->data, and to->len will be
12
 * changed to show the actual OID length.
13
 * Otherwise, memory for the OID will be allocated (from the caller's
14
 * PLArenaPool, if pool is non-NULL) and to->data will receive the address
15
 * of the allocated data, and to->len will receive the OID length.
16
 * The original value of to->data is not freed when a new buffer is allocated.
17
 *
18
 * The input string may begin with "OID." and this still be ignored.
19
 * The length of the input string is given in len.  If len == 0, then
20
 * len will be computed as strlen(from), meaning it must be NUL terminated.
21
 * It is an error if from == NULL, or if *from == '\0'.
22
 */
23
24
SECStatus
25
SEC_StringToOID(PLArenaPool *pool, SECItem *to, const char *from, PRUint32 len)
26
5.73k
{
27
5.73k
    PRUint32 decimal_numbers = 0;
28
5.73k
    PRUint32 result_bytes = 0;
29
5.73k
    SECStatus rv;
30
5.73k
    PRUint8 result[1024];
31
32
5.73k
    static const PRUint32 max_decimal = (0xffffffff / 10);
33
5.73k
    static const char OIDstring[] = { "OID." };
34
35
5.73k
    if (!from || !to) {
36
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
37
0
        return SECFailure;
38
0
    }
39
5.73k
    if (!len) {
40
0
        len = PL_strlen(from);
41
0
    }
42
5.73k
    if (len >= 4 && !PL_strncasecmp(from, OIDstring, 4)) {
43
258
        from += 4; /* skip leading "OID." if present */
44
258
        len -= 4;
45
258
    }
46
5.73k
    if (!len) {
47
190
    bad_data:
48
190
        PORT_SetError(SEC_ERROR_BAD_DATA);
49
190
        return SECFailure;
50
9
    }
51
12.0k
    do {
52
12.0k
        PRUint32 decimal = 0;
53
24.9k
        while (len > 0 && isdigit((unsigned char)*from)) {
54
12.8k
            PRUint32 addend = (*from++ - '0');
55
12.8k
            --len;
56
12.8k
            if (decimal > max_decimal) /* overflow */
57
5
                goto bad_data;
58
12.8k
            decimal = (decimal * 10) + addend;
59
12.8k
            if (decimal < addend) /* overflow */
60
1
                goto bad_data;
61
12.8k
        }
62
12.0k
        if (len != 0 && *from != '.') {
63
13
            goto bad_data;
64
13
        }
65
12.0k
        if (decimal_numbers == 0) {
66
5.70k
            if (decimal > 2)
67
109
                goto bad_data;
68
5.60k
            result[0] = decimal * 40;
69
5.60k
            result_bytes = 1;
70
6.36k
        } else if (decimal_numbers == 1) {
71
1.80k
            if (decimal > 40)
72
53
                goto bad_data;
73
1.75k
            result[0] += decimal;
74
4.56k
        } else {
75
            /* encode the decimal number,  */
76
4.56k
            PRUint8 *rp;
77
4.56k
            PRUint32 num_bytes = 0;
78
4.56k
            PRUint32 tmp = decimal;
79
8.18k
            while (tmp) {
80
3.62k
                num_bytes++;
81
3.62k
                tmp >>= 7;
82
3.62k
            }
83
4.56k
            if (!num_bytes)
84
2.40k
                ++num_bytes; /* use one byte for a zero value */
85
4.56k
            if (num_bytes + result_bytes > sizeof result)
86
0
                goto bad_data;
87
4.56k
            tmp = num_bytes;
88
4.56k
            rp = result + result_bytes - 1;
89
4.56k
            rp[tmp] = (PRUint8)(decimal & 0x7f);
90
4.56k
            decimal >>= 7;
91
6.02k
            while (--tmp > 0) {
92
1.46k
                rp[tmp] = (PRUint8)(decimal | 0x80);
93
1.46k
                decimal >>= 7;
94
1.46k
            }
95
4.56k
            result_bytes += num_bytes;
96
4.56k
        }
97
11.9k
        ++decimal_numbers;
98
11.9k
        if (len > 0) { /* skip trailing '.' */
99
6.93k
            ++from;
100
6.93k
            --len;
101
6.93k
        }
102
11.9k
    } while (len > 0);
103
    /* now result contains result_bytes of data */
104
5.54k
    if (to->data && to->len >= result_bytes) {
105
0
        PORT_Memcpy(to->data, result, to->len = result_bytes);
106
0
        rv = SECSuccess;
107
5.54k
    } else {
108
5.54k
        SECItem result_item = { siBuffer, NULL, 0 };
109
5.54k
        result_item.data = result;
110
5.54k
        result_item.len = result_bytes;
111
5.54k
        rv = SECITEM_CopyItem(pool, to, &result_item);
112
5.54k
    }
113
5.54k
    return rv;
114
5.72k
}