diff --git a/nmap.cc b/nmap.cc index 36ac65ada..18a0ea260 100644 --- a/nmap.cc +++ b/nmap.cc @@ -417,9 +417,8 @@ static int ip_is_reserved(struct in_addr *ip) static char *grab_next_host_spec(FILE *inputfd, int argc, char **fakeargv) { static char host_spec[1024]; - unsigned int host_spec_index; - int ch; struct in_addr ip; + size_t n; if (o.generate_random_ips) { do { @@ -429,25 +428,12 @@ static char *grab_next_host_spec(FILE *inputfd, int argc, char **fakeargv) { } else if (!inputfd) { return( (optind < argc)? fakeargv[optind++] : NULL); } else { - host_spec_index = 0; - while((ch = getc(inputfd)) != EOF) { - if (ch == ' ' || ch == '\r' || ch == '\n' || ch == '\t' || ch == '\0') { - if (host_spec_index == 0) continue; - host_spec[host_spec_index] = '\0'; - return host_spec; - } else if (ch == '#') { - /* Found a comment marker, ignore everything until EOL or EOF */ - while ((ch = getc(inputfd)) != EOF && ch != '\n') - ; - if (ch != EOF) - ungetc(ch, inputfd); - } else if (host_spec_index < sizeof(host_spec) / sizeof(char) -1) { - host_spec[host_spec_index++] = (char) ch; - } else fatal("One of the host_specifications from your input file is too long (> %d chars)", (int) sizeof(host_spec)); - } - host_spec[host_spec_index] = '\0'; + n = read_host_from_file(inputfd, host_spec, sizeof(host_spec)); + if (n == 0) + return NULL; + else if (n >= sizeof(host_spec)) + fatal("One of the host_specifications from your input file is too long (>= %u chars)", (unsigned int) sizeof(host_spec)); } - if (!*host_spec) return NULL; return host_spec; } diff --git a/targets.cc b/targets.cc index f2104f434..dac8eb131 100644 --- a/targets.cc +++ b/targets.cc @@ -347,6 +347,47 @@ TargetGroup* load_exclude(FILE *fExclude, char *szExclude) { return excludelist; } +static inline bool is_host_separator(int c) { + return c == ' ' || c == '\r' || c == '\n' || c == '\t' || c == '\0'; +} + +/* Read a single host specification from a file, as for -iL and --excludefile. + It returns the length of the string read; an overflow is indicated when the + return value is >= n. Returns 0 if there was no specification to be read. The + buffer is always null-terminated. */ +size_t read_host_from_file(FILE *fp, char *buf, size_t n) +{ + int ch; + size_t i; + + i = 0; + ch = getc(fp); + while (is_host_separator(ch) || ch == '#') { + if (ch == '#') { + /* Skip comments to the end of the line. */ + while ((ch = getc(fp)) != EOF && ch != '\n') + ; + } else { + ch = getc(fp); + } + } + while (ch != EOF && !(is_host_separator(ch) || ch == '#')) { + if (i < n) + buf[i] = ch; + i++; + ch = getc(fp); + } + if (ch != EOF) + ungetc(ch, fp); + if (i < n) + buf[i] = '\0'; + else if (n > 0) + /* Null-terminate even though it was too long. */ + buf[n - 1] = '\0'; + + return i; +} + /* A debug routine to dump some information to stdout. (mdmcl) * Invoked if debugging is set to 3 or higher * I had to make signigicant changes from wam's code. Although wam diff --git a/targets.h b/targets.h index 8b1a5e15e..5108d1b39 100644 --- a/targets.h +++ b/targets.h @@ -161,6 +161,8 @@ Target *nexthost(HostGroupState *hs, TargetGroup *exclude_group, struct scan_lists *ports, int pingtype); /* loads an exclude file into a excluded target list */ TargetGroup* load_exclude(FILE *fExclude, char *szExclude); +/* Read a single host specification from a file, as for -iL and --excludefile. */ +size_t read_host_from_file(FILE *fp, char *buf, size_t n); /* a debugging routine to dump an exclude list to stdout. */ int dumpExclude(TargetGroup*exclude_group); /* Returns the last host obtained by nexthost. It will be given again the next