]> The Tcpdump Group git mirrors - libpcap/commitdiff
Use asprintf(), and provide a version for systems that lack it.
authorGuy Harris <[email protected]>
Sat, 9 Feb 2019 22:05:24 +0000 (14:05 -0800)
committerGuy Harris <[email protected]>
Sat, 9 Feb 2019 22:05:24 +0000 (14:05 -0800)
This lets us get rid of places where we calculate the length that a
formatted string will require, attempt to allocate a buffer for the
string, and then format the string into that buffer; this way, we don't
have to hope we got the calculation correct, we rely on the same code
that formats strings to do the calculation.

Provide versions of asprintf() for:

1) Windows and the MSVC runtime, where we use _vscprintf() to determine
the length;

2) systems that have (what is presumed to be) an snprintf() that, when
handed a too-short buffer, returns the number of characters that would
have been written had the buffer been long enough (as C99 specifies),
where we format to a one-character buffer to determine the length;

3) systems that don't have snprintf(), where we use the asprintf()
provided by the missing/snprintf.c file that also provides snprintf().

While we're at it, include "portability.h" in missing/win_snprintf.c, to
get declaration/definition checking done.

15 files changed:
CMakeLists.txt
Makefile.in
cmakeconfig.h.in
config.h.in
configure
configure.ac
missing/asprintf.c [new file with mode: 0644]
missing/snprintf.c
missing/win_asprintf.c [new file with mode: 0644]
missing/win_snprintf.c
pcap-new.c
pcap-npf.c
pcap-rpcap.c
pcap.c
portability.h

index e1a49273f09b8cdfc9760cfd6e63d2ce03010afc..ad7c8a66243929ef4a6f13e4ff06fedc32b92a62 100644 (file)
@@ -340,6 +340,8 @@ check_function_exists(strlcpy HAVE_STRLCPY)
 check_function_exists(strlcat HAVE_STRLCAT)
 check_function_exists(snprintf HAVE_SNPRINTF)
 check_function_exists(vsnprintf HAVE_VSNPRINTF)
+check_function_exists(asprintf HAVE_ASPRINTF)
+check_function_exists(vasprintf HAVE_VASPRINTF)
 check_function_exists(strtok_r HAVE_STRTOK_R)
 if(NOT WIN32)
     check_function_exists(vsyslog HAVE_VSYSLOG)
@@ -908,11 +910,55 @@ set(PROJECT_SOURCE_LIST_C
 )
 
 if(WIN32)
-    set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} missing/win_snprintf.c)
+    #
+    # For now, we assume we don't have snprintf() or that it's not one
+    # that behaves enough like C99's snprintf() for our purposes (i.e.,
+    # it doesn't null-terminate the string if it truncates it to fit in
+    # the buffer), so we have to provide our own (a wrapper around
+    # _snprintf() that null-terminates the buffer).
+    #
+    # We also assume we don't have asprintf(), and provide an implementation
+    # that uses _vscprintf() to determine how big the string needs to be.
+    #
+    set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C}
+        missing/win_snprintf.c, missing/win_asprintf.c)
 else()
+    #
+    # Either:
+    #
+    #  we have snprintf() and vsnprintf(), and have asprintf() and
+    #  vasprintf();
+    #
+    #  we have snprintf() and vsnprintf(), but don't have asprintf()
+    #  or vasprintf();
+    #
+    #  we have neither snprintf() nor vsnprintf(), and don't have
+    #  asprintf() or vasprintf(), either.
+    #
+    # We assume that if we have asprintf() we have vasprintf(), as well
+    # as snprintf() and vsnprintf(), and that if we have snprintf() we
+    # have vsnprintf().
+    #
+    # For the first case, we don't need any replacement routines.
+    # For the second case, we need replacement asprintf()/vasprintf()
+    # routines.
+    # For the third case, we need replacement snprintf()/vsnprintf() and
+    # asprintf()/vasprintf() routines.
+    #
     if(NOT HAVE_SNPRINTF)
+        #
+        # We assume we have none of them; missing/snprintf.c supplies
+        # all of them.
+        #
         set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} missing/snprintf.c)
