1 /*
2 * This file has been copied from the zcbor library.
3 * Commit zcbor 0.7.0
4 */
5
6 /*
7 * Copyright (c) 2020 Nordic Semiconductor ASA
8 *
9 * SPDX-License-Identifier: Apache-2.0
10 */
11
12 #include <stddef.h>
13 #include <stdbool.h>
14 #include <stdint.h>
15 #include <string.h>
16 #include "zcbor_common.h"
17
18 _Static_assert((sizeof(size_t) == sizeof(void *)),
19 "This code needs size_t to be the same length as pointers.");
20
21 _Static_assert((sizeof(zcbor_state_t) >= sizeof(struct zcbor_state_constant)),
22 "This code needs zcbor_state_t to be at least as large as zcbor_backups_t.");
23
zcbor_new_backup(zcbor_state_t * state,uint_fast32_t new_elem_count)24 bool zcbor_new_backup(zcbor_state_t *state, uint_fast32_t new_elem_count)
25 {
26 ZCBOR_CHECK_ERROR();
27
28 if ((state->constant_state->current_backup)
29 >= state->constant_state->num_backups) {
30 ZCBOR_ERR(ZCBOR_ERR_NO_BACKUP_MEM);
31 }
32
33 state->payload_moved = false;
34
35 (state->constant_state->current_backup)++;
36
37 /* use the backup at current_backup - 1, since otherwise, the 0th
38 * backup would be unused. */
39 uint_fast32_t i = (state->constant_state->current_backup) - 1;
40
41 memcpy(&state->constant_state->backup_list[i], state,
42 sizeof(zcbor_state_t));
43
44 state->elem_count = new_elem_count;
45
46 return true;
47 }
48
49
zcbor_process_backup(zcbor_state_t * state,uint32_t flags,uint_fast32_t max_elem_count)50 bool zcbor_process_backup(zcbor_state_t *state, uint32_t flags,
51 uint_fast32_t max_elem_count)
52 {
53 const uint8_t *payload = state->payload;
54 const uint_fast32_t elem_count = state->elem_count;
55
56 ZCBOR_CHECK_ERROR();
57
58 if (state->constant_state->current_backup == 0) {
59 zcbor_print("No backups available.\r\n");
60 ZCBOR_ERR(ZCBOR_ERR_NO_BACKUP_ACTIVE);
61 }
62
63 if (flags & ZCBOR_FLAG_RESTORE) {
64 /* use the backup at current_backup - 1, since otherwise, the
65 * 0th backup would be unused. */
66 uint_fast32_t i = state->constant_state->current_backup - 1;
67
68 if (!(flags & ZCBOR_FLAG_TRANSFER_PAYLOAD)) {
69 if (state->constant_state->backup_list[i].payload_moved) {
70 zcbor_print("Payload pointer out of date.\r\n");
71 ZCBOR_FAIL();
72 }
73 }
74 memcpy(state, &state->constant_state->backup_list[i],
75 sizeof(zcbor_state_t));
76 }
77
78 if (flags & ZCBOR_FLAG_CONSUME) {
79 state->constant_state->current_backup--;
80 }
81
82 if (elem_count > max_elem_count) {
83 zcbor_print("elem_count: %" PRIuFAST32 " (expected max %" PRIuFAST32 ")\r\n",
84 elem_count, max_elem_count);
85 ZCBOR_ERR(ZCBOR_ERR_HIGH_ELEM_COUNT);
86 }
87
88 if (flags & ZCBOR_FLAG_TRANSFER_PAYLOAD) {
89 state->payload = payload;
90 }
91
92 return true;
93 }
94
update_backups(zcbor_state_t * state,uint8_t const * new_payload_end)95 static void update_backups(zcbor_state_t *state, uint8_t const *new_payload_end)
96 {
97 if (state->constant_state) {
98 for (int i = 0; i < state->constant_state->current_backup; i++) {
99 state->constant_state->backup_list[i].payload_end = new_payload_end;
100 state->constant_state->backup_list[i].payload_moved = true;
101 }
102 }
103 }
104
105
zcbor_union_start_code(zcbor_state_t * state)106 bool zcbor_union_start_code(zcbor_state_t *state)
107 {
108 if (!zcbor_new_backup(state, state->elem_count)) {
109 ZCBOR_FAIL();
110 }
111 return true;
112 }
113
114
zcbor_union_elem_code(zcbor_state_t * state)115 bool zcbor_union_elem_code(zcbor_state_t *state)
116 {
117 if (!zcbor_process_backup(state, ZCBOR_FLAG_RESTORE, state->elem_count)) {
118 ZCBOR_FAIL();
119 }
120 return true;
121 }
122
zcbor_union_end_code(zcbor_state_t * state)123 bool zcbor_union_end_code(zcbor_state_t *state)
124 {
125 if (!zcbor_process_backup(state, ZCBOR_FLAG_CONSUME, state->elem_count)) {
126 ZCBOR_FAIL();
127 }
128 return true;
129 }
130
zcbor_new_state(zcbor_state_t * state_array,uint_fast32_t n_states,const uint8_t * payload,size_t payload_len,uint_fast32_t elem_count)131 void zcbor_new_state(zcbor_state_t *state_array, uint_fast32_t n_states,
132 const uint8_t *payload, size_t payload_len, uint_fast32_t elem_count)
133 {
134 state_array[0].payload = payload;
135 state_array[0].payload_end = payload + payload_len;
136 state_array[0].elem_count = elem_count;
137 state_array[0].indefinite_length_array = false;
138 state_array[0].payload_moved = false;
139 state_array[0].constant_state = NULL;
140
141 if(n_states < 2) {
142 return;
143 }
144
145 /* Use the last state as a struct zcbor_state_constant object. */
146 state_array[0].constant_state = (struct zcbor_state_constant *)&state_array[n_states - 1];
147 state_array[0].constant_state->backup_list = NULL;
148 state_array[0].constant_state->num_backups = n_states - 2;
149 state_array[0].constant_state->current_backup = 0;
150 state_array[0].constant_state->error = ZCBOR_SUCCESS;
151 #ifdef ZCBOR_STOP_ON_ERROR
152 state_array[0].constant_state->stop_on_error = false;
153 #endif
154 if (n_states > 2) {
155 state_array[0].constant_state->backup_list = &state_array[1];
156 }
157 }
158
zcbor_update_state(zcbor_state_t * state,const uint8_t * payload,size_t payload_len)159 void zcbor_update_state(zcbor_state_t *state,
160 const uint8_t *payload, size_t payload_len)
161 {
162 state->payload = payload;
163 state->payload_end = payload + payload_len;
164
165 update_backups(state, state->payload_end);
166 }
167
168
zcbor_validate_string_fragments(struct zcbor_string_fragment * fragments,uint_fast32_t num_fragments)169 bool zcbor_validate_string_fragments(struct zcbor_string_fragment *fragments,
170 uint_fast32_t num_fragments)
171 {
172 size_t total_len = 0;
173
174 if (fragments == NULL) {
175 return false;
176 }
177
178 for (uint_fast32_t i = 0; i < num_fragments; i++) {
179 if (fragments[i].offset != total_len) {
180 return false;
181 }
182 if (fragments[i].fragment.value == NULL) {
183 return false;
184 }
185 if (fragments[i].total_len != fragments[0].total_len) {
186 return false;
187 }
188 total_len += fragments[i].fragment.len;
189 if (total_len > fragments[0].total_len) {
190 return false;
191 }
192 }
193
194 if (num_fragments && total_len != fragments[0].total_len) {
195 return false;
196 }
197
198 if (num_fragments && (fragments[0].total_len == ZCBOR_STRING_FRAGMENT_UNKNOWN_LENGTH)) {
199 for (uint_fast32_t i = 0; i < num_fragments; i++) {
200 fragments[i].total_len = total_len;
201 }
202 }
203
204 return true;
205 }
206
zcbor_splice_string_fragments(struct zcbor_string_fragment * fragments,uint_fast32_t num_fragments,uint8_t * result,size_t * result_len)207 bool zcbor_splice_string_fragments(struct zcbor_string_fragment *fragments,
208 uint_fast32_t num_fragments, uint8_t *result, size_t *result_len)
209 {
210 size_t total_len = 0;
211
212 if (!fragments) {
213 return false;
214 }
215
216 for (uint_fast32_t i = 0; i < num_fragments; i++) {
217 if ((total_len > *result_len)
218 || (fragments[i].fragment.len > (*result_len - total_len))) {
219 return false;
220 }
221 memcpy(&result[total_len],
222 fragments[i].fragment.value, fragments[i].fragment.len);
223 total_len += fragments[i].fragment.len;
224 }
225
226 *result_len = total_len;
227 return true;
228 }
229