Coverage Report

Created: 2024-11-21 07:03

/src/nss-nspr/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
0
{
27
0
    PRUint32 decimal_numbers = 0;
28
0
    PRUint32 result_bytes = 0;
29
0
    SECStatus rv;
30
0
    PRUint8 result[1024];
31
32
0
    static const PRUint32 max_decimal = (0xffffffff / 10);
33
0
    static const char OIDstring[] = { "OID." };
34
35
0
    if (!from || !to) {
36
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
37
0
        return SECFailure;
38
0
    }
39
0
    if (!len) {
40
0
        len = PL_strlen(from);
41
0
    }
42
0
    if (len >= 4 && !PL_strncasecmp(from, OIDstring, 4)) {
43
0
        from += 4; /* skip leading "OID." if present */
44
0
        len -= 4;
45
0
    }
46
0
    if (!len) {
47
0
    bad_data:
48
0
        PORT_SetError(SEC_ERROR_BAD_DATA);
49
0
        return SECFailure;
50
0
    }
51
0
    do {
52
0
        PRUint32 decimal = 0;
53
0
        while (len > 0 && isdigit((unsigned char)*from)) {
54
0
            PRUint32 addend = (*from++ - '0');
55
0
            --len;
56
0
            if (decimal > max_decimal) /* overflow */
57
0
                goto bad_data;
58
0
            decimal = (decimal * 10) + addend;
59
0
            if (decimal < addend) /* overflow */
60
0
                goto bad_data;
61
0
        }
62
0
        if (len != 0 && *from != '.') {
63
0
            goto bad_data;
64
0
        }
65
0
        if (decimal_numbers == 0) {
66
0
            if (decimal > 2)
67
0
                goto bad_data;
68
0
            result[0] = decimal * 40;
69
0
            result_bytes = 1;
70
0
        } else if (decimal_numbers == 1) {
71
0
            if (decimal > 40)
72
0
                goto bad_data;
73
0
            result[0] += decimal;
74
0
        } else {
75
            /* encode the decimal number,  */
76
0
            PRUint8 *rp;
77
0
            PRUint32 num_bytes = 0;
78
0
            PRUint32 tmp = decimal;
79
0
            while (tmp) {
80
0
                num_bytes++;
81
0
                tmp >>= 7;
82
0
            }
83
0
            if (!num_bytes)
84
0
                ++num_bytes; /* use one byte for a zero value */
85
0
            if (num_bytes + result_bytes > sizeof result)
86
0
                goto bad_data;
87
0
            tmp = num_bytes;
88
0
            rp = result + result_bytes - 1;
89
0
            rp[tmp] = (PRUint8)(decimal & 0x7f);
90
0
            decimal >>= 7;
91
0
            while (--tmp > 0) {
92
0
                rp[tmp] = (PRUint8)(decimal | 0x80);
93
0
                decimal >>= 7;
94
0
            }
95
0
            result_bytes += num_bytes;
96
0
        }
97
0
        ++decimal_numbers;
98
0
        if (len > 0) { /* skip trailing '.' */
99
0
            ++from;
100
0
            --len;
101
0
        }
102
0
    } while (len > 0);
103
    /* now result contains result_bytes of data */
104
0
    if (to->data && to->len >= result_bytes) {
105
0
        PORT_Memcpy(to->data, result, to->len = result_bytes);
106
0
        rv = SECSuccess;
107
0
    } else {
108
0
        SECItem result_item = { siBuffer, NULL, 0 };
109
0
        result_item.data = result;
110
0
        result_item.len = result_bytes;
111
0
        rv = SECITEM_CopyItem(pool, to, &result_item);
112
0
    }
113
0
    return rv;
114
0
}