-    endif(NOT HAVE_SNPRINTF)
+    elif(NOT HAVE_ASPRINTF)
+        #
+        # We assume we have snprintf()/vsnprintf() but lack
+        # asprintf()/vasprintf(); missing/asprintf.c supplies
+        # the latter (using vsnprintf()).
+        #
+        set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} missing/asprintf.c)
+    endif()
     if(NOT HAVE_STRLCAT)
         set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} missing/strlcat.c)
     endif(NOT HAVE_STRLCAT)
index a731d91e462a5561e796d807b720029a0c39c3b6..a906d7fdb78c4766fd6b1e77818d00d7bc02ee91 100644 (file)
@@ -279,12 +279,14 @@ EXTRA_DIST = \
        lbl/os-sunos4.h \
        lbl/os-ultrix4.h \
        libpcap.pc.in \
+       missing/asprintf.c \
        missing/getopt.c \
        missing/getopt.h \
        missing/snprintf.c \
        missing/strlcat.c \
        missing/strlcpy.c \
        missing/strtok_r.c \
+       missing/win_asprintf.c \
        missing/win_snprintf.c \
        mkdep \
        msdos/bin2c.c \
@@ -507,6 +509,9 @@ grammar.o: grammar.c scanner.h
 gencode.o: $(srcdir)/gencode.c grammar.h scanner.h
        $(CC) $(FULL_CFLAGS) -c $(srcdir)/gencode.c
 
+asprintf.o: $(srcdir)/missing/asprintf.c
+       $(CC) $(FULL_CFLAGS) -o $@ -c $(srcdir)/missing/asprintf.c
+
 snprintf.o: $(srcdir)/missing/snprintf.c
        $(CC) $(FULL_CFLAGS) -o $@ -c $(srcdir)/missing/snprintf.c
 
index 1d1e48ec3f3f11c966907689e7a3036173e41bf6..94f1cb562d7d2cf66f99b3cf90669c2facb75179 100644 (file)
@@ -15,6 +15,9 @@
 /* define if we have the AIX getprotobyname_r() */
 #cmakedefine HAVE_AIX_GETPROTOBYNAME_R 1
 
+/* Define to 1 if you have the `asprintf' function. */
+#cmakedefine HAVE_ASPRINTF 1
+
 /* define if you have the DAG API */
 #cmakedefine HAVE_DAG_API 1
 
 /* Define to 1 if you have the <unistd.h> header file. */
 #cmakedefine HAVE_UNISTD_H 1
 
+/* Define to 1 if you have the `vasprintf' function. */
+#cmakedefine HAVE_VASPRINTF 1
+
 /* Define to 1 if you have the `vsnprintf' function. */
 #cmakedefine HAVE_VSNPRINTF 1
 
index dd5c2e620ff0a8a624abdc01082f8c0ae97df89a..7503020201c5fdadeb519309526aecd14fb620c9 100644 (file)
@@ -15,6 +15,9 @@
 /* define if we have the AIX getprotobyname_r() */
 #undef HAVE_AIX_GETPROTOBYNAME_R
 
+/* Define to 1 if you have the `asprintf' function. */
+#undef HAVE_ASPRINTF
+
 /* Define to 1 if you have the <dagapi.h> header file. */
 #undef HAVE_DAGAPI_H
 
 /* Define to 1 if you have the <unistd.h> header file. */
 #undef HAVE_UNISTD_H
 
+/* Define to 1 if you have the `vasprintf' function. */
+#undef HAVE_VASPRINTF
+
 /* Define to 1 if you have the `vsnprintf' function. */
 #undef HAVE_VSNPRINTF
 
index f23a0ef673fe57d058745f146ebbb3f49811909e..ae85cf23afc2ced56f04e5a5b832d3ee85a436ed 100755 (executable)
--- a/configure
+++ b/configure
@@ -5050,6 +5050,28 @@ fi
 done
 
 
