From: Roy Marples Date: Sat, 31 Jan 2015 01:02:07 +0000 (+0000) Subject: Use strtoi(3) and strtou(3) from NetBSD-8 instead of the harder to use X-Git-Tag: v6.8.0~106 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f94b4eab068a6c0c1a9cdf61113e8a508632cc51;p=thirdparty%2Fdhcpcd.git Use strtoi(3) and strtou(3) from NetBSD-8 instead of the harder to use strtol(3) calls. Add shims around strtoimax(3) and strtoumax(3) when these functions are not available. --- diff --git a/compat/strtoi.c b/compat/strtoi.c new file mode 100644 index 00000000..701d57b3 --- /dev/null +++ b/compat/strtoi.c @@ -0,0 +1,112 @@ +/* + * dhcpcd - DHCP client daemon + * Copyright (c) 2006-2015 Roy Marples + * All rights reserved + + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include + +#include "strtoi.h" + +intmax_t +strtoi(const char * __restrict nptr, char ** __restrict endptr, int base, + intmax_t lo, intmax_t hi, int *rstatus) +{ + int serrno; + intmax_t r; + char *ep; + int rep; + + if (endptr == NULL) + endptr = &ep; + if (rstatus == NULL) + rstatus = &rep; + + serrno = errno; + errno = 0; + r = strtoimax(nptr, endptr, base); + *rstatus = errno; + errno = serrno; + + if (*rstatus == 0) { + if (nptr == *endptr) + *rstatus = ECANCELED; + else if (**endptr != '\0') + *rstatus = ENOTSUP; + } + + if (r < lo) { + if (*rstatus == 0) + *rstatus = ERANGE; + return lo; + } + if (r > hi) { + if (*rstatus == 0) + *rstatus = ERANGE; + return hi; + } + return r; +} + +uintmax_t +strtou(const char * __restrict nptr, char ** __restrict endptr, int base, + uintmax_t lo, uintmax_t hi, int *rstatus) +{ + int serrno; + uintmax_t r; + char *ep; + int rep; + + if (endptr == NULL) + endptr = &ep; + if (rstatus == NULL) + rstatus = &rep; + + serrno = errno; + errno = 0; + r = strtoumax(nptr, endptr, base); + *rstatus = errno; + errno = serrno; + + if (*rstatus == 0) { + if (nptr == *endptr) + *rstatus = ECANCELED; + else if (**endptr != '\0') + *rstatus = ENOTSUP; + } + + if (r < lo) { + if (*rstatus == 0) + *rstatus = ERANGE; + return lo; + } + if (r > hi) { + if (*rstatus == 0) + *rstatus = ERANGE; + return hi; + } + return r; +} diff --git a/compat/strtoi.h b/compat/strtoi.h new file mode 100644 index 00000000..69eb2643 --- /dev/null +++ b/compat/strtoi.h @@ -0,0 +1,35 @@ +/* + * dhcpcd - DHCP client daemon + * Copyright (c) 2006-2015 Roy Marples + * All rights reserved + + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef STRTOI_H +#define STRTOI_H + +intmax_t strtoi(const char * __restrict nptr, char ** __restrict endptr, + int base, intmax_t lo, intmax_t hi, int *rstatus); +uintmax_t strtou(const char * __restrict nptr, char ** __restrict endptr, + int base, uintmax_t lo, uintmax_t hi, int *rstatus); +#endif diff --git a/configure b/configure index bac56d7a..cf91a171 100755 --- a/configure +++ b/configure @@ -636,6 +636,30 @@ if [ "$STRLCPY" = no ]; then echo "#include \"compat/strlcpy.h\"" >>$CONFIG_H fi +if [ -z "$STRTOI" ]; then + printf "Testing for strtoi ... " + cat <_strtoi.c +#include +#include +#include +int main(void) { + int e; + return strtoi("1234", NULL, 0, 0, INT32_MAX, &e); +} +EOF + if $XCC _strtoi.c -o _strtoi 2>&3; then + STRTOI=yes + else + STRTOI=no + fi + echo "$STRTOI" + rm -f _strtoi.c _strtoi +fi +if [ "$STRTOI" = no ]; then + echo "COMPAT_SRCS+= compat/strtoi.c" >>$CONFIG_MK + echo "#include \"compat/strtoi.h\"" >>$CONFIG_H +fi + if [ -z "$DPRINTF" ]; then printf "Testing for dprintf ... " cat <_dprintf.c diff --git a/dhcp-common.c b/dhcp-common.c index 3eb1b172..109120f1 100644 --- a/dhcp-common.c +++ b/dhcp-common.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -152,9 +153,9 @@ make_option_mask(const struct dhcp_opt *dopts, size_t dopts_len, const struct dhcp_opt *odopts, size_t odopts_len, uint8_t *mask, const char *opts, int add) { - char *token, *o, *p, *t; + char *token, *o, *p; const struct dhcp_opt *opt; - int match; + int match, e; unsigned int n; size_t i; @@ -169,11 +170,10 @@ make_option_mask(const struct dhcp_opt *dopts, size_t dopts_len, if (strcmp(opt->var, token) == 0) match = 1; else { - errno = 0; - n = (unsigned int)strtol(token, &t, 0); - if (errno == 0 && !*t) - if (opt->option == n) - match = 1; + n = (unsigned int)strtou(token, NULL, 0, + 0, UINT_MAX, &e); + if (e == 0 && opt->option == n) + match = 1; } if (match) break; @@ -183,11 +183,10 @@ make_option_mask(const struct dhcp_opt *dopts, size_t dopts_len, if (strcmp(opt->var, token) == 0) match = 1; else { - errno = 0; - n = (unsigned int)strtol(token, &t, 0); - if (errno == 0 && !*t) - if (opt->option == n) - match = 1; + n = (unsigned int)strtou(token, NULL, 0, + 0, UINT_MAX, &e); + if (e == 0 && opt->option == n) + match = 1; } if (match) break; diff --git a/if-options.c b/if-options.c index 86b0a12b..3afd8e9d 100644 --- a/if-options.c +++ b/if-options.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -189,26 +190,6 @@ const struct option cf_options[] = { {NULL, 0, NULL, '\0'} }; -static int -atoint(const char *s) -{ - char *t; - long n; - - errno = 0; - n = strtol(s, &t, 0); - if ((errno != 0 && n == 0) || s == t || - (errno == ERANGE && (n == LONG_MAX || n == LONG_MIN))) - { - if (errno == 0) - errno = EINVAL; - syslog(LOG_ERR, "`%s' out of range", s); - return -1; - } - - return (int)n; -} - static char * add_environ(struct if_options *ifo, const char *value, int uniq) { @@ -402,19 +383,15 @@ parse_string_hwaddr(char *sbuf, size_t slen, const char *str, int clid) static int parse_iaid1(uint8_t *iaid, const char *arg, size_t len, int n) { - unsigned long l; + int e; + uint32_t narg; ssize_t s; - uint32_t u32; - char *np; - errno = 0; - l = strtoul(arg, &np, 0); - if (l <= (unsigned long)UINT32_MAX && errno == 0 && *np == '\0') { + narg = (uint32_t)strtou(arg, NULL, 0, 0, UINT32_MAX, &e); + if (e == 0) { if (n) - u32 = htonl((uint32_t)l); - else - u32 = (uint32_t)l; - memcpy(iaid, &u32, sizeof(u32)); + narg = htonl(narg); + memcpy(iaid, &narg, sizeof(narg)); return 0; } @@ -644,7 +621,7 @@ static int parse_option(struct dhcpcd_ctx *ctx, const char *ifname, struct if_options *ifo, int opt, const char *arg, struct dhcp_opt **ldop, struct dhcp_opt **edop) { - int i, t; + int e, i, t; long l; unsigned long u; char *p = NULL, *fp, *np, **nconf; @@ -734,22 +711,17 @@ parse_option(struct dhcpcd_ctx *ctx, const char *ifname, struct if_options *ifo, ifo->options |= DHCPCD_RELEASE; break; case 'l': - if (*arg == '-') { - syslog(LOG_ERR, - "leasetime must be a positive value"); - return -1; - } - errno = 0; - ifo->leasetime = (uint32_t)strtoul(arg, NULL, 0); - if (errno == EINVAL || errno == ERANGE) { - syslog(LOG_ERR, "`%s' out of range", arg); + ifo->leasetime = (uint32_t)strtou(arg, NULL, + 0, 0, UINT32_MAX, &e); + if (e) { + syslog(LOG_ERR, "failed to convert leasetime %s", arg); return -1; } break; case 'm': - ifo->metric = atoint(arg); - if (ifo->metric < 0) { - syslog(LOG_ERR, "metric must be a positive value"); + ifo->metric = (int)strtoi(arg, NULL, 0, 0, INT32_MAX, &e); + if (e) { + syslog(LOG_ERR, "failed to convert metric %s", arg); return -1; } break; @@ -806,9 +778,9 @@ parse_option(struct dhcpcd_ctx *ctx, const char *ifname, struct if_options *ifo, ifo->options &= ~(DHCPCD_ARP | DHCPCD_STATIC); break; case 't': - ifo->timeout = atoint(arg); - if (ifo->timeout < 0) { - syslog(LOG_ERR, "timeout must be a positive value"); + ifo->timeout = (time_t)strtoi(arg, NULL, 0, 0, INT32_MAX, &e); + if (e) { + syslog(LOG_ERR, "failed to convert timeout"); return -1; } break; @@ -853,8 +825,8 @@ parse_option(struct dhcpcd_ctx *ctx, const char *ifname, struct if_options *ifo, } /* No need to strip the comma */ - i = atoint(arg); - if (i < 1 || i > 254) { + i = (int)strtoi(arg, NULL, 0, 1, 254, &e); + if (e) { syslog(LOG_ERR, "vendor option should be between" " 1 and 254 inclusive"); return -1; @@ -895,9 +867,9 @@ parse_option(struct dhcpcd_ctx *ctx, const char *ifname, struct if_options *ifo, } break; case 'y': - ifo->reboot = atoint(arg); - if (ifo->reboot < 0) { - syslog(LOG_ERR, "reboot must be a positive value"); + ifo->reboot = (time_t)strtoi(arg, NULL, 0, 0, UINT32_MAX, &e); + if (e) { + syslog(LOG_ERR, "failed to convert reboot %s", arg); return -1; } break; @@ -1332,13 +1304,12 @@ parse_option(struct dhcpcd_ctx *ctx, const char *ifname, struct if_options *ifo, memset(&ia->addr, 0, sizeof(ia->addr)); } if (p && ia->ia_type == D6_OPTION_IA_PD) { - i = atoint(p); - if (i != -1 && (i < 8 || i > 120)) { - errno = EINVAL; - i = -1; - } - if (i == -1) { - syslog(LOG_ERR, "%s: %m", p); + i = (int)strtoi(p, NULL, 0, 8, 120, &e); + if (e) { + syslog(LOG_ERR, + "%s: failed to convert" + " prefix len", + p); ia->prefix_len = 0; } else ia->prefix_len = (uint8_t)i; @@ -1382,11 +1353,15 @@ parse_option(struct dhcpcd_ctx *ctx, const char *ifname, struct if_options *ifo, if (*p == '\0') sla->sla_set = 0; else { - errno = 0; - i = atoint(p); - if (i == -1) + sla->sla = (uint32_t)strtou(p, NULL, + 0, 0, UINT32_MAX, &e); + sla->sla_set = 1; + if (e) { + syslog(LOG_ERR, + "%s: failed to convert sla", + ifname); goto err_sla; - sla->sla = (uint32_t)i; + } if (sla->sla == 0 && ia->sla_len > 1) { syslog(LOG_ERR, "%s: cannot" " assign multiple prefixes" @@ -1394,15 +1369,16 @@ parse_option(struct dhcpcd_ctx *ctx, const char *ifname, struct if_options *ifo, ifname); goto err_sla; } - sla->sla_set = 1; - if (errno) - goto err_sla; } if (np) { - i = atoint(np); - if (i < 0 || i > 128) + sla->prefix_len = (uint8_t)strtoi(np, + NULL, 0, 0, 128, &e); + if (e) { + syslog(LOG_ERR, "%s: failed to " + "convert prefix len", + ifname); goto err_sla; - sla->prefix_len = (uint8_t)i; + } } else sla->prefix_len = 0; } else { @@ -1505,9 +1481,8 @@ err_sla: return -1; } *fp++ = '\0'; - errno = 0; - u = strtoul(arg, &np, 0); - if (u > UINT32_MAX || errno != 0 || *np != '\0') { + u = strtou(arg, NULL, 0, 0, UINT32_MAX, &e); + if (e) { syslog(LOG_ERR, "invalid code: %s", arg); return -1; } @@ -1525,8 +1500,11 @@ err_sla: /* length */ if (np) { *np++ = '\0'; - if ((l = atoint(np)) == -1) + l = (long)strtou(np, NULL, 0, 0, LONG_MAX, &e); + if (e) { + syslog(LOG_ERR, "failed to convert length"); return -1; + } } else l = 0; t = 0; @@ -1685,9 +1663,8 @@ err_sla: fp = strwhite(arg); if (fp) *fp++ = '\0'; - errno = 0; - u = strtoul(arg, &np, 0); - if (u > UINT32_MAX || errno != 0 || *np != '\0') { + u = (uint32_t)strtou(arg, NULL, 0, 0, UINT32_MAX, &e); + if (e) { syslog(LOG_ERR, "invalid code: %s", arg); return -1; }