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