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