From 16d3d9a04d5d2a7f4f10c3658cccc5aa0c7cd0af Mon Sep 17 00:00:00 2001 From: Sami Kerola Date: Sun, 15 Feb 2015 17:12:03 +0000 Subject: [PATCH] tailf: do not allow minus signed last lines argument Before mmap() the command behavior was not completely correct, as demonstrated below, and after the mmap() it tried to print some eighteen quintillion lines. $ tailf -n-1 x tailf: cannot allocate 18446744073709543424 bytes: Cannot allocate memory Signed-off-by: Sami Kerola --- text-utils/tailf.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/text-utils/tailf.c b/text-utils/tailf.c index 179dfc3d66..a89a3b5315 100644 --- a/text-utils/tailf.c +++ b/text-utils/tailf.c @@ -208,16 +208,16 @@ static void __attribute__ ((__noreturn__)) usage(FILE *out) } /* parses -N option */ -static long old_style_option(int *argc, char **argv) +static long old_style_option(int *argc, char **argv, unsigned long *lines) { - int i = 1, nargs = *argc; - long lines = -1; + int i = 1, nargs = *argc, ret = 0; while(i < nargs) { if (argv[i][0] == '-' && isdigit(argv[i][1])) { - lines = strtol_or_err(argv[i] + 1, + *lines = strtoul_or_err(argv[i] + 1, _("failed to parse number of lines")); nargs--; + ret = 1; if (nargs - i) memmove(argv + i, argv + i + 1, sizeof(char *) * (nargs - i)); @@ -225,13 +225,13 @@ static long old_style_option(int *argc, char **argv) i++; } *argc = nargs; - return lines; + return ret; } int main(int argc, char **argv) { const char *filename; - long lines; + unsigned long lines; int ch; struct stat st; @@ -247,16 +247,18 @@ int main(int argc, char **argv) textdomain(PACKAGE); atexit(close_stdout); - lines = old_style_option(&argc, argv); - if (lines < 0) + if (!old_style_option(&argc, argv, &lines)) lines = DEFAULT_LINES; while ((ch = getopt_long(argc, argv, "n:N:Vh", longopts, NULL)) != -1) - switch((char)ch) { + switch ((char)ch) { case 'n': case 'N': - lines = strtol_or_err(optarg, - _("failed to parse number of lines")); + if (optarg[0] == '-') + errx(EXIT_FAILURE, "%s: %s", + _("failed to parse number of lines"), optarg); + lines = + strtoul_or_err(optarg, _("failed to parse number of lines")); break; case 'V': printf(UTIL_LINUX_VERSION); -- 2.47.2