@@ -165,11 +165,7 @@ The Regents of the University of California. All rights reserved.\n";
165
165
#endif
166
166
167
167
static int Bflag ; /* buffer size */
168
- #ifdef HAVE_PCAP_DUMP_FTELL64
169
168
static int64_t Cflag ; /* rotate dump files after this many bytes */
170
- #else
171
- static long Cflag ; /* rotate dump files after this many bytes */
172
- #endif
173
169
static int Cflag_count ; /* Keep track of which file number we're writing */
174
170
static int Dflag ; /* list available devices and exit */
175
171
#ifdef HAVE_PCAP_FINDALLDEVS_EX
@@ -219,6 +215,12 @@ static int infoprint;
219
215
char * program_name ;
220
216
221
217
/* Forwards */
218
+ static int parse_int (const char * argname , const char * string , char * * endp ,
219
+ int minval , int maxval , int base );
220
+ static u_int parse_u_int (const char * argname , const char * string , char * * endp ,
221
+ u_int minval , u_int maxval , int base );
222
+ static int64_t parse_int64 (const char * argname , const char * string ,
223
+ char * * endp , int64_t minval , int64_t maxval , int base );
222
224
static void (* setsignal (int sig , void (* func )(int )))(int );
223
225
static void cleanup (int );
224
226
static void child_cleanup (int );
@@ -1422,7 +1424,6 @@ main(int argc, char **argv)
1422
1424
const char * chroot_dir = NULL ;
1423
1425
#endif
1424
1426
char * ret = NULL ;
1425
- char * end ;
1426
1427
pcap_if_t * devlist ;
1427
1428
long devnum ;
1428
1429
int status ;
@@ -1645,26 +1646,24 @@ main(int argc, char **argv)
1645
1646
break ;
1646
1647
1647
1648
case 'B' :
1648
- Bflag = atoi (optarg )* 1024 ;
1649
- if (Bflag <= 0 )
1650
- error ("invalid packet buffer size %s" , optarg );
1649
+ Bflag = parse_int ("packet buffer size" , optarg , NULL , 1 ,
1650
+ INT_MAX , 10 );
1651
+ /*
1652
+ * Will multiplying it by 1024 overflow?
1653
+ */
1654
+ if (Bflag > INT_MAX / 1024 )
1655
+ error ("packet buffer size %s is too large" , optarg );
1656
+ Bflag *= 1024 ;
1651
1657
break ;
1652
1658
1653
1659
case 'c' :
1654
- cnt = atoi (optarg );
1655
- if (cnt <= 0 )
1656
- error ("invalid packet count %s" , optarg );
1660
+ cnt = parse_int ("packet count" , optarg , NULL , 1 ,
1661
+ INT_MAX , 10 );
1657
1662
break ;
1658
1663
1659
1664
case 'C' :
1660
- errno = 0 ;
1661
- #ifdef HAVE_PCAP_DUMP_FTELL64
1662
- Cflag = strtoint64_t (optarg , & endp , 10 );
1663
- #else
1664
- Cflag = strtol (optarg , & endp , 10 );
1665
- #endif
1666
- if (endp == optarg || errno != 0 || Cflag <= 0 )
1667
- error ("invalid file size %s" , optarg );
1665
+ Cflag = parse_int64 ("file size" , optarg , & endp , 1 ,
1666
+ INT64_MAX , 10 );
1668
1667
1669
1668
if (* endp == '\0' ) {
1670
1669
/*
@@ -1709,7 +1708,7 @@ main(int argc, char **argv)
1709
1708
break ;
1710
1709
1711
1710
default :
1712
- error ("invalid file size %s" , optarg );
1711
+ error ("invalid file size %s (invalid units) " , optarg );
1713
1712
}
1714
1713
1715
1714
/*
@@ -1720,7 +1719,7 @@ main(int argc, char **argv)
1720
1719
endp ++ ;
1721
1720
if (* endp != '\0' ) {
1722
1721
/* Yes - error */
1723
- error ("invalid file size %s" , optarg );
1722
+ error ("invalid file size %s (invalid units) " , optarg );
1724
1723
}
1725
1724
}
1726
1725
@@ -1774,9 +1773,8 @@ main(int argc, char **argv)
1774
1773
break ;
1775
1774
1776
1775
case 'G' :
1777
- Gflag = atoi (optarg );
1778
- if (Gflag < 0 )
1779
- error ("invalid number of seconds %s" , optarg );
1776
+ Gflag = parse_int ("number of seconds" , optarg , NULL , 0 ,
1777
+ INT_MAX , 10 );
1780
1778
1781
1779
/* We will create one file initially. */
1782
1780
Gflag_count = 0 ;
@@ -1895,11 +1893,8 @@ main(int argc, char **argv)
1895
1893
break ;
1896
1894
1897
1895
case 's' :
1898
- ndo -> ndo_snaplen = (int )strtol (optarg , & end , 0 );
1899
- if (optarg == end || * end != '\0'
1900
- || ndo -> ndo_snaplen < 0 || ndo -> ndo_snaplen > MAXIMUM_SNAPLEN )
1901
- error ("invalid snaplen %s (must be >= 0 and <= %d)" ,
1902
- optarg , MAXIMUM_SNAPLEN );
1896
+ ndo -> ndo_snaplen = parse_int ("snaplen" , optarg , NULL ,
1897
+ 0 , MAXIMUM_SNAPLEN , 0 );
1903
1898
break ;
1904
1899
1905
1900
case 'S' :
@@ -1978,9 +1973,8 @@ main(int argc, char **argv)
1978
1973
break ;
1979
1974
1980
1975
case 'W' :
1981
- Wflag = atoi (optarg );
1982
- if (Wflag <= 0 )
1983
- error ("invalid number of output files %s" , optarg );
1976
+ Wflag = parse_int ("number of output files" , optarg ,
1977
+ NULL , 1 , INT_MAX , 10 );
1984
1978
WflagChars = getWflagChars (Wflag );
1985
1979
break ;
1986
1980
@@ -2056,17 +2050,13 @@ main(int argc, char **argv)
2056
2050
case OPTION_PRINT_SAMPLING :
2057
2051
print = 1 ;
2058
2052
++ ndo -> ndo_Sflag ;
2059
- ndo -> ndo_print_sampling = atoi (optarg );
2060
- if (ndo -> ndo_print_sampling <= 0 )
2061
- error ("invalid print sampling %s" , optarg );
2053
+ ndo -> ndo_print_sampling = parse_int ("print sampling" ,
2054
+ optarg , NULL , 1 , INT_MAX , 10 );
2062
2055
break ;
2063
2056
2064
2057
case OPTION_SKIP :
2065
- errno = 0 ;
2066
- packets_skipped = (u_int )strtoul (optarg , & end , 0 );
2067
- if (optarg [0 ] == '-' || optarg == end || * end != '\0' ||
2068
- errno != 0 )
2069
- error ("invalid packet skipped %s" , optarg );
2058
+ packets_skipped = parse_u_int ("packet skip count" ,
2059
+ optarg , NULL , 1 , UINT_MAX , 0 );
2070
2060
break ;
2071
2061
2072
2062
#ifdef HAVE_PCAP_SET_TSTAMP_PRECISION
@@ -2829,6 +2819,134 @@ DIAG_ON_ASSIGN_ENUM
2829
2819
exit_tcpdump (status == -1 ? S_ERR_HOST_PROGRAM : S_SUCCESS );
2830
2820
}
2831
2821
2822
+ /*
2823
+ * Routines to parse numerical command-line arguments and check for
2824
+ * errors, including "too large for that type".
2825
+ */
2826
+ static int
2827
+ parse_int (const char * argname , const char * string , char * * endpp ,
2828
+ int minval , int maxval , int base )
2829
+ {
2830
+ long val ;
2831
+ char * endp ;
2832
+
2833
+ errno = 0 ;
2834
+ val = strtol (string , & endp , base );
2835
+
2836
+ /*
2837
+ * Did it either not parse any of the string, find extra stuff
2838
+ * at the end that the caller isn't interested in, or get
2839
+ * another parsing error?
2840
+ */
2841
+ if (string == endp || (endpp == NULL && * endp != '\0' ) ||
2842
+ (val == 0 && errno == EINVAL )) {
2843
+ error ("invalid %s \"%s\" (not a valid number)" , argname ,
2844
+ string );
2845
+ }
2846
+
2847
+ /*
2848
+ * Did it get a value that's out of range?
2849
+ */
2850
+ if (((val == LONG_MAX || val == LONG_MIN ) && errno == ERANGE ) ||
2851
+ val < minval || val > maxval ) {
2852
+ error ("invalid %s %s (must be >= %d and <= %d)" ,
2853
+ argname , string , minval , maxval );
2854
+ }
2855
+
2856
+ /*
2857
+ * OK, it passes all the tests.
2858
+ */
2859
+ if (endpp != NULL )
2860
+ * endpp = endp ;
2861
+ return ((int )val );
2862
+ }
2863
+
2864
+ static u_int
2865
+ parse_u_int (const char * argname , const char * string , char * * endpp ,
2866
+ u_int minval , u_int maxval , int base )
2867
+ {
2868
+ unsigned long val ;
2869
+ char * endp ;
2870
+
2871
+ errno = 0 ;
2872
+
2873
+ /*
2874
+ * strtoul() does *NOT* report an error if the string
2875
+ * begins with a minus sign. We do.
2876
+ */
2877
+ if (* string == '-' ) {
2878
+ error ("invalid %s \"%s\" (not a valid unsigned number)" ,
2879
+ argname , string );
2880
+ }
2881
+
2882
+ val = strtoul (string , & endp , base );
2883
+
2884
+ /*
2885
+ * Did it either not parse any of the string, find extra stuff
2886
+ * at the end that the caller isn't interested in, or get
2887
+ * another parsing error?
2888
+ */
2889
+ if (string == endp || (endpp == NULL && * endp != '\0' ) ||
2890
+ (val == 0 && errno == EINVAL )) {
2891
+ error ("invalid %s \"%s\" (not a valid unsigned number)" ,
2892
+ argname , string );
2893
+ }
2894
+
2895
+ /*
2896
+ * Did it get a value that's out of range?
2897
+ */
2898
+ if ((val == ULONG_MAX && errno == ERANGE ) ||
2899
+ val < minval || val > maxval ) {
2900
+ error ("invalid %s %s (must be >= %u and <= %u)" ,
2901
+ argname , string , minval , maxval );
2902
+ }
2903
+
2904
+ /*
2905
+ * OK, it passes all the tests.
2906
+ */
2907
+ if (endpp != NULL )
2908
+ * endpp = endp ;
2909
+ return ((u_int )val );
2910
+ }
2911
+
2912
+ static int64_t
2913
+ parse_int64 (const char * argname , const char * string , char * * endpp ,
2914
+ int64_t minval , int64_t maxval , int base )
2915
+ {
2916
+ intmax_t val ;
2917
+ char * endp ;
2918
+
2919
+ errno = 0 ;
2920
+ val = strtoimax (string , & endp , base );
2921
+
2922
+ /*
2923
+ * Did it either not parse any of the string, find extra stuff
2924
+ * at the end that the caller isn't interested in, or get
2925
+ * another parsing error?
2926
+ */
2927
+ if (string == endp || (endpp == NULL && * endp != '\0' ) ||
2928
+ (val == 0 && errno == EINVAL )) {
2929
+ error ("invalid %s \"%s\" (not a valid number)" , argname ,
2930
+ string );
2931
+ }
2932
+
2933
+ /*
2934
+ * Did it get a value that's out of range?
2935
+ */
2936
+ if (((val == INTMAX_MAX || val == INTMAX_MIN ) && errno == ERANGE ) ||
2937
+ val < minval || val > maxval ) {
2938
+ error ("invalid %s %s (must be >= %" PRId64 " and <= %" PRId64 ")" ,
2939
+ argname , string , minval , maxval );
2940
+ }
2941
+
2942
+ /*
2943
+ * OK, it passes all the tests.
2944
+ */
2945
+ if (endpp != NULL )
2946
+ * endpp = endp ;
2947
+ return ((int64_t )val );
2948
+ }
2949
+
2832
2950
/*
2833
2951
* Catch a signal.
2834
2952
*/
0 commit comments