+#
+# Either:
+#
+#      we have snprintf() and vsnprintf(), and have asprintf() and
+#      vasprintf();
+#
+#      we have snprintf() and vsnprintf(), but don't have asprintf()
+#      or vasprintf();
+#
+#      we have neither snprintf() nor vsnprintf(), and don't have
+#      asprintf() or vasprintf(), either.
+#
+# We assume that if we have asprintf() we have vasprintf(), as well
+# as snprintf() and vsnprintf(), and that if we have snprintf() we
+# have vsnprintf().
+#
+# For the first case, we don't need any replacement routines.
+# For the second case, we need replacement asprintf()/vasprintf()
+# routines.
+# For the third case, we need replacement snprintf()/vsnprintf() and
+# asprintf()/vasprintf() routines.
+#
 needsnprintf=no
 for ac_func in vsnprintf snprintf
 do :
@@ -5065,13 +5087,44 @@ else
 fi
 done
 
+needasprintf=no
+for ac_func in vasprintf asprintf
+do :
+  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+else
+  needasprintf=yes
+fi
+done
+
 if test $needsnprintf = yes; then
+       #
+       # We assume we have none of them; missing/snprintf.c supplies
+       # all of them.
+       #
        case " $LIBOBJS " in
   *" snprintf.$ac_objext "* ) ;;
   *) LIBOBJS="$LIBOBJS snprintf.$ac_objext"
  ;;
 esac
 
+elif test $needasprintf = yes; then
+       #
+       # We assume we have snprintf()/vsnprintf() but lack
+       # asprintf()/vasprintf(); missing/asprintf.c supplies
+       # the latter (using vsnprintf()).
+       #
+       case " $LIBOBJS " in
+  *" asprintf.$ac_objext "* ) ;;
+  *) LIBOBJS="$LIBOBJS asprintf.$ac_objext"
+ ;;
+esac
+
 fi
 
 needstrlcat=no
index bca90044680445fdf508d9183cb42558eadbaf40..89aed3ff2dfde2fce843c1c65f529a2df5f5e8fc 100644 (file)
@@ -101,11 +101,47 @@ AC_CHECK_FUNCS(strerror strerror_r strerror_s)
 #
 AC_CHECK_FUNCS(vsyslog)
 
+#
+# Either:
+#
+#      we have snprintf() and vsnprintf(), and have asprintf() and
+#      vasprintf();
+#
+#      we have snprintf() and vsnprintf(), but don't have asprintf()
+#      or vasprintf();
+#
+#      we have neither snprintf() nor vsnprintf(), and don't have
+#      asprintf() or vasprintf(), either.
+#
+# We assume that if we have asprintf() we have vasprintf(), as well
+# as snprintf() and vsnprintf(), and that if we have snprintf() we
+# have vsnprintf().
+#
+# For the first case, we don't need any replacement routines.
+# For the second case, we need replacement asprintf()/vasprintf()
+# routines.
+# For the third case, we need replacement snprintf()/vsnprintf() and
+# asprintf()/vasprintf() routines.
+#
 needsnprintf=no
 AC_CHECK_FUNCS(vsnprintf snprintf,,
        [needsnprintf=yes])
+needasprintf=no
+AC_CHECK_FUNCS(vasprintf asprintf,,
+       [needasprintf=yes])
 if test $needsnprintf = yes; then
+       #
+       # We assume we have none of them; missing/snprintf.c supplies
+       # all of them.
+       #
        AC_LIBOBJ([snprintf])
+elif test $needasprintf = yes; then
+       #
+       # We assume we have snprintf()/vsnprintf() but lack
+       # asprintf()/vasprintf(); missing/asprintf.c supplies
+       # the latter (using vsnprintf()).
+       #
+       AC_LIBOBJ([asprintf])
 fi
 
 needstrlcat=no
