blob: cccaee503a4dd94400270f4e668e3bf31689a218 [file] [log] [blame]
David Zeuthen21e95262016-07-27 17:58:40 -04001/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
David Zeuthenc612e2e2016-09-16 16:44:08 -04004 * Permission is hereby granted, free of charge, to any person
5 * obtaining a copy of this software and associated documentation
6 * files (the "Software"), to deal in the Software without
7 * restriction, including without limitation the rights to use, copy,
8 * modify, merge, publish, distribute, sublicense, and/or sell copies
9 * of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
David Zeuthen21e95262016-07-27 17:58:40 -040011 *
David Zeuthenc612e2e2016-09-16 16:44:08 -040012 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
David Zeuthen21e95262016-07-27 17:58:40 -040014 *
David Zeuthenc612e2e2016-09-16 16:44:08 -040015 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
David Zeuthen21e95262016-07-27 17:58:40 -040023 */
24
25#include "avb_util.h"
26
27uint32_t avb_be32toh(uint32_t in) {
28 uint8_t* d = (uint8_t*)∈
29 uint32_t ret;
30 ret = ((uint32_t)d[0]) << 24;
31 ret |= ((uint32_t)d[1]) << 16;
32 ret |= ((uint32_t)d[2]) << 8;
33 ret |= ((uint32_t)d[3]);
34 return ret;
35}
36
37uint64_t avb_be64toh(uint64_t in) {
38 uint8_t* d = (uint8_t*)&in;
39 uint64_t ret;
40 ret = ((uint64_t)d[0]) << 56;
41 ret |= ((uint64_t)d[1]) << 48;
42 ret |= ((uint64_t)d[2]) << 40;
43 ret |= ((uint64_t)d[3]) << 32;
44 ret |= ((uint64_t)d[4]) << 24;
45 ret |= ((uint64_t)d[5]) << 16;
46 ret |= ((uint64_t)d[6]) << 8;
47 ret |= ((uint64_t)d[7]);
48 return ret;
49}
50
David Zeuthen8b6973b2016-09-20 12:39:49 -040051/* Converts a 32-bit unsigned integer from host to big-endian byte order. */
52uint32_t avb_htobe32(uint32_t in) {
53 union {
54 uint32_t word;
55 uint8_t bytes[4];
56 } ret;
57 ret.bytes[0] = (in >> 24) & 0xff;
58 ret.bytes[1] = (in >> 16) & 0xff;
59 ret.bytes[2] = (in >> 8) & 0xff;
60 ret.bytes[3] = in & 0xff;
61 return ret.word;
62}
63
64/* Converts a 64-bit unsigned integer from host to big-endian byte order. */
65uint64_t avb_htobe64(uint64_t in) {
66 union {
67 uint64_t word;
68 uint8_t bytes[8];
69 } ret;
70 ret.bytes[0] = (in >> 56) & 0xff;
71 ret.bytes[1] = (in >> 48) & 0xff;
72 ret.bytes[2] = (in >> 40) & 0xff;
73 ret.bytes[3] = (in >> 32) & 0xff;
74 ret.bytes[4] = (in >> 24) & 0xff;
75 ret.bytes[5] = (in >> 16) & 0xff;
76 ret.bytes[6] = (in >> 8) & 0xff;
77 ret.bytes[7] = in & 0xff;
78 return ret.word;
79}
80
David Zeuthen21e95262016-07-27 17:58:40 -040081int avb_safe_memcmp(const void* s1, const void* s2, size_t n) {
82 const unsigned char* us1 = s1;
83 const unsigned char* us2 = s2;
84 int result = 0;
85
86 if (0 == n) return 0;
87
88 /*
89 * Code snippet without data-dependent branch due to Nate Lawson
90 * (nate@root.org) of Root Labs.
91 */
92 while (n--) result |= *us1++ ^ *us2++;
93
94 return result != 0;
95}
96
97bool avb_safe_add_to(uint64_t* value, uint64_t value_to_add) {
98 uint64_t original_value;
99
100 avb_assert(value != NULL);
101
102 original_value = *value;
103
104 *value += value_to_add;
105 if (*value < original_value) {
106 avb_error("Overflow when adding values.\n");
107 return false;
108 }
109
110 return true;
111}
112
113bool avb_safe_add(uint64_t* out_result, uint64_t a, uint64_t b) {
114 uint64_t dummy;
115 if (out_result == NULL) out_result = &dummy;
116 *out_result = a;
117 return avb_safe_add_to(out_result, b);
118}
119
120bool avb_validate_utf8(const uint8_t* data, size_t num_bytes) {
121 size_t n;
122 unsigned int num_cc;
123
124 for (n = 0, num_cc = 0; n < num_bytes; n++) {
125 uint8_t c = data[n];
126
127 if (num_cc > 0) {
128 if ((c & (0x80 | 0x40)) == 0x80) {
129 /* 10xx xxxx */
130 } else {
131 goto fail;
132 }
133 num_cc--;
134 } else {
135 if (c < 0x80) {
136 num_cc = 0;
137 } else if ((c & (0x80 | 0x40 | 0x20)) == (0x80 | 0x40)) {
138 /* 110x xxxx */
139 num_cc = 1;
140 } else if ((c & (0x80 | 0x40 | 0x20 | 0x10)) == (0x80 | 0x40 | 0x20)) {
141 /* 1110 xxxx */
142 num_cc = 2;
143 } else if ((c & (0x80 | 0x40 | 0x20 | 0x10 | 0x08)) ==
144 (0x80 | 0x40 | 0x20 | 0x10)) {
145 /* 1111 0xxx */
146 num_cc = 3;
147 } else {
148 goto fail;
149 }
150 }
151 }
152
153 if (num_cc != 0) {
154 goto fail;
155 }
156
157 return true;
158
159fail:
160 return false;
161}
162
163bool avb_str_concat(char* buf, size_t buf_size, const char* str1,
164 size_t str1_len, const char* str2, size_t str2_len) {
165 uint64_t combined_len;
166
167 if (!avb_safe_add(&combined_len, str1_len, str2_len)) {
168 avb_error("Overflow when adding string sizes.\n");
169 return false;
170 }
171
172 if (combined_len > buf_size - 1) {
173 avb_error("Insufficient buffer space.\n");
174 return false;
175 }
176
177 avb_memcpy(buf, str1, str1_len);
178 avb_memcpy(buf + str1_len, str2, str2_len);
179 buf[combined_len] = '\0';
180
181 return true;
182}
183
184void* avb_malloc(size_t size) {
185 void* ret = avb_malloc_(size);
186 if (ret == NULL) {
187 avb_error("Failed to allocate memory.\n");
188 return NULL;
189 }
190 return ret;
191}
192
193void* avb_calloc(size_t size) {
194 void* ret = avb_malloc(size);
195 if (ret == NULL) {
196 return NULL;
197 }
198
199 avb_memset(ret, '\0', size);
200 return ret;
201}
202
203char* avb_strdup(const char* str) {
204 size_t len = avb_strlen(str);
205 char* ret = avb_malloc(len + 1);
206 if (ret == NULL) {
207 return NULL;
208 }
209
210 avb_memcpy(ret, str, len);
211 ret[len] = '\0';
212
213 return ret;
214}
215
216const char* avb_strstr(const char* haystack, const char* needle) {
217 size_t n, m;
218
219 /* Look through |haystack| and check if the first character of
220 * |needle| matches. If so, check the rest of |needle|.
221 */
222 for (n = 0; haystack[n] != '\0'; n++) {
223 if (haystack[n] != needle[0]) continue;
224
225 for (m = 1;; m++) {
226 if (needle[m] == '\0') {
227 return haystack + n;
228 }
229
230 if (haystack[n + m] != needle[m]) break;
231 }
232 }
233
234 return NULL;
235}
236
237char* avb_replace(const char* str, const char* search, const char* replace) {
238 char* ret = NULL;
239 size_t ret_len = 0;
240 size_t search_len, replace_len;
241 const char* str_after_last_replace;
242
243 search_len = avb_strlen(search);
244 replace_len = avb_strlen(replace);
245
246 str_after_last_replace = str;
247 while (*str != '\0') {
248 const char* s;
249 size_t num_before;
250 size_t num_new;
251
252 s = avb_strstr(str, search);
253 if (s == NULL) break;
254
255 num_before = s - str;
256
257 if (ret == NULL) {
258 num_new = num_before + replace_len + 1;
259 ret = avb_malloc(num_new);
260 if (ret == NULL) {
261 goto out;
262 }
263 avb_memcpy(ret, str, num_before);
264 avb_memcpy(ret + num_before, replace, replace_len);
265 ret[num_new - 1] = '\0';
266 ret_len = num_new - 1;
267 } else {
268 char* new_str;
269 num_new = ret_len + num_before + replace_len + 1;
270 new_str = avb_malloc(num_new);
271 if (ret == NULL) {
272 goto out;
273 }
274 avb_memcpy(new_str, ret, ret_len);
275 avb_memcpy(new_str + ret_len, str, num_before);
276 avb_memcpy(new_str + ret_len + num_before, replace, replace_len);
277 new_str[num_new - 1] = '\0';
278 avb_free(ret);
279 ret = new_str;
280 ret_len = num_new - 1;
281 }
282
283 str = s + search_len;
284 str_after_last_replace = str;
285 }
286
287 if (ret == NULL) {
288 ret = avb_strdup(str_after_last_replace);
289 if (ret == NULL) {
290 goto out;
291 }
292 } else {
293 size_t num_remaining = avb_strlen(str_after_last_replace);
294 size_t num_new = ret_len + num_remaining + 1;
295 char* new_str = avb_malloc(num_new);
296 if (ret == NULL) goto out;
297 avb_memcpy(new_str, ret, ret_len);
298 avb_memcpy(new_str + ret_len, str_after_last_replace, num_remaining);
299 new_str[num_new - 1] = '\0';
300 avb_free(ret);
301 ret = new_str;
302 ret_len = num_new - 1;
303 }
304
305out:
306 return ret;
307}