]> The Tcpdump Group git mirrors - tcpdump/commitdiff
Use basename() and dirname() right on FreeBSD. [skip appveyor]
authorDenis Ovsienko <[email protected]>
Thu, 5 Aug 2021 13:18:55 +0000 (14:18 +0100)
committerDenis Ovsienko <[email protected]>
Thu, 5 Aug 2021 13:39:45 +0000 (14:39 +0100)
On FreeBSD CMake runs Clang with -std=gnu99, which used to emit three
warnings in a Capsicum-specific block along the following lines:

tcpdump.c:2432:32: warning: '_Generic' is a C11 extension
  [-Wc11-extensions]
/usr/include/libgen.h:61:21: note: expanded from macro 'basename'
  basename)(x)
/usr/include/sys/cdefs.h:325:2: note: expanded from macro '__generic'
        _Generic(expr, t: yes, default: no)

(In the same context Autoconf does not request a specific C standard
from Clang, so it happens to use C17 and there is no warning.)

Type-generic expressions support in C99 mode seems to be a quirk of
Clang that cannot be disabled and is harmless in this context, so
introduce and use another pair of diagnostic control macros (for Clang
only) to squelch the warnings.

While at it, study the reason for _Generic use in /usr/include/libgen.h
and realize that tcpdump.c still assumes the behaviour before FreeBSD
12.0.  Add two temporary buffers around basename() and dirname() calls
to get consistent results regardless of which FreeBSD version it is.

Remove the last remaining exemption rule.

build.sh
diag-control.h
tcpdump.c

index a10a4f66f851e07f482d52d6eb47eee8d1e5bc85..0be231b8db632aa64a54ac2d7ef18c3a585a48d4 100755 (executable)
--- a/build.sh
+++ b/build.sh
@@ -28,22 +28,9 @@ print_cc_version
 # are not warning-free for one or another reason.  If you manage to fix one of
 # these cases, please remember to remove respective exemption below to help any
 # later warnings in the same matrix subset trigger an error.
-# shellcheck disable=SC2006
-case `os_id`/"$CMAKE" in
-FreeBSD-*/yes)
-    case `cc_id` in
-    clang-*)
-        # tcpdump.c:2434:32: error: '_Generic' is a C11 extension
-        #   [-Werror,-Wc11-extensions]
-        # tcpdump.c:2439:26: error: '_Generic' is a C11 extension
-        #   [-Werror,-Wc11-extensions]
-        # tcpdump.c:2443:9: error: '_Generic' is a C11 extension
-        #   [-Werror,-Wc11-extensions]
-        TCPDUMP_TAINTED=yes
-        ;;
-    esac
-    ;;
-esac
+
+# (There are no exemptions right now.)
+
 # shellcheck disable=SC2006
 [ "$TCPDUMP_TAINTED" != yes ] && CFLAGS=`cc_werr_cflags`
 
index c1ca6536ce87c13216a234bcb4d959317399e2c8..b7ef01fc46a150089c5a5d6920b6b2b4b186fa44 100644 (file)
     DIAG_DO_PRAGMA(clang diagnostic ignored "-Wdeprecated-declarations")
   #define DIAG_ON_DEPRECATION \
     DIAG_DO_PRAGMA(clang diagnostic pop)
+
+  /*
+   * Clang supports the generic C11 extension even if run with the -std=gnu99
+   * flag, which leads FreeBSD <sys/cdefs.h> to use the extension, which
+   * results in Clang emitting a -Wc11-extensions warning. The warning is not
+   * documented in the user manual, but it happens with Clang 10.0.1 on
+   * FreeBSD 12.2, so let's use that as a reference.
+   */
+  #if ND_IS_AT_LEAST_CLANG_VERSION(10,0)
+    #define DIAG_OFF_C11_EXTENSIONS \
+      DIAG_DO_PRAGMA(clang diagnostic push) \
+      DIAG_DO_PRAGMA(clang diagnostic ignored "-Wc11-extensions")
+    #define DIAG_ON_C11_EXTENSIONS \
+      DIAG_DO_PRAGMA(clang diagnostic pop)
+  #endif
 #elif ND_IS_AT_LEAST_GNUC_VERSION(4,2)
   /* GCC apparently doesn't complain about ORing enums together. */
   #define DIAG_OFF_ASSIGN_ENUM
     DIAG_DO_PRAGMA(GCC diagnostic ignored "-Wdeprecated-declarations")
   #define DIAG_ON_DEPRECATION \
     DIAG_DO_PRAGMA(GCC diagnostic pop)
+  /*
+   * GCC supports -Wc99-c11-compat since version 5.1.0, but the warning does
+   * not trigger for now, so let's just leave it be.
+   */
 #else
   #define DIAG_OFF_ASSIGN_ENUM
   #define DIAG_ON_ASSIGN_ENUM
   #define DIAG_ON_DEPRECATION
 #endif
 
+#ifndef DIAG_OFF_C11_EXTENSIONS
+#define DIAG_OFF_C11_EXTENSIONS
+#endif
+#ifndef DIAG_ON_C11_EXTENSIONS
+#define DIAG_ON_C11_EXTENSIONS
+#endif
+
 #endif /* _diag_control_h */
index 611fa69b327bc75ec76efb5c68ea58df7bc00bd7..bac890f0da1951779536d620c2be6174d7f751c3 100644 (file)
--- a/tcpdump.c
+++ b/tcpdump.c
@@ -2429,17 +2429,44 @@ DIAG_ON_ASSIGN_ENUM
 #endif
                if (Cflag != 0 || Gflag != 0) {
 #ifdef HAVE_CAPSICUM
-                       dumpinfo.WFileName = strdup(basename(WFileName));
+                       /*
+                        * basename() and dirname() may modify their input buffer
+                        * and they do since FreeBSD 12.0, but they didn't before.
+                        * Hence use the return value only, but always assume the
+                        * input buffer has been modified and would need to be
+                        * reset before the next use.
+                        */
+                       char *WFileName_copy;
+
+                       if ((WFileName_copy = strdup(WFileName)) == NULL) {
+                               error("Unable to allocate memory for file %s",
+                                   WFileName);
+                       }
+                       DIAG_OFF_C11_EXTENSIONS
+                       dumpinfo.WFileName = strdup(basename(WFileName_copy));
+                       DIAG_ON_C11_EXTENSIONS
                        if (dumpinfo.WFileName == NULL) {
                                error("Unable to allocate memory for file %s",
                                    WFileName);
                        }
-                       dumpinfo.dirfd = open(dirname(WFileName),
+                       free(WFileName_copy);
+
+                       if ((WFileName_copy = strdup(WFileName)) == NULL) {
+                               error("Unable to allocate memory for file %s",
+                                   WFileName);
+                       }
+                       DIAG_OFF_C11_EXTENSIONS
+                       char *WFileName_dirname = dirname(WFileName_copy);
+                       DIAG_ON_C11_EXTENSIONS
+                       dumpinfo.dirfd = open(WFileName_dirname,
                            O_DIRECTORY | O_RDONLY);
                        if (dumpinfo.dirfd < 0) {
                                error("unable to open directory %s",
-                                   dirname(WFileName));
+                                   WFileName_dirname);
                        }
+                       free(WFileName_dirname);
+                       free(WFileName_copy);
+
                        cap_rights_init(&rights, CAP_CREATE, CAP_FCNTL,
                            CAP_FTRUNCATE, CAP_LOOKUP, CAP_SEEK, CAP_WRITE);
                        if (cap_rights_limit(dumpinfo.dirfd, &rights) < 0 &&