xref: /spdk/lib/json/json_util.c (revision f86f10757912918b8ba7b4b3bfdab1cd4c2d180c)
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright (c) Intel Corporation.
5  *   All rights reserved.
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following conditions
9  *   are met:
10  *
11  *     * Redistributions of source code must retain the above copyright
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright
14  *       notice, this list of conditions and the following disclaimer in
15  *       the documentation and/or other materials provided with the
16  *       distribution.
17  *     * Neither the name of Intel Corporation nor the names of its
18  *       contributors may be used to endorse or promote products derived
19  *       from this software without specific prior written permission.
20  *
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 #include "json_internal.h"
35 
36 size_t
37 spdk_json_val_len(const struct spdk_json_val *val)
38 {
39 	if (val == NULL) {
40 		return 0;
41 	}
42 
43 	if (val->type == SPDK_JSON_VAL_ARRAY_BEGIN || val->type == SPDK_JSON_VAL_OBJECT_BEGIN) {
44 		return val->len + 2;
45 	}
46 
47 	return 1;
48 }
49 
50 bool
51 spdk_json_strequal(const struct spdk_json_val *val, const char *str)
52 {
53 	size_t len;
54 
55 	if (val->type != SPDK_JSON_VAL_STRING && val->type != SPDK_JSON_VAL_NAME) {
56 		return false;
57 	}
58 
59 	len = strlen(str);
60 	if (val->len != len) {
61 		return false;
62 	}
63 
64 	return memcmp(val->start, str, len) == 0;
65 }
66 
67 char *
68 spdk_json_strdup(const struct spdk_json_val *val)
69 {
70 	size_t len;
71 	char *s;
72 
73 	if (val->type != SPDK_JSON_VAL_STRING && val->type != SPDK_JSON_VAL_NAME) {
74 		return NULL;
75 	}
76 
77 	len = val->len;
78 
79 	if (memchr(val->start, '\0', len)) {
80 		/* String contains embedded NUL, so it is not a valid C string. */
81 		return NULL;
82 	}
83 
84 	s = malloc(len + 1);
85 	if (s == NULL) {
86 		return s;
87 	}
88 
89 	memcpy(s, val->start, len);
90 	s[len] = '\0';
91 
92 	return s;
93 }
94 
95 struct spdk_json_num {
96 	bool negative;
97 	uint64_t significand;
98 	int64_t exponent;
99 };
100 
101 static int
102 spdk_json_number_split(const struct spdk_json_val *val, struct spdk_json_num *num)
103 {
104 	const char *iter;
105 	size_t remaining;
106 	uint64_t *pval;
107 	uint64_t frac_digits = 0;
108 	uint64_t exponent_u64 = 0;
109 	bool exponent_negative = false;
110 	enum {
111 		NUM_STATE_INT,
112 		NUM_STATE_FRAC,
113 		NUM_STATE_EXP,
114 	} state;
115 
116 	memset(num, 0, sizeof(*num));
117 
118 	if (val->type != SPDK_JSON_VAL_NUMBER) {
119 		return -EINVAL;
120 	}
121 
122 	remaining = val->len;
123 	if (remaining == 0) {
124 		return -EINVAL;
125 	}
126 
127 	iter = val->start;
128 	if (*iter == '-') {
129 		num->negative = true;
130 		iter++;
131 		remaining--;
132 	}
133 
134 	state = NUM_STATE_INT;
135 	pval = &num->significand;
136 	while (remaining--) {
137 		char c = *iter++;
138 
139 		if (c == '.') {
140 			state = NUM_STATE_FRAC;
141 		} else if (c == 'e' || c == 'E') {
142 			state = NUM_STATE_EXP;
143 			pval = &exponent_u64;
144 		} else if (c == '-') {
145 			assert(state == NUM_STATE_EXP);
146 			exponent_negative = true;
147 		} else if (c == '+') {
148 			assert(state == NUM_STATE_EXP);
149 			/* exp_negative = false; */ /* already false by default */
150 		} else {
151 			uint64_t new_val;
152 
153 			assert(c >= '0' && c <= '9');
154 			new_val = *pval * 10 + c - '0';
155 			if (new_val < *pval) {
156 				return -ERANGE;
157 			}
158 
159 			if (state == NUM_STATE_FRAC) {
160 				frac_digits++;
161 			}
162 
163 			*pval = new_val;
164 		}
165 	}
166 
167 	if (exponent_negative) {
168 		if (exponent_u64 > 9223372036854775808ULL) { /* abs(INT64_MIN) */
169 			return -ERANGE;
170 		}
171 		num->exponent = (int64_t) - exponent_u64;
172 	} else {
173 		if (exponent_u64 > INT64_MAX) {
174 			return -ERANGE;
175 		}
176 		num->exponent = exponent_u64;
177 	}
178 	num->exponent -= frac_digits;
179 
180 	/* Apply as much of the exponent as possible without overflow or truncation */
181 	if (num->exponent < 0) {
182 		while (num->exponent && num->significand >= 10 && num->significand % 10 == 0) {
183 			num->significand /= 10;
184 			num->exponent++;
185 		}
186 	} else { /* positive exponent */
187 		while (num->exponent) {
188 			uint64_t new_val = num->significand * 10;
189 
190 			if (new_val < num->significand) {
191 				break;
192 			}
193 
194 			num->significand = new_val;
195 			num->exponent--;
196 		}
197 	}
198 
199 	return 0;
200 }
201 
202 int
203 spdk_json_number_to_int32(const struct spdk_json_val *val, int32_t *num)
204 {
205 	struct spdk_json_num split_num;
206 	int rc;
207 
208 	rc = spdk_json_number_split(val, &split_num);
209 	if (rc) {
210 		return rc;
211 	}
212 
213 	if (split_num.exponent) {
214 		return -ERANGE;
215 	}
216 
217 	if (split_num.negative) {
218 		if (split_num.significand > 2147483648) { /* abs(INT32_MIN) */
219 			return -ERANGE;
220 		}
221 		*num = (int32_t) - (int64_t)split_num.significand;
222 		return 0;
223 	}
224 
225 	/* positive */
226 	if (split_num.significand > INT32_MAX) {
227 		return -ERANGE;
228 	}
229 	*num = (int32_t)split_num.significand;
230 	return 0;
231 }
232 
233 int
234 spdk_json_number_to_uint32(const struct spdk_json_val *val, uint32_t *num)
235 {
236 	struct spdk_json_num split_num;
237 	int rc;
238 
239 	rc = spdk_json_number_split(val, &split_num);
240 	if (rc) {
241 		return rc;
242 	}
243 
244 	if (split_num.exponent || split_num.negative) {
245 		return -ERANGE;
246 	}
247 
248 	if (split_num.significand > UINT32_MAX) {
249 		return -ERANGE;
250 	}
251 	*num = (uint32_t)split_num.significand;
252 	return 0;
253 }
254 
255 int
256 spdk_json_number_to_uint64(const struct spdk_json_val *val, uint64_t *num)
257 {
258 	struct spdk_json_num split_num;
259 	int rc;
260 
261 	rc = spdk_json_number_split(val, &split_num);
262 	if (rc) {
263 		return rc;
264 	}
265 
266 	if (split_num.exponent || split_num.negative) {
267 		return -ERANGE;
268 	}
269 
270 	*num = split_num.significand;
271 	return 0;
272 }
273 
274 int
275 spdk_json_decode_object(const struct spdk_json_val *values,
276 			const struct spdk_json_object_decoder *decoders, size_t num_decoders, void *out)
277 {
278 	uint32_t i;
279 	bool invalid = false;
280 	size_t decidx;
281 	bool *seen;
282 
283 	if (values == NULL || values->type != SPDK_JSON_VAL_OBJECT_BEGIN) {
284 		return -1;
285 	}
286 
287 	seen = calloc(sizeof(bool), num_decoders);
288 	if (seen == NULL) {
289 		return -1;
290 	}
291 
292 	for (i = 0; i < values->len;) {
293 		const struct spdk_json_val *name = &values[i + 1];
294 		const struct spdk_json_val *v = &values[i + 2];
295 		bool found = false;
296 
297 		for (decidx = 0; decidx < num_decoders; decidx++) {
298 			const struct spdk_json_object_decoder *dec = &decoders[decidx];
299 			if (spdk_json_strequal(name, dec->name)) {
300 				void *field = (void *)((uintptr_t)out + dec->offset);
301 
302 				found = true;
303 
304 				if (seen[decidx]) {
305 					/* duplicate field name */
306 					invalid = true;
307 				} else {
308 					seen[decidx] = true;
309 					if (dec->decode_func(v, field)) {
310 						invalid = true;
311 						/* keep going to fill out any other valid keys */
312 					}
313 				}
314 				break;
315 			}
316 		}
317 
318 		if (!found) {
319 			invalid = true;
320 		}
321 
322 		i += 1 + spdk_json_val_len(v);
323 	}
324 
325 	for (decidx = 0; decidx < num_decoders; decidx++) {
326 		if (!decoders[decidx].optional && !seen[decidx]) {
327 			/* required field is missing */
328 			invalid = true;
329 			break;
330 		}
331 	}
332 
333 	free(seen);
334 	return invalid ? -1 : 0;
335 }
336 
337 int
338 spdk_json_decode_array(const struct spdk_json_val *values, spdk_json_decode_fn decode_func,
339 		       void *out, size_t max_size, size_t *out_size, size_t stride)
340 {
341 	uint32_t i;
342 	char *field;
343 
344 	if (values == NULL || values->type != SPDK_JSON_VAL_ARRAY_BEGIN) {
345 		return -1;
346 	}
347 
348 	if (values->len > max_size) {
349 		return -1;
350 	}
351 
352 	*out_size = 0;
353 	field = out;
354 	for (i = 0; i < values->len;) {
355 		const struct spdk_json_val *v = &values[i + 1];
356 
357 		if (decode_func(v, field)) {
358 			return -1;
359 		}
360 
361 		i += spdk_json_val_len(v);
362 		field += stride;
363 		(*out_size)++;
364 	}
365 
366 	return 0;
367 }
368 
369 int
370 spdk_json_decode_bool(const struct spdk_json_val *val, void *out)
371 {
372 	bool *f = out;
373 
374 	if (val->type != SPDK_JSON_VAL_TRUE && val->type != SPDK_JSON_VAL_FALSE) {
375 		return -1;
376 	}
377 
378 	*f = val->type == SPDK_JSON_VAL_TRUE;
379 	return 0;
380 }
381 
382 int
383 spdk_json_decode_int32(const struct spdk_json_val *val, void *out)
384 {
385 	int32_t *i = out;
386 
387 	return spdk_json_number_to_int32(val, i);
388 }
389 
390 int
391 spdk_json_decode_uint32(const struct spdk_json_val *val, void *out)
392 {
393 	uint32_t *i = out;
394 
395 	return spdk_json_number_to_uint32(val, i);
396 }
397 
398 int
399 spdk_json_decode_uint64(const struct spdk_json_val *val, void *out)
400 {
401 	uint64_t *i = out;
402 
403 	return spdk_json_number_to_uint64(val, i);
404 }
405 
406 int
407 spdk_json_decode_string(const struct spdk_json_val *val, void *out)
408 {
409 	char **s = out;
410 
411 	free(*s);
412 
413 	*s = spdk_json_strdup(val);
414 
415 	if (*s) {
416 		return 0;
417 	} else {
418 		return -1;
419 	}
420 }
421