/src/open5gs/lib/asn1c/common/BIT_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 <BIT_STRING.h> |
8 | | |
9 | | asn_random_fill_result_t |
10 | | BIT_STRING_random_fill(const asn_TYPE_descriptor_t *td, void **sptr, |
11 | | const asn_encoding_constraints_t *constraints, |
12 | 0 | size_t max_length) { |
13 | 0 | const asn_OCTET_STRING_specifics_t *specs = |
14 | 0 | td->specifics ? (const asn_OCTET_STRING_specifics_t *)td->specifics |
15 | 0 | : &asn_SPC_BIT_STRING_specs; |
16 | 0 | asn_random_fill_result_t result_ok = {ARFILL_OK, 1}; |
17 | 0 | asn_random_fill_result_t result_failed = {ARFILL_FAILED, 0}; |
18 | 0 | asn_random_fill_result_t result_skipped = {ARFILL_SKIPPED, 0}; |
19 | 0 | static unsigned lengths[] = {0, 1, 2, 3, 4, 8, |
20 | 0 | 126, 127, 128, 16383, 16384, 16385, |
21 | 0 | 65534, 65535, 65536, 65537}; |
22 | 0 | uint8_t *buf; |
23 | 0 | uint8_t *bend; |
24 | 0 | uint8_t *b; |
25 | 0 | size_t rnd_bits, rnd_len; |
26 | 0 | BIT_STRING_t *st; |
27 | |
|
28 | 0 | if(max_length == 0) return result_skipped; |
29 | | |
30 | 0 | switch(specs->subvariant) { |
31 | 0 | case ASN_OSUBV_ANY: |
32 | 0 | return result_failed; |
33 | 0 | case ASN_OSUBV_BIT: |
34 | 0 | break; |
35 | 0 | default: |
36 | 0 | break; |
37 | 0 | } |
38 | | |
39 | | /* Figure out how far we should go */ |
40 | 0 | rnd_bits = lengths[asn_random_between( |
41 | 0 | 0, sizeof(lengths) / sizeof(lengths[0]) - 1)]; |
42 | 0 | #if !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT) |
43 | 0 | if(!constraints || !constraints->per_constraints) |
44 | 0 | constraints = &td->encoding_constraints; |
45 | 0 | if(constraints->per_constraints) { |
46 | 0 | const asn_per_constraint_t *pc = &constraints->per_constraints->size; |
47 | 0 | if(pc->flags & APC_CONSTRAINED) { |
48 | 0 | long suggested_upper_bound = pc->upper_bound < (ssize_t)max_length |
49 | 0 | ? pc->upper_bound |
50 | 0 | : (ssize_t)max_length; |
51 | 0 | if(max_length < (size_t)pc->lower_bound) { |
52 | 0 | return result_skipped; |
53 | 0 | } |
54 | 0 | if(pc->flags & APC_EXTENSIBLE) { |
55 | 0 | switch(asn_random_between(0, 5)) { |
56 | 0 | case 0: |
57 | 0 | if(pc->lower_bound > 0) { |
58 | 0 | rnd_bits = pc->lower_bound - 1; |
59 | 0 | break; |
60 | 0 | } |
61 | | /* Fall through */ |
62 | 0 | case 1: |
63 | 0 | rnd_bits = pc->upper_bound + 1; |
64 | 0 | break; |
65 | 0 | case 2: |
66 | | /* Keep rnd_bits from the table */ |
67 | 0 | if(rnd_bits < max_length) { |
68 | 0 | break; |
69 | 0 | } |
70 | | /* Fall through */ |
71 | 0 | default: |
72 | 0 | rnd_bits = asn_random_between(pc->lower_bound, |
73 | 0 | suggested_upper_bound); |
74 | 0 | } |
75 | 0 | } else { |
76 | 0 | rnd_bits = |
77 | 0 | asn_random_between(pc->lower_bound, suggested_upper_bound); |
78 | 0 | } |
79 | 0 | } else { |
80 | 0 | rnd_bits = asn_random_between(0, max_length - 1); |
81 | 0 | } |
82 | 0 | } else { |
83 | | #else |
84 | | if(!constraints) constraints = &td->encoding_constraints; |
85 | | { |
86 | | #endif /* !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT) */ |
87 | 0 | if(rnd_bits >= max_length) { |
88 | 0 | rnd_bits = asn_random_between(0, max_length - 1); |
89 | 0 | } |
90 | 0 | } |
91 | | |
92 | 0 | rnd_len = (rnd_bits + 7) / 8; |
93 | 0 | buf = CALLOC(1, rnd_len + 1); |
94 | 0 | if(!buf) return result_failed; |
95 | | |
96 | 0 | bend = &buf[rnd_len]; |
97 | |
|
98 | 0 | for(b = buf; b < bend; b++) { |
99 | 0 | *(uint8_t *)b = asn_random_between(0, 255); |
100 | 0 | } |
101 | 0 | *b = 0; /* Zero-terminate just in case. */ |
102 | |
|
103 | 0 | if(*sptr) { |
104 | 0 | st = *sptr; |
105 | 0 | FREEMEM(st->buf); |
106 | 0 | } else { |
107 | 0 | st = (BIT_STRING_t *)(*sptr = CALLOC(1, specs->struct_size)); |
108 | 0 | if(!st) { |
109 | 0 | FREEMEM(buf); |
110 | 0 | return result_failed; |
111 | 0 | } |
112 | 0 | } |
113 | | |
114 | 0 | st->buf = buf; |
115 | 0 | st->size = rnd_len; |
116 | 0 | st->bits_unused = (8 - (rnd_bits & 0x7)) & 0x7; |
117 | 0 | if(st->bits_unused) { |
118 | 0 | assert(st->size > 0); |
119 | 0 | st->buf[st->size-1] &= 0xff << st->bits_unused; |
120 | 0 | } |
121 | |
|
122 | 0 | result_ok.length = st->size; |
123 | 0 | return result_ok; |
124 | 0 | } |