diff --git a/missing/asprintf.c b/missing/asprintf.c
new file mode 100644 (file)
index 0000000..3aa55ed
--- /dev/null
@@ -0,0 +1,101 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+
+#include "portability.h"
+
+/*
+ * vasprintf() and asprintf() for platforms with a C99-compliant
+ * snprintf() - so that, if you format into a 1-byte buffer, it
+ * will return how many characters it would have produced had
+ * it been given an infinite-sized buffer.
+ */
+int
+pcap_vasprintf(char **strp, const char *format, va_list args)
+{
+       char buf;
+       int len;
+       size_t str_size;
+       char *str;
+       int ret;
+
+       /*
+        * XXX - the C99 standard says, in section 7.19.6.5 "Thes
+        * nprintf function":
+        *
+        *    The snprintf function is equivalent to fprintf, except that
+        *    the output is written into an array (specified by argument s)
+        *    rather than to a stream.  If n is zero, nothing is written,
+        *    and s may be a null pointer.  Otherwise, output characters
+        *    beyond the n-1st are discarded rather than being written
+        *    to the array, and a null character is written at the end
+        *    of the characters actually written into the array.
+        *
+        *        ...
+        *
+        *    The snprintf function returns the number of characters that
+        *    would have been written had n been sufficiently large, not
+        *    counting the terminating null character, or a negative value
+        *    if an encoding error occurred. Thus, the null-terminated
+        *    output has been completely written if and only if the returned
+        *    value is nonnegative and less than n.
+        *
+        * That doesn't make it entirely clear whether, if a null buffer
+        * pointer and a zero count are passed, it will return the number
+        * of characters that would have been written had a buffer been
+        * passed.
+        *
+        * And, even if C99 *does*, in fact, say it has to work, it
+        * doesn't work in Solaris 8, for example - it returns -1 for
+        * NULL/0, but returns the correct character count for a 1-byte
+        * buffer.
+        *
+        * So we pass a one-character pointer in order to find out how
+        * many characters this format and those arguments will need
+        * without actually generating any more of those characters
+        * than we need.
+        *
+        * (The fact that it might happen to work with GNU libc or with
+        * various BSD libcs is completely uninteresting, as those tend
+        * to have asprintf() already and thus don't even *need* this
+        * code; this is for use in those UN*Xes that *don't* have
+        * asprintf().)
+        */
+       len = vsnprintf(&buf, sizeof buf, format, args);
+       if (len == -1) {
+               *strp = NULL;
+               return (-1);
+       }
+       str_size = len + 1;
+       str = malloc(str_size);
+       if (str == NULL) {
+               *strp = NULL;
+               return (-1);
+       }
+       ret = vsnprintf(str, str_size, format, args);
+       if (ret == -1) {
+               free(str);
+               *strp = NULL;
+               return (-1);
+       }
+       *strp = str;
+       /*
+        * vsnprintf() shouldn't truncate the string, as we have
+        * allocated a buffer large enough to hold the string, so its
+        * return value should be the number of characters written.
+        */
+       return (ret);
+}
+
+int
+pcap_asprintf(char **strp, const char *format, ...)
+{
+       va_list args;
+       int ret;
+
+       va_start(args, format);
+       ret = pcap_vasprintf(strp, format, args);
+       va_end(args);
+       return (ret);
+}
+
index ef2065000eab3c4a65a4614570615dadd00fffa3..672aeb86a6d6b35b69b696a1f624553bf1e48889 100644 (file)
  * SUCH DAMAGE.
  */
 
+/*
+ * We use this for platforms that don't have snprintf() at all.
+ */
+
 #ifdef HAVE_CONFIG_H
 #include <config.h>
 #endif
@@ -42,7 +46,7 @@
 #include <ctype.h>
 #include <sys/types.h>
 
