xref: /spdk/lib/json/json_util.c (revision 22898a91b9b6f289933db19b0175821cfb7e7820)
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 "spdk/json.h"
35 
36 #include "spdk_internal/utf.h"
37 
38 size_t
39 spdk_json_val_len(const struct spdk_json_val *val)
40 {
41 	if (val == NULL) {
42 		return 0;
43 	}
44 
45 	if (val->type == SPDK_JSON_VAL_ARRAY_BEGIN || val->type == SPDK_JSON_VAL_OBJECT_BEGIN) {
46 		return val->len + 2;
47 	}
48 
49 	return 1;
50 }
51 
52 bool
53 spdk_json_strequal(const struct spdk_json_val *val, const char *str)
54 {
55 	size_t len;
56 
57 	if (val->type != SPDK_JSON_VAL_STRING && val->type != SPDK_JSON_VAL_NAME) {
58 		return false;
59 	}
60 
61 	len = strlen(str);
62 	if (val->len != len) {
63 		return false;
64 	}
65 
66 	return memcmp(val->start, str, len) == 0;
67 }
68 
69 char *
70 spdk_json_strdup(const struct spdk_json_val *val)
71 {
72 	size_t len;
73 	char *s;
74 
75 	if (val->type != SPDK_JSON_VAL_STRING && val->type != SPDK_JSON_VAL_NAME) {
76 		return NULL;
77 	}
78 
79 	len = val->len;
80 
81 	if (memchr(val->start, '\0', len)) {
82 		/* String contains embedded NUL, so it is not a valid C string. */
83 		return NULL;
84 	}
85 
86 	s = malloc(len + 1);
87 	if (s == NULL) {
88 		return s;
89 	}
90 
91 	memcpy(s, val->start, len);
92 	s[len] = '\0';
93 
94 	return s;
95 }
96 
97 struct spdk_json_num {
98 	bool negative;
99 	uint64_t significand;
100 	int64_t exponent;
101 };
102 
103 static int
104 spdk_json_number_split(const struct spdk_json_val *val, struct spdk_json_num *num)
105 {
106 	const char *iter;
107 	size_t remaining;
108 	uint64_t *pval;
109 	uint64_t frac_digits = 0;
110 	uint64_t exponent_u64 = 0;
111 	bool exponent_negative = false;
112 	enum {
113 		NUM_STATE_INT,
114 		NUM_STATE_FRAC,
115 		NUM_STATE_EXP,
116 	} state;
117 
118 	memset(num, 0, sizeof(*num));
119 
120 	if (val->type != SPDK_JSON_VAL_NUMBER) {
121 		return -EINVAL;
122 	}
123 
124 	remaining = val->len;
125 	if (remaining == 0) {
126 		return -EINVAL;
127 	}
128 
129 	iter = val->start;
130 	if (*iter == '-') {
131 		num->negative = true;
132 		iter++;
133 		remaining--;
134 	}
135 
136 	state = NUM_STATE_INT;
137 	pval = &num->significand;
138 	while (remaining--) {
139 		char c = *iter++;
140 
141 		if (c == '.') {
142 			state = NUM_STATE_FRAC;
143 		} else if (c == 'e' || c == 'E') {
144 			state = NUM_STATE_EXP;
145 			pval = &exponent_u64;
146 		} else if (c == '-') {
147 			assert(state == NUM_STATE_EXP);
148 			exponent_negative = true;
149 		} else if (c == '+') {
150 			assert(state == NUM_STATE_EXP);
151 			/* exp_negative = false; */ /* already false by default */
152 		} else {
153 			uint64_t new_val;
154 
155 			assert(c >= '0' && c <= '9');
156 			new_val = *pval * 10 + c - '0';
157 			if (new_val < *pval) {
158 				return -ERANGE;
159 			}
160 
161 			if (state == NUM_STATE_FRAC) {
162 				frac_digits++;
163 			}
164 
165 			*pval = new_val;
166 		}
167 	}
168 
169 	if (exponent_negative) {
170 		if (exponent_u64 > 9223372036854775808ULL) { /* abs(INT64_MIN) */
171 			return -ERANGE;
172 		}
173 		num->exponent = (int64_t) - exponent_u64;
174 	} else {
175 		if (exponent_u64 > INT64_MAX) {
176 			return -ERANGE;
177 		}
178 		num->exponent = exponent_u64;
179 	}
180 	num->exponent -= frac_digits;
181 
182 	/* Apply as much of the exponent as possible without overflow or truncation */
183 	if (num->exponent < 0) {
184 		while (num->exponent && num->significand >= 10 && num->significand % 10 == 0) {
185 			num->significand /= 10;
186 			num->exponent++;
187 		}
188 	} else { /* positive exponent */
189 		while (num->exponent) {
190 			uint64_t new_val = num->significand * 10;
191 
192 			if (new_val < num->significand) {
193 				break;
194 			}
195 
196 			num->significand = new_val;
197 			num->exponent--;
198 		}
199 	}
200 
201 	return 0;
202 }
203 
204 int
205 spdk_json_number_to_int32(const struct spdk_json_val *val, int32_t *num)
206 {
207 	struct spdk_json_num split_num;
208 	int rc;
209 
210 	rc = spdk_json_number_split(val, &split_num);
211 	if (rc) {
212 		return rc;
213 	}
214 
215 	if (split_num.exponent) {
216 		return -ERANGE;
217 	}
218 
219 	if (split_num.negative) {
220 		if (split_num.significand > 2147483648) { /* abs(INT32_MIN) */
221 			return -ERANGE;
222 		}
223 		*num = (int32_t) - (int64_t)split_num.significand;
224 		return 0;
225 	}
226 
227 	/* positive */
228 	if (split_num.significand > INT32_MAX) {
229 		return -ERANGE;
230 	}
231 	*num = (int32_t)split_num.significand;
232 	return 0;
233 }
234 
235 int
236 spdk_json_number_to_uint32(const struct spdk_json_val *val, uint32_t *num)
237 {
238 	struct spdk_json_num split_num;
239 	int rc;
240 
241 	rc = spdk_json_number_split(val, &split_num);
242 	if (rc) {
243 		return rc;
244 	}
245 
246 	if (split_num.exponent || split_num.negative) {
247 		return -ERANGE;
248 	}
249 
250 	if (split_num.significand > UINT32_MAX) {
251 		return -ERANGE;
252 	}
253 	*num = (uint32_t)split_num.significand;
254 	return 0;
255 }
256 
257 int
258 spdk_json_number_to_uint64(const struct spdk_json_val *val, uint64_t *num)
259 {
260 	struct spdk_json_num split_num;
261 	int rc;
262 
263 	rc = spdk_json_number_split(val, &split_num);
264 	if (rc) {
265 		return rc;
266 	}
267 
268 	if (split_num.exponent || split_num.negative) {
269 		return -ERANGE;
270 	}
271 
272 	*num = split_num.significand;
273 	return 0;
274 }
275 
276 int
277 spdk_json_decode_object(const struct spdk_json_val *values,
278 			const struct spdk_json_object_decoder *decoders, size_t num_decoders, void *out)
279 {
280 	uint32_t i;
281 	bool invalid = false;
282 	size_t decidx;
283 	bool *seen;
284 
285 	if (values == NULL || values->type != SPDK_JSON_VAL_OBJECT_BEGIN) {
286 		return -1;
287 	}
288 
289 	seen = calloc(sizeof(bool), num_decoders);
290 	if (seen == NULL) {
291 		return -1;
292 	}
293 
294 	for (i = 0; i < values->len;) {
295 		const struct spdk_json_val *name = &values[i + 1];
296 		const struct spdk_json_val *v = &values[i + 2];
297 		bool found = false;
298 
299 		for (decidx = 0; decidx < num_decoders; decidx++) {
300 			const struct spdk_json_object_decoder *dec = &decoders[decidx];
301 			if (spdk_json_strequal(name, dec->name)) {
302 				void *field = (void *)((uintptr_t)out + dec->offset);
303 
304 				found = true;
305 
306 				if (seen[decidx]) {
307 					/* duplicate field name */
308 					invalid = true;
309 				} else {
310 					seen[decidx] = true;
311 					if (dec->decode_func(v, field)) {
312 						invalid = true;
313 						/* keep going to fill out any other valid keys */
314 					}
315 				}
316 				break;
317 			}
318 		}
319 
320 		if (!found) {
321 			invalid = true;
322 		}
323 
324 		i += 1 + spdk_json_val_len(v);
325 	}
326 
327 	for (decidx = 0; decidx < num_decoders; decidx++) {
328 		if (!decoders[decidx].optional && !seen[decidx]) {
329 			/* required field is missing */
330 			invalid = true;
331 			break;
332 		}
333 	}
334 
335 	free(seen);
336 	return invalid ? -1 : 0;
337 }
338 
339 int
340 spdk_json_decode_array(const struct spdk_json_val *values, spdk_json_decode_fn decode_func,
341 		       void *out, size_t max_size, size_t *out_size, size_t stride)
342 {
343 	uint32_t i;
344 	char *field;
345 	char *out_end;
346 
347 	if (values == NULL || values->type != SPDK_JSON_VAL_ARRAY_BEGIN) {
348 		return -1;
349 	}
350 
351 	*out_size = 0;
352 	field = out;
353 	out_end = field + max_size * stride;
354 	for (i = 0; i < values->len;) {
355 		const struct spdk_json_val *v = &values[i + 1];
356 
357 		if (field == out_end) {
358 			return -1;
359 		}
360 
361 		if (decode_func(v, field)) {
362 			return -1;
363 		}
364 
365 		i += spdk_json_val_len(v);
366 		field += stride;
367 		(*out_size)++;
368 	}
369 
370 	return 0;
371 }
372 
373 int
374 spdk_json_decode_bool(const struct spdk_json_val *val, void *out)
375 {
376 	bool *f = out;
377 
378 	if (val->type != SPDK_JSON_VAL_TRUE && val->type != SPDK_JSON_VAL_FALSE) {
379 		return -1;
380 	}
381 
382 	*f = val->type == SPDK_JSON_VAL_TRUE;
383 	return 0;
384 }
385 
386 int
387 spdk_json_decode_int32(const struct spdk_json_val *val, void *out)
388 {
389 	int32_t *i = out;
390 
391 	return spdk_json_number_to_int32(val, i);
392 }
393 
394 int
395 spdk_json_decode_uint32(const struct spdk_json_val *val, void *out)
396 {
397 	uint32_t *i = out;
398 
399 	return spdk_json_number_to_uint32(val, i);
400 }
401 
402 int
403 spdk_json_decode_uint64(const struct spdk_json_val *val, void *out)
404 {
405 	uint64_t *i = out;
406 
407 	return spdk_json_number_to_uint64(val, i);
408 }
409 
410 int
411 spdk_json_decode_string(const struct spdk_json_val *val, void *out)
412 {
413 	char **s = out;
414 
415 	free(*s);
416 
417 	*s = spdk_json_strdup(val);
418 
419 	if (*s) {
420 		return 0;
421 	} else {
422 		return -1;
423 	}
424 }
425