From c32c317f7ecfe5af5da64be4c8cac8d87db04654 Mon Sep 17 00:00:00 2001 From: Thomas Habets Date: Wed, 26 Oct 2022 21:09:16 +0100 Subject: Parse -wW strictly as float --- src/arping.c | 49 +++++++++++++++++++++++++++++++++++++--- src/arping_test.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 113 insertions(+), 3 deletions(-) diff --git a/src/arping.c b/src/arping.c index a2717cd..d09b9ec 100644 --- a/src/arping.c +++ b/src/arping.c @@ -238,6 +238,32 @@ int verbose = 0; /* Increase with -v */ /* Doesn't really need to be volatile, but doesn't hurt. */ static volatile sig_atomic_t time_to_die = 0; +static float +must_parse_float(const char* in, const char* what) +{ + if (!*in) { + fprintf(stderr, "arping: %s: value was empty\n", what); + exit(1); + } + char *endp = NULL; + errno = 0; + // Maybe need to use strtod() instead? It's in C89, whereas + // looks like strtof() is in POSIX.1-2001, POSIX.1-2008, C99. + const float ret = strtof(in, &endp); + if (errno) { + fprintf(stderr, "arping: %s: parsing <%s> as float: %s\n", + what, in, strerror(errno)); + exit(1); + } + if (*endp) { + fprintf(stderr, + "arping: %s: failed parsing <%s> as float\n", + what, in); + exit(1); + } + return ret; +} + static int must_parse_int(const char* in, const char* what) { @@ -2111,11 +2137,28 @@ arping_main(int argc, char **argv) } break; case 'w': - deadline = atof(optarg); + deadline = must_parse_float(optarg, "deadline (-w)"); + if (deadline < 0) { + fprintf(stderr, + "arping: deadline (-w) must be >=0. Is %f\n", + deadline); + exit(1); + } break; - case 'W': - packetwait = (unsigned)(1000000.0 * atof(optarg)); + case 'W': { + const float val = must_parse_float(optarg, + "packetwait (-W)"); + // TODO: range check into unsigned. + // Also turns out zero doesn't work. + packetwait = (unsigned)(1000000.0 * val); + if (val < 0) { + fprintf(stderr, + "arping: packetwait (-W) must be >=0. Is %f\n", + val); + exit(1); + } break; + } case 'z': use_seccomp = 1; break; diff --git a/src/arping_test.c b/src/arping_test.c index 9166c54..9db2d60 100644 --- a/src/arping_test.c +++ b/src/arping_test.c @@ -497,6 +497,7 @@ START_TEST(badarg_maxcount_neg) char* args[] = { "arping", "-c", "-1", + "-h", // To exit cleanly. "dummy", NULL }; @@ -508,6 +509,19 @@ START_TEST(badarg_maxcount_nan) char* args[] = { "arping", "-c", "number", + "-h", // To exit cleanly. + "dummy", + NULL + }; + arping_main(sizeof(args)/sizeof(char*)-1, args); +} + +START_TEST(badarg_maxcount_range) +{ + char* args[] = { + "arping", + "-c", "100000000000000000000000000000", + "-h", // To exit cleanly. "dummy", NULL }; @@ -538,6 +552,54 @@ START_TEST(arg_maxcount_hex) arping_main(sizeof(args)/sizeof(char*)-1, args); } +START_TEST(badarg_packetwait_neg) +{ + char* args[] = { + "arping", + "-W", "-1", + "-h", // To exit cleanly. + "dummy", + NULL + }; + arping_main(sizeof(args)/sizeof(char*)-1, args); +} + +START_TEST(badarg_packetwait_nan) +{ + char* args[] = { + "arping", + "-W", "huteosu", + "-h", // To exit cleanly. + "dummy", + NULL + }; + arping_main(sizeof(args)/sizeof(char*)-1, args); +} + +START_TEST(badarg_packetwait_range) +{ + char* args[] = { + "arping", + "-W", "10000000000000000000000000000000000000000", + "-h", // To exit cleanly. + "dummy", + NULL + }; + arping_main(sizeof(args)/sizeof(char*)-1, args); +} + +START_TEST(arg_packetwait_good) +{ + char* args[] = { + "arping", + "-W", "1.2", + "-h", // To exit cleanly. + "dummy", + NULL + }; + arping_main(sizeof(args)/sizeof(char*)-1, args); +} + START_TEST(libnet_init_bad_nolo) { // It'll only try lo if named interface fails. @@ -595,6 +657,7 @@ arping_suite(void) SIGH_LIBCHECK(libnet_init_good); SIGH_LIBCHECK(arg_maxcount_good); SIGH_LIBCHECK(arg_maxcount_hex); + SIGH_LIBCHECK(arg_packetwait_good); #define SIGH_LIBCHECK_EXIT(tn) \ tc_core = tcase_create(#tn); \ @@ -603,6 +666,10 @@ arping_suite(void) SIGH_LIBCHECK_EXIT(badarg_maxcount_neg); SIGH_LIBCHECK_EXIT(badarg_maxcount_nan); + SIGH_LIBCHECK_EXIT(badarg_maxcount_range); + SIGH_LIBCHECK_EXIT(badarg_packetwait_neg); + SIGH_LIBCHECK_EXIT(badarg_packetwait_nan); + SIGH_LIBCHECK_EXIT(badarg_packetwait_range); SIGH_LIBCHECK_EXIT(libnet_init_bad_nolo); SIGH_LIBCHECK_EXIT(libnet_init_null_nolo_nonull); -- cgit v1.2.1