-#include <pcap-int.h>
+#include "portability.h"
 
 enum format_flags {
     minus_flag     =  1,
diff --git a/missing/win_asprintf.c b/missing/win_asprintf.c
new file mode 100644 (file)
index 0000000..cce6296
--- /dev/null
@@ -0,0 +1,51 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+
+#include "portability.h"
+
+int
+pcap_vasprintf(char **strp, const char *format, va_list args)
+{
+       int len;
+       size_t str_size;
+       char *str;
+       int ret;
+
+       len = _vscprintf(format, args);
+       if (len == -1) {
+               *strp = NULL;
+               return (-1);
+       }
+       str_size = len + 1;
+       str = malloc(str_size);
+       if (str == NULL) {
+               *strp = NULL;
+               return (-1);
+       }
+       ret = pcap_vsnprintf(str, str_size, format, args);
+       if (ret == -1) {
+               free(str);
+               *strp = NULL;
+               return (-1);
+       }
+       *strp = str;
+       /*
+        * pcap_vsnprintf() shouldn't truncate the string, as we have
+        * allocated a buffer large enough to hold the string, so its
+        * return value should be the number of characters printed.
+        */
+       return (ret);
+}
+
+int
+pcap_asprintf(char **strp, const char *format, ...)
+{
+       va_list args;
+       int ret;
+
+       va_start(args, format);
+       ret = pcap_vasprintf(strp, format, args);
+       va_end(args);
+       return (ret);
+}
index 65a8ea1a5cd9eee656d5453f3d65de0b19963b41..f42240352920b380add9ef2c740d9c2b0ffc13b9 100644 (file)
@@ -1,6 +1,8 @@
 #include <stdio.h>
 #include <stdarg.h>
 
+#include "portability.h"
+
 int
 pcap_vsnprintf(char *str, size_t str_size, const char *format, va_list args)
 {
@@ -13,6 +15,16 @@ pcap_vsnprintf(char *str, size_t str_size, const char *format, va_list args)
         * that str is null-terminated, but C99's vsnprintf()
         * and snprintf() do, and we want to offer C99 behavior,
         * so forcibly null-terminate the string.
+        *
+        * We don't, however, offer C99 behavior for the return
+        * value; _vsnprintf_s() returns -1, not the number of
+        * characters that would have been put into the buffer
+        * had it been large enough, if the string is truncated.
+        * The only way to get that value is to use _vscprintf();
+        * getting that count isn't worth the re-formatting.
+        *
+        * XXX - does _vsnprintf_s() return -1 on a formatting
+        * error?
         */
        str[str_size - 1] = '\0';
        return (ret);
index c4d35d186781a89e57716465e22e91f2fe5a855e..6b333e4e2260d27607f378e358216df8a241a28a 100644 (file)
@@ -150,21 +150,14 @@ int pcap_findalldevs_ex(const char *source, struct pcap_rmtauth *auth, pcap_if_t
 
                        /*
                         * Create the description.
-                        * First, allocate a buffer large enough
-                        * for the name.
                         */
                        if ((dev->description == NULL) || (dev->description[0] == 0))
                                localdesc = dev->name;
                        else
                                localdesc = dev->description;
-                       stringlen = PCAP_TEXT_SOURCE_ADAPTER_LEN
-                           + 1 + 1 /* space and ' */
-                           + strlen(localdesc)
-                           + 1 + 1 /* ' and space */
-                           + PCAP_TEXT_SOURCE_ON_LOCAL_HOST_LEN
-                           + 1; /* terminating '\0' */
-                       desc = (char *)malloc(stringlen);
-                       if (desc == NULL)
+                       if (pcap_asprintf(&desc, "%s '%s' %s",
+                           PCAP_TEXT_SOURCE_ADAPTER, localdesc,
+                           PCAP_TEXT_SOURCE_ON_LOCAL_HOST) == -1)
                        {
                                pcap_fmt_errmsg_for_errno(errbuf,
                                    PCAP_ERRBUF_SIZE, errno,
@@ -172,9 +165,6 @@ int pcap_findalldevs_ex(const char *source, struct pcap_rmtauth *auth, pcap_if_t
                                pcap_freealldevs(*alldevs);
                                return -1;
                        }
-                       pcap_snprintf(desc, stringlen, "%s '%s' %s",
-                           PCAP_TEXT_SOURCE_ADAPTER, localdesc,
-                           PCAP_TEXT_SOURCE_ON_LOCAL_HOST);
 
                        /* Now overwrite the description */
                        free(dev->description);
@@ -320,17 +310,10 @@ int pcap_findalldevs_ex(const char *source, struct pcap_rmtauth *auth, pcap_if_t
 
                                /*
                                 * Create the description.
-                                * First, allocate a buffer large enough
-                                * for the name.
                                 */
-                               stringlen = PCAP_TEXT_SOURCE_FILE_LEN
-                                   + 1 + 1 /* space and ' */
-                                   + strlen(filename)
-                                   + 1 + 1 /* ' and space */
-                                   + PCAP_TEXT_SOURCE_ON_LOCAL_HOST_LEN
-                                   + 1; /* terminating '\0' */
-                               dev->description = (char *)malloc(stringlen);
-                               if (dev->description == NULL)
+                               if (pcap_asprintf(&dev->description,
+                                   "%s '%s' %s", PCAP_TEXT_SOURCE_FILE,
+                                   filename, PCAP_TEXT_SOURCE_ON_LOCAL_HOST) == -1)
                                {
                                        pcap_fmt_errmsg_for_errno(errbuf,
                                            PCAP_ERRBUF_SIZE, errno,
@@ -339,14 +322,6 @@ int pcap_findalldevs_ex(const char *source, struct pcap_rmtauth *auth, pcap_if_t
                                        return -1;
                                }
 
-                               /*
-                                * Now format the new device description
-                                * into that buffer.
-                                */
-                               pcap_snprintf(dev->description, stringlen,
-                                   "%s '%s' %s", PCAP_TEXT_SOURCE_FILE,
-                                   filename, PCAP_TEXT_SOURCE_ON_LOCAL_HOST);
-
                                pcap_close(fp);
                        }
                }
index eecde122694cb6fe1246f965b1f81c8e5e7fdae7..81fa4036387e2536bbce6e2b544220e02e008811 100644 (file)
@@ -2019,21 +2019,16 @@ static const char *pcap_lib_version_string;
 
 static const char pcap_version_string[] =
        WINPCAP_PRODUCT_NAME " version " WINPCAP_VER_STRING ", based on " PCAP_VERSION_STRING;
-static const char pcap_version_string_packet_dll_fmt[] =
-       WINPCAP_PRODUCT_NAME " version " WINPCAP_VER_STRING " (packet.dll version %s), based on " PCAP_VERSION_STRING;
 
 const char *
 pcap_lib_version(void)
 {
-       char *packet_version_string;
-       size_t full_pcap_version_string_len;
-       char *full_pcap_version_string;
-
        if (pcap_lib_version_string == NULL) {
                /*
                 * Generate the version string.
                 */
-               packet_version_string = PacketGetVersion();
+               char *packet_version_string = PacketGetVersion();
+
                if (strcmp(WINPCAP_VER_STRING, packet_version_string) == 0) {
                        /*
                         * WinPcap version string and packet.dll version
@@ -2048,22 +2043,14 @@ pcap_lib_version(void)
                         * case (the two libraries should come from the
                         * same version of WinPcap), so we report both
                         * versions.
-                        *
-                        * The -2 is for the %s in the format string,
-                        * which will be replaced by packet_version_string.
                         */
-                       full_pcap_version_string_len =
-                           (sizeof pcap_version_string_packet_dll_fmt - 2) +
-                           strlen(packet_version_string);
-                       full_pcap_version_string = malloc(full_pcap_version_string_len);
-                       if (full_pcap_version_string == NULL)
-                               return (NULL);
-                       pcap_snprintf(full_pcap_version_string,
-                           full_pcap_version_string_len,
-                           pcap_version_string_packet_dll_fmt,
-                           packet_version_string);
+                       if (pcap_asprintf(&pcap_lib_version_string,
+                           WINPCAP_PRODUCT_NAME " version " WINPCAP_VER_STRING " (packet.dll version %s), based on " PCAP_VERSION_STRING,
+                           packet_version_string) == -1) {
+                               /* Failed. */
+                               pcap_lib_version_string = NULL;
+                       }
                }
-               pcap_lib_version_string = full_pcap_version_string;
        }
        return (pcap_lib_version_string);
 }
@@ -2074,35 +2061,20 @@ pcap_lib_version(void)
  * libpcap being built for Windows, not as part of a WinPcap/Npcap source
  * tree.
  */
-static const char pcap_version_string_packet_dll_fmt[] =
-       PCAP_VERSION_STRING " (packet.dll version %s)";
 const char *
 pcap_lib_version(void)
 {
-       char *packet_version_string;
-       size_t full_pcap_version_string_len;
-       char *full_pcap_version_string;
-
        if (pcap_lib_version_string == NULL) {
                /*
                 * Generate the version string.  Report the packet.dll
                 * version.
-                *
-                * The -2 is for the %s in the format string, which will
-                * be replaced by packet_version_string.
                 */
-               packet_version_string = PacketGetVersion();
-               full_pcap_version_string_len =
-                   (sizeof pcap_version_string_packet_dll_fmt - 2) +
-                   strlen(packet_version_string);
-               full_pcap_version_string = malloc(full_pcap_version_string_len);
-               if (full_pcap_version_string == NULL)
-                       return (NULL);
-               pcap_snprintf(full_pcap_version_string,
-                   full_pcap_version_string_len,
-                   pcap_version_string_packet_dll_fmt,
-                   packet_version_string);
-               pcap_lib_version_string = full_pcap_version_string;
+               if (pcap_asprintf(&pcap_lib_version_string,
+                   PCAP_VERSION_STRING " (packet.dll version %s)",
+                   PacketGetVersion()) == -1) {
+                       /* Failed. */
+                       pcap_lib_version_string = NULL;
+               }
        }
        return (pcap_lib_version_string);
 }
index d3b7ebf0d629a8b09e77a39df3f7885e8f7d39d3..6aceccb49874080a9aad93a14ab6a93154734ba0 100644 (file)
@@ -1684,8 +1684,6 @@ static int pcap_createfilter_norpcappkt(pcap_t *fp, struct bpf_program *prog)
                char peeraddress[128];
                char peerctrlport[128];
                char *newfilter;
-               const int newstringsize = 1024;
-               size_t currentfiltersize;
 
                /* Get the name/port of our peer */
                saddrlen = sizeof(struct sockaddr_storage);
@@ -1732,25 +1730,42 @@ static int pcap_createfilter_norpcappkt(pcap_t *fp, struct bpf_program *prog)
                        return -1;
                }
 
-               currentfiltersize = pr->currentfilter ? strlen(pr->currentfilter) : 0;
-
-               newfilter = (char *)malloc(currentfiltersize + newstringsize + 1);
-
-               if (currentfiltersize)
+               if (pr->currentfilter && pr->currentfilter[0] != '\0')
                {
-                       pcap_snprintf(newfilter, currentfiltersize + newstringsize,
-                               "(%s) and not (host %s and host %s and port %s and port %s) and not (host %s and host %s and port %s)",
-                               pr->currentfilter, myaddress, peeraddress, myctrlport, peerctrlport, myaddress, peeraddress, mydataport);
+                       /*
+                        * We have a current filter; add items to it to
+                        * filter out this rpcap session.
+                        */
+                       if (pcap_asprintf(&newfilter,
+                           "(%s) and not (host %s and host %s and port %s and port %s) and not (host %s and host %s and port %s)",
+                           pr->currentfilter, myaddress, peeraddress,
+                           myctrlport, peerctrlport, myaddress, peeraddress,
+                           mydataport) == -1)
+                       {
+                               /* Failed. */
+                               pcap_snprintf(fp->errbuf, PCAP_ERRBUF_SIZE,
+                                   "Can't allocate memory for new filter");
+                               return -1;
+                       }
                }
                else
                {
-                       pcap_snprintf(newfilter, currentfiltersize + newstringsize,
-                               "not (host %s and host %s and port %s and port %s) and not (host %s and host %s and port %s)",
-                               myaddress, peeraddress, myctrlport, peerctrlport, myaddress, peeraddress, mydataport);
+                       /*
+                        * We have no current filter; construct a filter to
+                        * filter out this rpcap session.
+                        */
+                       if (pcap_asprintf(&newfilter,
+                           "not (host %s and host %s and port %s and port %s) and not (host %s and host %s and port %s)",
+                           myaddress, peeraddress, myctrlport, peerctrlport,
+                           myaddress, peeraddress, mydataport) == -1)
+                       {
+                               /* Failed. */
+                               pcap_snprintf(fp->errbuf, PCAP_ERRBUF_SIZE,
+                                   "Can't allocate memory for new filter");
+                               return -1;
+                       }
                }
 
-               newfilter[currentfiltersize + newstringsize] = 0;
-
                /*
                 * This is only an hack to prevent the save_current_filter
                 * routine, which will be called when we call pcap_compile(),
@@ -2506,7 +2521,6 @@ pcap_findalldevs_ex_remote(const char *source, struct pcap_rmtauth *auth, pcap_i
        {
                struct rpcap_findalldevs_if findalldevs_if;
                char tmpstring2[PCAP_BUF_SIZE + 1];             /* Needed to convert names and descriptions from 'old' syntax to the 'new' one */
-               size_t stringlen;
                struct pcap_addr *addr, *prevaddr;
 
                tmpstring2[PCAP_BUF_SIZE] = 0;
@@ -2596,29 +2610,14 @@ pcap_findalldevs_ex_remote(const char *source, struct pcap_rmtauth *auth, pcap_i
 
                        tmpstring[findalldevs_if.desclen] = 0;
 
-                       stringlen = PCAP_TEXT_SOURCE_ADAPTER_LEN
-                           + 1 + 1 /* space and ' */
-                           + strlen(tmpstring)
-                           + 1 + 1 /* ' and space */
-                           + PCAP_TEXT_SOURCE_ON_REMOTE_HOST_LEN
-                           + 1 /* space */
-                           + strlen(host)
-                           + 1; /* terminating '\0' */
-                       dev->description = (char *)malloc(stringlen);
-                       if (dev->description == NULL)
+                       if (pcap_asprintf(&dev->description,
+                           "%s '%s' %s %s", PCAP_TEXT_SOURCE_ADAPTER,
+                           tmpstring, PCAP_TEXT_SOURCE_ON_REMOTE_HOST, host) == -1)
                        {
                                pcap_fmt_errmsg_for_errno(errbuf,
                                    PCAP_ERRBUF_SIZE, errno, "malloc() failed");
                                goto error;
                        }
-
-                       /*
-                        * Now format the new device description into
-                        * that buffer.
-                        */
-                       pcap_snprintf(dev->description, stringlen,
-                           "%s '%s' %s %s", PCAP_TEXT_SOURCE_ADAPTER,
-                           tmpstring, PCAP_TEXT_SOURCE_ON_REMOTE_HOST, host);
                }
 
                dev->flags = ntohl(findalldevs_if.flags);
diff --git a/pcap.c b/pcap.c
index a58db1834343452e3bee39b403e24bdad6c32bdd..c134cd6029b63502227e0f42f3f5e655756b8007 100644 (file)
--- a/pcap.c
+++ b/pcap.c
@@ -833,20 +833,13 @@ get_if_description(const char *name)
                                 * OK, it's a valid number that's not
                                 * bigger than INT_MAX.  Construct
                                 * a description from it.
+                                * (If that fails, we don't worry about
+                                * it, we just return NULL.)
                                 */
-                               static const char descr_prefix[] = "USB bus number ";
-                               size_t descr_size;
-
-                               /*
-                                * Allow enough room for a 32-bit bus number.
-                                * sizeof (descr_prefix) includes the
-                                * terminating NUL.
-                                */
-                               descr_size = sizeof (descr_prefix) + 10;
-                               description = malloc(descr_size);
-                               if (description != NULL) {
-                                       pcap_snprintf(description, descr_size,
-                                           "%s%ld", descr_prefix, busnum);
+                               if (pcap_asprintf(&description,
+                                   "USB bus number %ld", busnum) == -1) {
+                                       /* Failed. */
+                                       description = NULL;
                                }
                        }
                }
index beec43cc922eb85d82a8429e335d1a29eaa2c6cb..543846e8bd25eb22d904554544a668faccd70852 100644 (file)
@@ -38,6 +38,7 @@
  * Helpers for portability between Windows and UN*X and between different
  * flavors of UN*X.
  */
+#include <stdarg.h>    /* we declare varargs functions on some platforms */
 
 #include "pcap/funcattrs.h"
 
@@ -130,6 +131,23 @@ extern int pcap_snprintf(char *, size_t, PCAP_FORMAT_STRING(const char *), ...)
 extern int pcap_vsnprintf(char *, size_t, const char *, va_list ap);
 #endif
 
+/*
+ * We also want asprintf(), for some cases where we use it to construct
+ * dynamically-allocated variable-length strings.
+ */
+#ifdef HAVE_ASPRINTF
+#define pcap_asprintf asprintf
+#else
+extern int pcap_asprintf(char **, PCAP_FORMAT_STRING(const char *), ...)
+    PCAP_PRINTFLIKE(2, 3);
+#endif
+
+#ifdef HAVE_VASPRINTF
+#define pcap_vasprintf vasprintf
+#else
+extern int pcap_vasprintf(char **, const char *, va_list ap);
+#endif
+
 #ifdef HAVE_STRTOK_R
   #define pcap_strtok_r        strtok_r
 #else