/src/open5gs/lib/asn1c/common/OCTET_STRING_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 <OCTET_STRING.h> |
8 | | |
9 | | /* |
10 | | * Biased function for randomizing character values around their limits. |
11 | | */ |
12 | | static uint32_t |
13 | 0 | OCTET_STRING__random_char(unsigned long lb, unsigned long ub) { |
14 | 0 | assert(lb <= ub); |
15 | 0 | switch(asn_random_between(0, 16)) { |
16 | 0 | case 0: |
17 | 0 | if(lb < ub) return lb + 1; |
18 | | /* Fall through */ |
19 | 0 | case 1: |
20 | 0 | return lb; |
21 | 0 | case 2: |
22 | 0 | if(lb < ub) return ub - 1; |
23 | | /* Fall through */ |
24 | 0 | case 3: |
25 | 0 | return ub; |
26 | 0 | default: |
27 | 0 | return asn_random_between(lb, ub); |
28 | 0 | } |
29 | 0 | } |
30 | | |
31 | | asn_random_fill_result_t |
32 | | OCTET_STRING_random_fill(const asn_TYPE_descriptor_t *td, void **sptr, |
33 | | const asn_encoding_constraints_t *constraints, |
34 | 0 | size_t max_length) { |
35 | 0 | const asn_OCTET_STRING_specifics_t *specs = td->specifics |
36 | 0 | ? (const asn_OCTET_STRING_specifics_t *)td->specifics |
37 | 0 | : &asn_SPC_OCTET_STRING_specs; |
38 | 0 | asn_random_fill_result_t result_ok = {ARFILL_OK, 1}; |
39 | 0 | asn_random_fill_result_t result_failed = {ARFILL_FAILED, 0}; |
40 | 0 | asn_random_fill_result_t result_skipped = {ARFILL_SKIPPED, 0}; |
41 | 0 | unsigned int unit_bytes = 1; |
42 | 0 | unsigned long clb = 0; /* Lower bound on char */ |
43 | 0 | unsigned long cub = 255; /* Higher bound on char value */ |
44 | 0 | uint8_t *buf; |
45 | 0 | uint8_t *bend; |
46 | 0 | uint8_t *b; |
47 | 0 | size_t rnd_len; |
48 | 0 | OCTET_STRING_t *st; |
49 | |
|
50 | 0 | if(max_length == 0 && !*sptr) return result_skipped; |
51 | | |
52 | 0 | switch(specs->subvariant) { |
53 | 0 | default: |
54 | 0 | case ASN_OSUBV_ANY: |
55 | 0 | return result_failed; |
56 | 0 | case ASN_OSUBV_BIT: |
57 | | /* Handled by BIT_STRING itself. */ |
58 | 0 | return result_failed; |
59 | 0 | case ASN_OSUBV_STR: |
60 | 0 | unit_bytes = 1; |
61 | 0 | clb = 0; |
62 | 0 | cub = 255; |
63 | 0 | break; |
64 | 0 | case ASN_OSUBV_U16: |
65 | 0 | unit_bytes = 2; |
66 | 0 | clb = 0; |
67 | 0 | cub = 65535; |
68 | 0 | break; |
69 | 0 | case ASN_OSUBV_U32: |
70 | 0 | unit_bytes = 4; |
71 | 0 | clb = 0; |
72 | 0 | cub = 0x10FFFF; |
73 | 0 | break; |
74 | 0 | } |
75 | | |
76 | 0 | #if !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT) |
77 | 0 | if(!constraints || !constraints->per_constraints) |
78 | 0 | constraints = &td->encoding_constraints; |
79 | 0 | if(constraints->per_constraints) { |
80 | 0 | const asn_per_constraint_t *pc = &constraints->per_constraints->value; |
81 | 0 | if(pc->flags & APC_SEMI_CONSTRAINED) { |
82 | 0 | clb = pc->lower_bound; |
83 | 0 | } else if(pc->flags & APC_CONSTRAINED) { |
84 | 0 | clb = pc->lower_bound; |
85 | 0 | cub = pc->upper_bound; |
86 | 0 | } |
87 | 0 | } |
88 | | #else |
89 | | if(!constraints) constraints = &td->encoding_constraints; |
90 | | #endif /* !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT) */ |
91 | |
|
92 | 0 | rnd_len = |
93 | 0 | OCTET_STRING_random_length_constrained(td, constraints, max_length); |
94 | |
|
95 | 0 | buf = CALLOC(unit_bytes, rnd_len + 1); |
96 | 0 | if(!buf) return result_failed; |
97 | | |
98 | 0 | bend = &buf[unit_bytes * rnd_len]; |
99 | |
|
100 | 0 | switch(unit_bytes) { |
101 | 0 | case 1: |
102 | 0 | for(b = buf; b < bend; b += unit_bytes) { |
103 | 0 | *(uint8_t *)b = OCTET_STRING__random_char(clb, cub); |
104 | 0 | } |
105 | 0 | *(uint8_t *)b = 0; |
106 | 0 | break; |
107 | 0 | case 2: |
108 | 0 | for(b = buf; b < bend; b += unit_bytes) { |
109 | 0 | uint32_t code = OCTET_STRING__random_char(clb, cub); |
110 | 0 | b[0] = code >> 8; |
111 | 0 | b[1] = code; |
112 | 0 | } |
113 | 0 | *(uint16_t *)b = 0; |
114 | 0 | break; |
115 | 0 | case 4: |
116 | 0 | for(b = buf; b < bend; b += unit_bytes) { |
117 | 0 | uint32_t code = OCTET_STRING__random_char(clb, cub); |
118 | 0 | b[0] = code >> 24; |
119 | 0 | b[1] = code >> 16; |
120 | 0 | b[2] = code >> 8; |
121 | 0 | b[3] = code; |
122 | 0 | } |
123 | 0 | *(uint32_t *)b = 0; |
124 | 0 | break; |
125 | 0 | } |
126 | | |
127 | 0 | if(*sptr) { |
128 | 0 | st = *sptr; |
129 | 0 | FREEMEM(st->buf); |
130 | 0 | } else { |
131 | 0 | st = (OCTET_STRING_t *)(*sptr = CALLOC(1, specs->struct_size)); |
132 | 0 | if(!st) { |
133 | 0 | FREEMEM(buf); |
134 | 0 | return result_failed; |
135 | 0 | } |
136 | 0 | } |
137 | | |
138 | 0 | st->buf = buf; |
139 | 0 | st->size = unit_bytes * rnd_len; |
140 | |
|
141 | 0 | result_ok.length = st->size; |
142 | 0 | return result_ok; |
143 | 0 | } |
144 | | |
145 | | size_t |
146 | | OCTET_STRING_random_length_constrained( |
147 | | const asn_TYPE_descriptor_t *td, |
148 | 0 | const asn_encoding_constraints_t *constraints, size_t max_length) { |
149 | 0 | const unsigned lengths[] = {0, 1, 2, 3, 4, 8, |
150 | 0 | 126, 127, 128, 16383, 16384, 16385, |
151 | 0 | 65534, 65535, 65536, 65537}; |
152 | 0 | size_t rnd_len; |
153 | | |
154 | | /* Figure out how far we should go */ |
155 | 0 | rnd_len = lengths[asn_random_between( |
156 | 0 | 0, sizeof(lengths) / sizeof(lengths[0]) - 1)]; |
157 | |
|
158 | 0 | #if !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT) |
159 | 0 | if(!constraints || !constraints->per_constraints) |
160 | 0 | constraints = &td->encoding_constraints; |
161 | 0 | if(constraints->per_constraints) { |
162 | 0 | const asn_per_constraint_t *pc = &constraints->per_constraints->size; |
163 | 0 | if(pc->flags & APC_CONSTRAINED) { |
164 | 0 | long suggested_upper_bound = pc->upper_bound < (ssize_t)max_length |
165 | 0 | ? pc->upper_bound |
166 | 0 | : (ssize_t)max_length; |
167 | 0 | if(max_length <= (size_t)pc->lower_bound) { |
168 | 0 | return pc->lower_bound; |
169 | 0 | } |
170 | 0 | if(pc->flags & APC_EXTENSIBLE) { |
171 | 0 | switch(asn_random_between(0, 5)) { |
172 | 0 | case 0: |
173 | 0 | if(pc->lower_bound > 0) { |
174 | 0 | rnd_len = pc->lower_bound - 1; |
175 | 0 | break; |
176 | 0 | } |
177 | | /* Fall through */ |
178 | 0 | case 1: |
179 | 0 | rnd_len = pc->upper_bound + 1; |
180 | 0 | break; |
181 | 0 | case 2: |
182 | | /* Keep rnd_len from the table */ |
183 | 0 | if(rnd_len <= max_length) { |
184 | 0 | break; |
185 | 0 | } |
186 | | /* Fall through */ |
187 | 0 | default: |
188 | 0 | rnd_len = asn_random_between(pc->lower_bound, |
189 | 0 | suggested_upper_bound); |
190 | 0 | } |
191 | 0 | } else { |
192 | 0 | rnd_len = |
193 | 0 | asn_random_between(pc->lower_bound, suggested_upper_bound); |
194 | 0 | } |
195 | 0 | } else { |
196 | 0 | rnd_len = asn_random_between(0, max_length); |
197 | 0 | } |
198 | 0 | } else { |
199 | | #else |
200 | | if(!constraints) constraints = &td->encoding_constraints; |
201 | | { |
202 | | #endif /* !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT) */ |
203 | 0 | if(rnd_len > max_length) { |
204 | 0 | rnd_len = asn_random_between(0, max_length); |
205 | 0 | } |
206 | 0 | } |
207 | | |
208 | 0 | return rnd_len; |
209 | 0 | } |