1*88771ae0Schristos /* $NetBSD: t_strtol.c,v 1.8 2024/07/22 16:41:05 christos Exp $ */ 22f29e266Sjruoho 32f29e266Sjruoho /*- 42f29e266Sjruoho * Copyright (c) 2011 The NetBSD Foundation, Inc. 52f29e266Sjruoho * All rights reserved. 62f29e266Sjruoho * 72f29e266Sjruoho * This code is derived from software contributed to The NetBSD Foundation 82f29e266Sjruoho * by Jukka Ruohonen. 92f29e266Sjruoho * 102f29e266Sjruoho * Redistribution and use in source and binary forms, with or without 112f29e266Sjruoho * modification, are permitted provided that the following conditions 122f29e266Sjruoho * are met: 132f29e266Sjruoho * 1. Redistributions of source code must retain the above copyright 142f29e266Sjruoho * notice, this list of conditions and the following disclaimer. 152f29e266Sjruoho * 2. Redistributions in binary form must reproduce the above copyright 162f29e266Sjruoho * notice, this list of conditions and the following disclaimer in the 172f29e266Sjruoho * documentation and/or other materials provided with the distribution. 182f29e266Sjruoho * 192f29e266Sjruoho * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 202f29e266Sjruoho * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 212f29e266Sjruoho * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 222f29e266Sjruoho * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 232f29e266Sjruoho * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 242f29e266Sjruoho * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 252f29e266Sjruoho * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 262f29e266Sjruoho * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 272f29e266Sjruoho * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 282f29e266Sjruoho * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 292f29e266Sjruoho * POSSIBILITY OF SUCH DAMAGE. 302f29e266Sjruoho */ 312f29e266Sjruoho 322f29e266Sjruoho #include <sys/cdefs.h> 33*88771ae0Schristos __RCSID("$NetBSD: t_strtol.c,v 1.8 2024/07/22 16:41:05 christos Exp $"); 342f29e266Sjruoho 352f29e266Sjruoho #include <atf-c.h> 362f29e266Sjruoho #include <errno.h> 37*88771ae0Schristos #include <inttypes.h> 382f29e266Sjruoho #include <stdlib.h> 392f29e266Sjruoho #include <string.h> 402f29e266Sjruoho #include <limits.h> 412f29e266Sjruoho 422f29e266Sjruoho struct test { 432f29e266Sjruoho const char *str; 44a4bc4192Sjruoho int64_t res; 452f29e266Sjruoho int base; 462f29e266Sjruoho const char *end; 472f29e266Sjruoho }; 482f29e266Sjruoho 492f29e266Sjruoho static void 50*88771ae0Schristos check(struct test *t, long int li, long long int lli, intmax_t ji, char *end) 512f29e266Sjruoho { 522f29e266Sjruoho 532f29e266Sjruoho if (li != -1 && li != t->res) 542f29e266Sjruoho atf_tc_fail_nonfatal("strtol(%s, &end, %d) failed " 552f29e266Sjruoho "(rv = %ld)", t->str, t->base, li); 562f29e266Sjruoho 570202e776Sjruoho if (lli != -1 && lli != t->res) 582f29e266Sjruoho atf_tc_fail_nonfatal("strtoll(%s, NULL, %d) failed " 592f29e266Sjruoho "(rv = %lld)", t->str, t->base, lli); 602f29e266Sjruoho 61*88771ae0Schristos if (ji != -1 && ji != t->res) 62*88771ae0Schristos atf_tc_fail_nonfatal("strtoll(%s, NULL, %d) failed " 63*88771ae0Schristos "(rv = %jd)", t->str, t->base, ji); 64*88771ae0Schristos 659458f2beSpgoyette if ((t->end != NULL && strcmp(t->end, end) != 0) || 669458f2beSpgoyette (t->end == NULL && *end != '\0')) 67d88dcd0fSjoerg atf_tc_fail_nonfatal("invalid end pointer (%p) from " 68d88dcd0fSjoerg "strtol(%p, &end, %d)", end, t->str, t->base); 692f29e266Sjruoho } 702f29e266Sjruoho 712f29e266Sjruoho ATF_TC(strtol_base); 722f29e266Sjruoho ATF_TC_HEAD(strtol_base, tc) 732f29e266Sjruoho { 742f29e266Sjruoho atf_tc_set_md_var(tc, "descr", "Test strtol(3) with different bases"); 752f29e266Sjruoho } 762f29e266Sjruoho 772f29e266Sjruoho ATF_TC_BODY(strtol_base, tc) 782f29e266Sjruoho { 792f29e266Sjruoho struct test t[] = { 802f29e266Sjruoho { "123456789", 123456789, 0, NULL }, 812f29e266Sjruoho { "111010110111100110100010101", 123456789, 2, NULL }, 822f29e266Sjruoho { "22121022020212200", 123456789, 3, NULL }, 832f29e266Sjruoho { "13112330310111", 123456789, 4, NULL }, 842f29e266Sjruoho { "223101104124", 123456789, 5, NULL }, 852f29e266Sjruoho { "20130035113", 123456789, 6, NULL }, 862f29e266Sjruoho { "3026236221", 123456789, 7, NULL }, 872f29e266Sjruoho { "726746425", 123456789, 8, NULL }, 882f29e266Sjruoho { "277266780", 123456789, 9, NULL }, 892f29e266Sjruoho { "123456789", 123456789, 10, NULL }, 902f29e266Sjruoho { "63762A05", 123456789, 11, NULL }, 912f29e266Sjruoho { "35418A99", 123456789, 12, NULL }, 922f29e266Sjruoho { "1C767471", 123456789, 13, NULL }, 932f29e266Sjruoho { "12579781", 123456789, 14, NULL }, 942f29e266Sjruoho { "AC89BC9", 123456789, 15, NULL }, 952f29e266Sjruoho { "75BCD15", 123456789, 16, NULL }, 969458f2beSpgoyette { "1234567", 342391, 8, NULL }, 979458f2beSpgoyette { "01234567", 342391, 0, NULL }, 982f29e266Sjruoho { "0123456789", 123456789, 10, NULL }, 992f29e266Sjruoho { "0x75bcd15", 123456789, 0, NULL }, 100d88dcd0fSjoerg { " 0xX", 0, 0, "xX" }, 101d88dcd0fSjoerg { " 0xX", 0, 16, "xX" }, 102d88dcd0fSjoerg { " 0XX", 0, 0, "XX" }, 103d88dcd0fSjoerg { " 0XX", 0, 16, "XX" }, 1042f29e266Sjruoho }; 1052f29e266Sjruoho 1062f29e266Sjruoho long long int lli; 1072f29e266Sjruoho long int li; 108*88771ae0Schristos intmax_t ji; 109d88dcd0fSjoerg long long int ulli; 110d88dcd0fSjoerg long int uli; 111*88771ae0Schristos uintmax_t uji; 112d88dcd0fSjoerg char *end, *end2; 1132f29e266Sjruoho size_t i; 1142f29e266Sjruoho 1152f29e266Sjruoho for (i = 0; i < __arraycount(t); i++) { 1162f29e266Sjruoho 1172f29e266Sjruoho li = strtol(t[i].str, &end, t[i].base); 1182f29e266Sjruoho lli = strtoll(t[i].str, NULL, t[i].base); 119*88771ae0Schristos ji = strtoimax(t[i].str, NULL, t[i].base); 1202f29e266Sjruoho 121d88dcd0fSjoerg uli = strtoul(t[i].str, &end2, t[i].base); 122d88dcd0fSjoerg ulli = strtoull(t[i].str, NULL, t[i].base); 123*88771ae0Schristos uji = strtoumax(t[i].str, NULL, t[i].base); 124d88dcd0fSjoerg 125*88771ae0Schristos check(&t[i], li, lli, ji, end); 126d88dcd0fSjoerg 127d88dcd0fSjoerg if (li != uli) 128d88dcd0fSjoerg atf_tc_fail_nonfatal("strtoul(%s, NULL, %d) failed " 129d88dcd0fSjoerg "(rv = %lu)", t[i].str, t[i].base, uli); 130d88dcd0fSjoerg if (lli != ulli) 131d88dcd0fSjoerg atf_tc_fail_nonfatal("strtoull(%s, NULL, %d) failed " 132d88dcd0fSjoerg "(rv = %llu)", t[i].str, t[i].base, ulli); 133*88771ae0Schristos if ((uintmax_t)ji != uji) 134*88771ae0Schristos atf_tc_fail_nonfatal("strtoumax(%s, NULL, %d) failed " 135*88771ae0Schristos "(rv = %ju)", t[i].str, t[i].base, uji); 136*88771ae0Schristos if (end != end2) 137*88771ae0Schristos atf_tc_fail_nonfatal("invalid end pointer ('%p') from " 138*88771ae0Schristos "strtoul(%s, &end, %d)", end2, t[i].str, t[i].base); 1392f29e266Sjruoho } 1402f29e266Sjruoho } 1412f29e266Sjruoho 142*88771ae0Schristos ATF_TC(strtol_invbase); 143*88771ae0Schristos ATF_TC_HEAD(strtol_invbase, tc) 144*88771ae0Schristos { 145*88771ae0Schristos atf_tc_set_md_var(tc, "descr", "Test strtol(3) with an invalid base"); 146*88771ae0Schristos } 147*88771ae0Schristos 148*88771ae0Schristos ATF_TC_BODY(strtol_invbase, tc) 149*88771ae0Schristos { 150*88771ae0Schristos long long int lli; 151*88771ae0Schristos long int li; 152*88771ae0Schristos intmax_t ji; 153*88771ae0Schristos long long int ulli; 154*88771ae0Schristos long int uli; 155*88771ae0Schristos uintmax_t uji; 156*88771ae0Schristos char *end; 157*88771ae0Schristos char boo[] = "boo"; 158*88771ae0Schristos const char str[] = "1"; 159*88771ae0Schristos 160*88771ae0Schristos #define CHECK(r, f, fun) \ 161*88771ae0Schristos end = boo; \ 162*88771ae0Schristos r = fun(str, &end, -2); \ 163*88771ae0Schristos if (strcmp(str, end) != 0) \ 164*88771ae0Schristos atf_tc_fail_nonfatal( \ 165*88771ae0Schristos "%s(1, boo, -2) failed endptr=%s ", # fun, end); \ 166*88771ae0Schristos if (r) \ 167*88771ae0Schristos atf_tc_fail_nonfatal( \ 168*88771ae0Schristos "%s(1, boo, -2) failed rv=" f, # fun, r); \ 169*88771ae0Schristos if (errno != EINVAL) \ 170*88771ae0Schristos atf_tc_fail_nonfatal( \ 171*88771ae0Schristos "%s(1, boo, -2) failed errno=%d", # fun, errno) 172*88771ae0Schristos 173*88771ae0Schristos CHECK(li, "%ld", strtol); 174*88771ae0Schristos CHECK(lli, "%lld", strtoll); 175*88771ae0Schristos CHECK(ji, "%jd", strtoimax); 176*88771ae0Schristos CHECK(uli, "%lu", strtoul); 177*88771ae0Schristos CHECK(ulli, "%llu", strtoull); 178*88771ae0Schristos CHECK(uji, "%ju", strtoumax); 179*88771ae0Schristos } 180*88771ae0Schristos 1812f29e266Sjruoho ATF_TC(strtol_case); 1822f29e266Sjruoho ATF_TC_HEAD(strtol_case, tc) 1832f29e266Sjruoho { 1842f29e266Sjruoho atf_tc_set_md_var(tc, "descr", "Case insensitivity with strtol(3)"); 1852f29e266Sjruoho } 1862f29e266Sjruoho 1872f29e266Sjruoho ATF_TC_BODY(strtol_case, tc) 1882f29e266Sjruoho { 1892f29e266Sjruoho struct test t[] = { 1902f29e266Sjruoho { "abcd", 0xabcd, 16, NULL }, 1912f29e266Sjruoho { " dcba", 0xdcba, 16, NULL }, 1922f29e266Sjruoho { "abcd dcba", 0xabcd, 16, " dcba" }, 1939458f2beSpgoyette { "abc0x123", 0xabc0, 16, "x123" }, 1942f29e266Sjruoho { "abcd\0x123", 0xabcd, 16, "\0x123" }, 1952f29e266Sjruoho { "ABCD", 0xabcd, 16, NULL }, 1962f29e266Sjruoho { "aBcD", 0xabcd, 16, NULL }, 1972f29e266Sjruoho { "0xABCD", 0xabcd, 16, NULL }, 1982f29e266Sjruoho { "0xABCDX", 0xabcd, 16, "X" }, 1992f29e266Sjruoho }; 2002f29e266Sjruoho 2012f29e266Sjruoho long long int lli; 2022f29e266Sjruoho long int li; 203*88771ae0Schristos intmax_t ji; 2042f29e266Sjruoho char *end; 2052f29e266Sjruoho size_t i; 2062f29e266Sjruoho 2072f29e266Sjruoho for (i = 0; i < __arraycount(t); i++) { 2082f29e266Sjruoho 2092f29e266Sjruoho li = strtol(t[i].str, &end, t[i].base); 2102f29e266Sjruoho lli = strtoll(t[i].str, NULL, t[i].base); 211*88771ae0Schristos ji = strtoimax(t[i].str, NULL, t[i].base); 2122f29e266Sjruoho 213*88771ae0Schristos check(&t[i], li, lli, ji, end); 2142f29e266Sjruoho } 2152f29e266Sjruoho } 2162f29e266Sjruoho 2172f29e266Sjruoho ATF_TC(strtol_range); 2182f29e266Sjruoho ATF_TC_HEAD(strtol_range, tc) 2192f29e266Sjruoho { 2202f29e266Sjruoho atf_tc_set_md_var(tc, "descr", "Test ERANGE from strtol(3)"); 2212f29e266Sjruoho } 2222f29e266Sjruoho 2232f29e266Sjruoho ATF_TC_BODY(strtol_range, tc) 2242f29e266Sjruoho { 2252f29e266Sjruoho 2262f29e266Sjruoho #if LONG_MAX == 0x7fffffff /* XXX: Is this portable? */ 2272f29e266Sjruoho 2282f29e266Sjruoho struct test t[] = { 2292f29e266Sjruoho { "20000000000", 2147483647, 8, NULL }, 2302f29e266Sjruoho { "2147483648", 2147483647, 10, NULL }, 2312f29e266Sjruoho { "80000000", 2147483647, 16, NULL }, 2322f29e266Sjruoho }; 2332f29e266Sjruoho #else 2342f29e266Sjruoho struct test t[] = { 2352f29e266Sjruoho { "1000000000000000000000", 9223372036854775807, 8, NULL }, 2362f29e266Sjruoho { "9223372036854775808", 9223372036854775807, 10, NULL }, 2372f29e266Sjruoho { "8000000000000000", 9223372036854775807, 16, NULL }, 2382f29e266Sjruoho }; 2392f29e266Sjruoho #endif 2402f29e266Sjruoho 2412f29e266Sjruoho long int li; 2422f29e266Sjruoho char *end; 2432f29e266Sjruoho size_t i; 2442f29e266Sjruoho 2452f29e266Sjruoho for (i = 0; i < __arraycount(t); i++) { 2462f29e266Sjruoho 2472f29e266Sjruoho errno = 0; 2482f29e266Sjruoho li = strtol(t[i].str, &end, t[i].base); 2492f29e266Sjruoho 2502f29e266Sjruoho if (errno != ERANGE) 2512f29e266Sjruoho atf_tc_fail("strtol(3) did not catch ERANGE"); 2522f29e266Sjruoho 253*88771ae0Schristos check(&t[i], li, -1, -1, end); 2542f29e266Sjruoho } 2552f29e266Sjruoho } 2562f29e266Sjruoho 2572f29e266Sjruoho ATF_TC(strtol_signed); 2582f29e266Sjruoho ATF_TC_HEAD(strtol_signed, tc) 2592f29e266Sjruoho { 2602f29e266Sjruoho atf_tc_set_md_var(tc, "descr", "A basic test of strtol(3)"); 2612f29e266Sjruoho } 2622f29e266Sjruoho 2632f29e266Sjruoho ATF_TC_BODY(strtol_signed, tc) 2642f29e266Sjruoho { 2652f29e266Sjruoho struct test t[] = { 2662f29e266Sjruoho { "1", 1, 0, NULL }, 2672f29e266Sjruoho { " 2", 2, 0, NULL }, 2682f29e266Sjruoho { " 3", 3, 0, NULL }, 2692f29e266Sjruoho { " -3", -3, 0, NULL }, 2702f29e266Sjruoho { "--1", 0, 0, "--1" }, 2712f29e266Sjruoho { "+-2", 0, 0, "+-2" }, 2722f29e266Sjruoho { "++3", 0, 0, "++3" }, 2732f29e266Sjruoho { "+9", 9, 0, NULL }, 2742f29e266Sjruoho { "+123", 123, 0, NULL }, 2752f29e266Sjruoho { "-1 3", -1, 0, " 3" }, 2762f29e266Sjruoho { "-1.3", -1, 0, ".3" }, 2772f29e266Sjruoho { "- 3", 0, 0, "- 3" }, 2782f29e266Sjruoho { "+33.", 33, 0, "." }, 2792f29e266Sjruoho { "30x0", 30, 0, "x0" }, 2802f29e266Sjruoho }; 2812f29e266Sjruoho 2822f29e266Sjruoho long long int lli; 2832f29e266Sjruoho long int li; 284*88771ae0Schristos intmax_t ji; 2852f29e266Sjruoho char *end; 2862f29e266Sjruoho size_t i; 2872f29e266Sjruoho 2882f29e266Sjruoho for (i = 0; i < __arraycount(t); i++) { 2892f29e266Sjruoho 2902f29e266Sjruoho li = strtol(t[i].str, &end, t[i].base); 2912f29e266Sjruoho lli = strtoll(t[i].str, NULL, t[i].base); 292*88771ae0Schristos ji = strtoimax(t[i].str, NULL, t[i].base); 2932f29e266Sjruoho 294*88771ae0Schristos check(&t[i], li, lli, ji, end); 2952f29e266Sjruoho } 2962f29e266Sjruoho } 2972f29e266Sjruoho 2982f29e266Sjruoho ATF_TP_ADD_TCS(tp) 2992f29e266Sjruoho { 3002f29e266Sjruoho 301*88771ae0Schristos ATF_TP_ADD_TC(tp, strtol_invbase); 3022f29e266Sjruoho ATF_TP_ADD_TC(tp, strtol_base); 3032f29e266Sjruoho ATF_TP_ADD_TC(tp, strtol_case); 3042f29e266Sjruoho ATF_TP_ADD_TC(tp, strtol_range); 3052f29e266Sjruoho ATF_TP_ADD_TC(tp, strtol_signed); 3062f29e266Sjruoho 3072f29e266Sjruoho return atf_no_error(); 3082f29e266Sjruoho } 309