xref: /netbsd-src/external/mpl/bind/dist/lib/isc/parseint.c (revision a04395531661c5e8d314125d5ae77d4cbedd5d73)
1 /*	$NetBSD: parseint.c,v 1.5 2021/02/19 16:42:19 christos Exp $	*/
2 
3 /*
4  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
5  *
6  * This Source Code Form is subject to the terms of the Mozilla Public
7  * License, v. 2.0. If a copy of the MPL was not distributed with this
8  * file, you can obtain one at https://mozilla.org/MPL/2.0/.
9  *
10  * See the COPYRIGHT file distributed with this work for additional
11  * information regarding copyright ownership.
12  */
13 
14 /*! \file */
15 
16 #include <ctype.h>
17 #include <errno.h>
18 #include <inttypes.h>
19 #include <limits.h>
20 #include <stdlib.h>
21 
22 #include <isc/parseint.h>
23 #include <isc/result.h>
24 
25 isc_result_t
26 isc_parse_uint32(uint32_t *uip, const char *string, int base) {
27 	unsigned long n;
28 	uint32_t r;
29 	char *e;
30 	if (!isalnum((unsigned char)(string[0]))) {
31 		return (ISC_R_BADNUMBER);
32 	}
33 	errno = 0;
34 	n = strtoul(string, &e, base);
35 	if (*e != '\0') {
36 		return (ISC_R_BADNUMBER);
37 	}
38 	/*
39 	 * Where long is 64 bits we need to convert to 32 bits then test for
40 	 * equality.  This is a no-op on 32 bit machines and a good compiler
41 	 * will optimise it away.
42 	 */
43 	r = (uint32_t)n;
44 	if ((n == ULONG_MAX && errno == ERANGE) || (n != (unsigned long)r)) {
45 		return (ISC_R_RANGE);
46 	}
47 	*uip = r;
48 	return (ISC_R_SUCCESS);
49 }
50 
51 isc_result_t
52 isc_parse_uint16(uint16_t *uip, const char *string, int base) {
53 	uint32_t val;
54 	isc_result_t result;
55 	result = isc_parse_uint32(&val, string, base);
56 	if (result != ISC_R_SUCCESS) {
57 		return (result);
58 	}
59 	if (val > 0xFFFF) {
60 		return (ISC_R_RANGE);
61 	}
62 	*uip = (uint16_t)val;
63 	return (ISC_R_SUCCESS);
64 }
65 
66 isc_result_t
67 isc_parse_uint8(uint8_t *uip, const char *string, int base) {
68 	uint32_t val;
69 	isc_result_t result;
70 	result = isc_parse_uint32(&val, string, base);
71 	if (result != ISC_R_SUCCESS) {
72 		return (result);
73 	}
74 	if (val > 0xFF) {
75 		return (ISC_R_RANGE);
76 	}
77 	*uip = (uint8_t)val;
78 	return (ISC_R_SUCCESS);
79 }
80