Coverage Report

Created: 2026-06-30 06:14

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/open5gs/lib/asn1c/common/UTF8String_rfill.c
Line
Count
Source
1
/*
2
 * Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
3
 * All rights reserved.
4
 * Redistribution and modifications are permitted subject to BSD license.
5
 */
6
#include <asn_internal.h>
7
#include <UTF8String.h>
8
9
/*
10
 * Biased function for randomizing UTF-8 sequences.
11
 */
12
static size_t
13
0
UTF8String__random_char(uint8_t *b, size_t size) {
14
0
    static const struct rnd_value {
15
0
        const char *value;
16
0
        size_t size;
17
0
    } values[] = {{"\0", 1},
18
0
                  {"\x01", 1},
19
0
                  {"\x7f", 1},
20
0
                  {"\xc2\xa2", 2},
21
0
                  {"\xe2\x82\xac", 3},
22
0
                  {"\xf0\x90\x8d\x88", 4},
23
0
                  {"\xf4\x8f\xbf\xbf", 4}};
24
25
0
    const struct rnd_value *v;
26
0
    size_t max_idx = 0;
27
28
0
    switch(size) {
29
0
    case 0:
30
0
        assert(size != 0);
31
0
        return 0;
32
0
    case 1:
33
0
        max_idx = 2;
34
0
        break;
35
0
    case 2:
36
0
        max_idx = 3;
37
0
        break;
38
0
    default:
39
0
    case 4:
40
0
        max_idx = sizeof(values) / sizeof(values[0]) - 1;
41
0
        break;
42
0
    }
43
44
0
    v = &values[asn_random_between(0, max_idx)];
45
0
    memcpy(b, v->value, v->size);
46
0
    return v->size;
47
0
}
48
49
static size_t
50
0
UTF8String__encode_codepoint(uint8_t *b, uint32_t code) {
51
0
    if(code <= 0x7f) {
52
0
        b[0] = code;
53
0
        return 1;
54
0
    } else if(code <= 0x7ff) {
55
0
        b[0] = 0xc0 | (code >> 6);
56
0
        b[1] = 0x80 | (code & 0x3f);
57
0
        return 2;
58
0
    } else if(code >= 0xd800 && code <= 0xdfff) {
59
        /* Surrogate code points are not valid Unicode scalar values. */
60
0
        return UTF8String__encode_codepoint(b, 0xfffd);
61
0
    } else if(code <= 0xffff) {
62
0
        b[0] = 0xe0 | (code >> 12);
63
0
        b[1] = 0x80 | ((code >> 6) & 0x3f);
64
0
        b[2] = 0x80 | (code & 0x3f);
65
0
        return 3;
66
0
    } else if(code <= 0x10ffff) {
67
0
        b[0] = 0xf0 | (code >> 18);
68
0
        b[1] = 0x80 | ((code >> 12) & 0x3f);
69
0
        b[2] = 0x80 | ((code >> 6) & 0x3f);
70
0
        b[3] = 0x80 | (code & 0x3f);
71
0
        return 4;
72
0
    } else {
73
0
        return UTF8String__encode_codepoint(b, 0x10ffff);
74
0
    }
75
0
}
76
77
static const asn_per_constraints_t *
78
UTF8String__per_constraints(const asn_TYPE_descriptor_t *td,
79
0
                            const asn_encoding_constraints_t *constraints) {
80
0
#if !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT)
81
0
    if(constraints && constraints->per_constraints)
82
0
        return constraints->per_constraints;
83
0
    if(td->encoding_constraints.per_constraints)
84
0
        return td->encoding_constraints.per_constraints;
85
0
#endif  /* !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT) */
86
0
    return 0;
87
0
}
88
89
asn_random_fill_result_t
90
UTF8String_random_fill(const asn_TYPE_descriptor_t *td, void **sptr,
91
                       const asn_encoding_constraints_t *constraints,
92
0
                       size_t max_length) {
93
0
    asn_random_fill_result_t result_ok = {ARFILL_OK, 1};
94
0
    asn_random_fill_result_t result_failed = {ARFILL_FAILED, 0};
95
0
    asn_random_fill_result_t result_skipped = {ARFILL_SKIPPED, 0};
96
0
    uint8_t *buf;
97
0
    uint8_t *bend;
98
0
    uint8_t *b;
99
0
    size_t rnd_len;
100
0
    size_t idx;
101
0
    UTF8String_t *st;
102
0
    const asn_per_constraints_t *pc;
103
0
    uint32_t value_lb = 0;
104
0
    uint32_t value_ub = 0x7f;
105
0
    int has_value_constraint = 0;
106
0
    int force_single_octets = 0;
107
108
0
    if(max_length == 0 && !*sptr) return result_skipped;
109
110
0
    pc = UTF8String__per_constraints(td, constraints);
111
0
    if(pc) {
112
0
        if((pc->value.flags & APC_CONSTRAINED)
113
0
                && pc->value.lower_bound >= 0
114
0
                && pc->value.lower_bound <= pc->value.upper_bound
115
0
                && pc->value.lower_bound <= 0x10ffff) {
116
0
            value_lb = (uint32_t)pc->value.lower_bound;
117
0
            value_ub = pc->value.upper_bound > 0x10ffff
118
0
                     ? 0x10ffff : (uint32_t)pc->value.upper_bound;
119
0
            has_value_constraint = 1;
120
0
        }
121
122
        /*
123
         * UTF8String is encoded through OCTET STRING helpers.  When a PER
124
         * SIZE constraint is present, the encoder checks the number of
125
         * octets.  Keep randomized values single-octet unless a permitted
126
         * alphabet constraint explicitly asks for another range.
127
         */
128
0
        if(pc->size.flags & APC_CONSTRAINED)
129
0
            force_single_octets = 1;
130
0
    }
131
132
    /*
133
     * When both a value constraint and a SIZE constraint are present,
134
     * restrict generation to code points in the value range that also
135
     * fit in a single octet (0..0x7f).  If the value range does not
136
     * intersect 0..0x7f at all, lift the single-octet restriction and
137
     * generate from the full value range.
138
     */
139
0
    if(has_value_constraint && force_single_octets) {
140
0
        if(value_lb > 0x7f) {
141
            /* Value range is entirely outside ASCII; allow multi-byte. */
142
0
            force_single_octets = 0;
143
0
        } else {
144
            /* Clamp value range to single-octet region. */
145
0
            if(value_ub > 0x7f)
146
0
                value_ub = 0x7f;
147
0
        }
148
0
    }
149
150
    /* Figure out how far we should go */
151
0
    rnd_len = OCTET_STRING_random_length_constrained(td, constraints,
152
0
                                                     max_length / 4);
153
154
0
    buf = CALLOC(4, rnd_len + 1);
155
0
    if(!buf) return result_failed;
156
157
0
    bend = &buf[4 * rnd_len];
158
159
0
    for(b = buf, idx = 0; idx < rnd_len; idx++) {
160
0
        if(has_value_constraint) {
161
0
            uint32_t code = (uint32_t)asn_random_between(value_lb, value_ub);
162
0
            b += UTF8String__encode_codepoint(b, code);
163
0
        } else if(force_single_octets) {
164
0
            b += UTF8String__random_char(b, 1);
165
0
        } else {
166
0
            b += UTF8String__random_char(b, (bend - b));
167
0
        }
168
0
    }
169
0
    *(uint8_t *)b = 0;
170
171
0
    if(*sptr) {
172
0
        st = *sptr;
173
0
        FREEMEM(st->buf);
174
0
    } else {
175
0
        st = (OCTET_STRING_t *)(*sptr = CALLOC(1, sizeof(UTF8String_t)));
176
0
        if(!st) {
177
0
            FREEMEM(buf);
178
0
            return result_failed;
179
0
        }
180
0
    }
181
182
0
    st->buf = buf;
183
0
    st->size = b - buf;
184
185
0
    assert(UTF8String_length(st) == (ssize_t)rnd_len);
186
187
0
    return result_ok;
188
0
}