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