瀏覽代碼

maint: port to Fedora 33

Fedora 33 uses GCC 10.2.1, which is a bit pickier.
* configure.ac: Do not use -Wsystem-headers, as this
runs afoul of netdb.h on Fedora 33.
* gnulib.modules: Add ‘attribute’.
* lib/wordsplit.c (wsnode_new): Return the newly allocated
pointer instead of a boolean, to pacify GCC 10.2.1 which otherwise
complains about use of possibly-null pointers.  All uses changed.
* src/buffer.c (try_new_volume): Don’t assume find_next_block succeeds.
(_write_volume_label): Pacify GCC 10.2.1 with an ‘assume’, since
LABEL must be nonnull here.
* src/common.h (FALLTHROUGH): Remove; now in attribute.h.
Include attribute.h, for ATTRIBUTE_NONNULL.
* src/misc.c (assign_string_or_null): New function,
taking over the old role of assign_string.
(assign_string): Assume VALUE is non-null.
(assign_null): New function, taking over the old
role of assign_string when its VALUE was nonnull.
All callers of assign_string changed to use these functions.
(assign_string_n): Clear *STRING if VALUE is null,
to fix a potential double-free.
Paul Eggert 4 年之前
父節點
當前提交
8378991cba
共有 7 個文件被更改,包括 124 次插入100 次删除
  1. 4 3
      configure.ac
  2. 1 0
      gnulib.modules
  3. 72 69
      lib/wordsplit.c
  4. 5 3
      src/buffer.c
  5. 5 7
      src/common.h
  6. 11 11
      src/extract.c
  7. 26 7
      src/misc.c

+ 4 - 3
configure.ac

@@ -112,7 +112,7 @@ if test $ac_cv_lib_error_at_line = no; then
   AC_DEFINE([ENABLE_ERROR_PRINT_PROGNAME],[1],
   AC_DEFINE([ENABLE_ERROR_PRINT_PROGNAME],[1],
             [Enable the use of error_print_progname to print program name with error messages.
             [Enable the use of error_print_progname to print program name with error messages.
 	     See comment to function tar_print_progname in src/tar.c])
 	     See comment to function tar_print_progname in src/tar.c])
-fi  
+fi
 
 
 # paxutils modules
 # paxutils modules
 tar_PAXUTILS
 tar_PAXUTILS
@@ -162,6 +162,7 @@ if test "$gl_gcc_warnings" = yes; then
   nw="$nw -Winline"                 # It's OK to not inline.
   nw="$nw -Winline"                 # It's OK to not inline.
   nw="$nw -Wstrict-overflow"	    # It's OK to optimize strictly.
   nw="$nw -Wstrict-overflow"	    # It's OK to optimize strictly.
   nw="$nw -Wsuggest-attribute=pure" # Too many warnings for now.
   nw="$nw -Wsuggest-attribute=pure" # Too many warnings for now.
+  nw="$nw -Wsystem-headers"         # Don't let system headers trigger warnings
   nw="$nw -Wstack-protector"
   nw="$nw -Wstack-protector"
 
 
   gl_MANYWARN_ALL_GCC([ws])
   gl_MANYWARN_ALL_GCC([ws])
@@ -173,10 +174,10 @@ if test "$gl_gcc_warnings" = yes; then
   gl_WARN_ADD([-Wno-type-limits])      # It's OK to optimize based on types.
   gl_WARN_ADD([-Wno-type-limits])      # It's OK to optimize based on types.
   gl_WARN_ADD([-Wno-unused-parameter]) # Too many warnings for now
   gl_WARN_ADD([-Wno-unused-parameter]) # Too many warnings for now
   gl_WARN_ADD([-Wno-format-nonliteral])
   gl_WARN_ADD([-Wno-format-nonliteral])
-  
+
   gl_WARN_ADD([-fdiagnostics-show-option])
   gl_WARN_ADD([-fdiagnostics-show-option])
   gl_WARN_ADD([-funit-at-a-time])
   gl_WARN_ADD([-funit-at-a-time])
-  
+
 
 
   AC_SUBST([WARN_CFLAGS])
   AC_SUBST([WARN_CFLAGS])
 
 

+ 1 - 0
gnulib.modules

@@ -23,6 +23,7 @@ areadlinkat-with-size
 argmatch
 argmatch
 argp
 argp
 argp-version-etc
 argp-version-etc
+attribute
 backupfile
 backupfile
 closeout
 closeout
 configmake
 configmake

+ 72 - 69
lib/wordsplit.c

@@ -95,7 +95,7 @@ _wsplt_seterr (struct wordsplit *wsp, int ec)
     wordsplit_perror (wsp);
     wordsplit_perror (wsp);
   return ec;
   return ec;
 }
 }
-  
+
 static int
 static int
 _wsplt_nomem (struct wordsplit *wsp)
 _wsplt_nomem (struct wordsplit *wsp)
 {
 {
@@ -126,7 +126,7 @@ _wsplt_subsplit (struct wordsplit *wsp, struct wordsplit *wss,
 		 unsigned flags, int finalize)
 		 unsigned flags, int finalize)
 {
 {
   int rc;
   int rc;
-  
+
   wss->ws_delim = wsp->ws_delim;
   wss->ws_delim = wsp->ws_delim;
   wss->ws_debug = wsp->ws_debug;
   wss->ws_debug = wsp->ws_debug;
   wss->ws_error = wsp->ws_error;
   wss->ws_error = wsp->ws_error;
@@ -150,7 +150,7 @@ _wsplt_subsplit (struct wordsplit *wsp, struct wordsplit *wss,
     }
     }
 
 
   wss->ws_options = wsp->ws_options;
   wss->ws_options = wsp->ws_options;
-  
+
   flags |= WRDSF_DELIM
   flags |= WRDSF_DELIM
          | WRDSF_ALLOC_DIE
          | WRDSF_ALLOC_DIE
          | WRDSF_ERROR
          | WRDSF_ERROR
@@ -209,7 +209,7 @@ wordsplit_init0 (struct wordsplit *wsp)
 }
 }
 
 
 char wordsplit_c_escape_tab[] = "\\\\\"\"a\ab\bf\fn\nr\rt\tv\v";
 char wordsplit_c_escape_tab[] = "\\\\\"\"a\ab\bf\fn\nr\rt\tv\v";
-  
+
 static int
 static int
 wordsplit_init (struct wordsplit *wsp, const char *input, size_t len,
 wordsplit_init (struct wordsplit *wsp, const char *input, size_t len,
 		unsigned flags)
 		unsigned flags)
@@ -282,7 +282,7 @@ wordsplit_init (struct wordsplit *wsp, const char *input, size_t len,
 	{
 	{
 	  wsp->ws_escape[WRDSX_WORD] = wordsplit_c_escape_tab;
 	  wsp->ws_escape[WRDSX_WORD] = wordsplit_c_escape_tab;
 	  wsp->ws_escape[WRDSX_QUOTE] = wordsplit_c_escape_tab;
 	  wsp->ws_escape[WRDSX_QUOTE] = wordsplit_c_escape_tab;
-	  wsp->ws_options |= WRDSO_OESC_QUOTE | WRDSO_OESC_WORD       
+	  wsp->ws_options |= WRDSO_OESC_QUOTE | WRDSO_OESC_WORD
 	                     | WRDSO_XESC_QUOTE | WRDSO_XESC_WORD;
 	                     | WRDSO_XESC_QUOTE | WRDSO_XESC_WORD;
 	}
 	}
       else
       else
@@ -292,16 +292,16 @@ wordsplit_init (struct wordsplit *wsp, const char *input, size_t len,
 	  wsp->ws_options |= WRDSO_BSKEEP_QUOTE;
 	  wsp->ws_options |= WRDSO_BSKEEP_QUOTE;
 	}
 	}
     }
     }
-  
+
   wsp->ws_endp = 0;
   wsp->ws_endp = 0;
   wsp->ws_wordi = 0;
   wsp->ws_wordi = 0;
 
 
   if (wsp->ws_flags & WRDSF_REUSE)
   if (wsp->ws_flags & WRDSF_REUSE)
     wordsplit_free_nodes (wsp);
     wordsplit_free_nodes (wsp);
   wsp->ws_head = wsp->ws_tail = NULL;
   wsp->ws_head = wsp->ws_tail = NULL;
-  
+
   wordsplit_init0 (wsp);
   wordsplit_init0 (wsp);
-  
+
   return 0;
   return 0;
 }
 }
 
 
@@ -424,14 +424,13 @@ wsnode_len (struct wordsplit_node *p)
     return p->v.segm.end - p->v.segm.beg;
     return p->v.segm.end - p->v.segm.beg;
 }
 }
 
 
-static int
-wsnode_new (struct wordsplit *wsp, struct wordsplit_node **pnode)
+static struct wordsplit_node *
+wsnode_new (struct wordsplit *wsp)
 {
 {
   struct wordsplit_node *node = calloc (1, sizeof (*node));
   struct wordsplit_node *node = calloc (1, sizeof (*node));
   if (!node)
   if (!node)
-    return _wsplt_nomem (wsp);
-  *pnode = node;
-  return 0;
+    _wsplt_nomem (wsp);
+  return node;
 }
 }
 
 
 static void
 static void
@@ -527,14 +526,11 @@ wsnode_insert (struct wordsplit *wsp, struct wordsplit_node *node,
 static int
 static int
 wordsplit_add_segm (struct wordsplit *wsp, size_t beg, size_t end, int flg)
 wordsplit_add_segm (struct wordsplit *wsp, size_t beg, size_t end, int flg)
 {
 {
-  struct wordsplit_node *node;
-  int rc;
-
   if (end == beg && !(flg & _WSNF_EMPTYOK))
   if (end == beg && !(flg & _WSNF_EMPTYOK))
     return 0;
     return 0;
-  rc = wsnode_new (wsp, &node);
-  if (rc)
-    return rc;
+  struct wordsplit_node *node = wsnode_new (wsp);
+  if (!node)
+    return 1;
   node->flags = flg & ~(_WSNF_WORD | _WSNF_EMPTYOK);
   node->flags = flg & ~(_WSNF_WORD | _WSNF_EMPTYOK);
   node->v.segm.beg = beg;
   node->v.segm.beg = beg;
   node->v.segm.end = end;
   node->v.segm.end = end;
@@ -587,7 +583,7 @@ coalesce_segment (struct wordsplit *wsp, struct wordsplit_node *node)
 
 
   if (!(node->flags & _WSNF_JOIN))
   if (!(node->flags & _WSNF_JOIN))
     return 0;
     return 0;
-  
+
   for (p = node; p && (p->flags & _WSNF_JOIN); p = p->next)
   for (p = node; p && (p->flags & _WSNF_JOIN); p = p->next)
     {
     {
       len += wsnode_len (p);
       len += wsnode_len (p);
@@ -717,7 +713,7 @@ wordsplit_finish (struct wordsplit *wsp)
 
 
      Nodes of type _WSNF_DELIM get inserted to the node list if either
      Nodes of type _WSNF_DELIM get inserted to the node list if either
      WRDSF_RETURN_DELIMS flag or WRDSO_MAXWORDS option is set.
      WRDSF_RETURN_DELIMS flag or WRDSO_MAXWORDS option is set.
-     
+
      The following cases should be distinguished:
      The following cases should be distinguished:
 
 
      1. If both WRDSF_SQUEEZE_DELIMS and WRDSF_RETURN_DELIMS are set, compress
      1. If both WRDSF_SQUEEZE_DELIMS and WRDSF_RETURN_DELIMS are set, compress
@@ -781,7 +777,7 @@ wordsplit_finish (struct wordsplit *wsp)
 	      continue;
 	      continue;
 	    }
 	    }
 	}
 	}
-      else 
+      else
 	{
 	{
 	  if (delim)
 	  if (delim)
 	    {
 	    {
@@ -900,11 +896,11 @@ node_split_prefix (struct wordsplit *wsp,
 		   struct wordsplit_node *node,
 		   struct wordsplit_node *node,
 		   size_t beg, size_t len, int flg)
 		   size_t beg, size_t len, int flg)
 {
 {
-  struct wordsplit_node *newnode;
 
 
   if (len == 0)
   if (len == 0)
     return 0;
     return 0;
-  if (wsnode_new (wsp, &newnode))
+  struct wordsplit_node *newnode = wsnode_new (wsp);
+  if (!newnode)
     return 1;
     return 1;
   wsnode_insert (wsp, newnode, *ptail, 0);
   wsnode_insert (wsp, newnode, *ptail, 0);
   if (node->flags & _WSNF_WORD)
   if (node->flags & _WSNF_WORD)
@@ -958,7 +954,7 @@ find_closing_paren (const char *str, size_t i, size_t len, size_t *poff,
 		  break;
 		  break;
 		}
 		}
 	      break;
 	      break;
-	      
+
 	    case '"':
 	    case '"':
 	      state = st_dquote;
 	      state = st_dquote;
 	      break;
 	      break;
@@ -1038,7 +1034,7 @@ wsplt_assign_var (struct wordsplit *wsp, const char *name, size_t namelen,
 {
 {
   int n = (wsp->ws_flags & WRDSF_ENV_KV) ? 2 : 1;
   int n = (wsp->ws_flags & WRDSF_ENV_KV) ? 2 : 1;
   char *v;
   char *v;
-  
+
   if (wsp->ws_envidx + n >= wsp->ws_envsiz)
   if (wsp->ws_envidx + n >= wsp->ws_envsiz)
     {
     {
       size_t sz;
       size_t sz;
@@ -1055,7 +1051,7 @@ wsplt_assign_var (struct wordsplit *wsp, const char *name, size_t namelen,
 		  for (; wsp->ws_env[i]; i++)
 		  for (; wsp->ws_env[i]; i++)
 		    ;
 		    ;
 		}
 		}
-	      
+
 	      sz = i + n + 1;
 	      sz = i + n + 1;
 
 
 	      newenv = calloc (sz, sizeof(newenv[0]));
 	      newenv = calloc (sz, sizeof(newenv[0]));
@@ -1075,7 +1071,7 @@ wsplt_assign_var (struct wordsplit *wsp, const char *name, size_t namelen,
 		    }
 		    }
 		}
 		}
 	      newenv[j] = NULL;
 	      newenv[j] = NULL;
-	      
+
 	      wsp->ws_envbuf = newenv;
 	      wsp->ws_envbuf = newenv;
 	      wsp->ws_envidx = i;
 	      wsp->ws_envidx = i;
 	      wsp->ws_envsiz = sz;
 	      wsp->ws_envsiz = sz;
@@ -1104,7 +1100,7 @@ wsplt_assign_var (struct wordsplit *wsp, const char *name, size_t namelen,
 	  wsp->ws_env = (const char**) wsp->ws_envbuf;
 	  wsp->ws_env = (const char**) wsp->ws_envbuf;
 	}
 	}
     }
     }
-  
+
   if (wsp->ws_flags & WRDSF_ENV_KV)
   if (wsp->ws_flags & WRDSF_ENV_KV)
     {
     {
       /* A key-value pair environment */
       /* A key-value pair environment */
@@ -1149,7 +1145,7 @@ expvar (struct wordsplit *wsp, const char *str, size_t len,
   const char *start = str - 1;
   const char *start = str - 1;
   int rc;
   int rc;
   struct wordsplit ws;
   struct wordsplit ws;
-  
+
   if (ISVARBEG (str[0]))
   if (ISVARBEG (str[0]))
     {
     {
       for (i = 1; i < len; i++)
       for (i = 1; i < len; i++)
@@ -1166,7 +1162,7 @@ expvar (struct wordsplit *wsp, const char *str, size_t len,
 	  if (str[i] == ':')
 	  if (str[i] == ':')
 	    {
 	    {
 	      size_t j;
 	      size_t j;
-	      
+
 	      defstr = str + i + 1;
 	      defstr = str + i + 1;
 	      if (find_closing_paren (str, i + 1, len, &j, "{}"))
 	      if (find_closing_paren (str, i + 1, len, &j, "{}"))
 		return _wsplt_seterr (wsp, WRDSE_CBRACE);
 		return _wsplt_seterr (wsp, WRDSE_CBRACE);
@@ -1182,7 +1178,7 @@ expvar (struct wordsplit *wsp, const char *str, size_t len,
 	  else if (strchr ("-+?=", str[i]))
 	  else if (strchr ("-+?=", str[i]))
 	    {
 	    {
 	      size_t j;
 	      size_t j;
-	      
+
 	      defstr = str + i;
 	      defstr = str + i;
 	      if (find_closing_paren (str, i, len, &j, "{}"))
 	      if (find_closing_paren (str, i, len, &j, "{}"))
 		return _wsplt_seterr (wsp, WRDSE_CBRACE);
 		return _wsplt_seterr (wsp, WRDSE_CBRACE);
@@ -1195,7 +1191,8 @@ expvar (struct wordsplit *wsp, const char *str, size_t len,
     }
     }
   else
   else
     {
     {
-      if (wsnode_new (wsp, &newnode))
+      newnode = wsnode_new (wsp);
+      if (!newnode)
 	return 1;
 	return 1;
       wsnode_insert (wsp, newnode, *ptail, 0);
       wsnode_insert (wsp, newnode, *ptail, 0);
       *ptail = newnode;
       *ptail = newnode;
@@ -1247,7 +1244,7 @@ expvar (struct wordsplit *wsp, const char *str, size_t len,
 	  rc = WRDSE_UNDEF;
 	  rc = WRDSE_UNDEF;
 	}
 	}
     }
     }
-  
+
   switch (rc)
   switch (rc)
     {
     {
     case WRDSE_OK:
     case WRDSE_OK:
@@ -1267,7 +1264,7 @@ expvar (struct wordsplit *wsp, const char *str, size_t len,
 	  wordsplit_free (&ws);
 	  wordsplit_free (&ws);
 	}
 	}
       break;
       break;
-      
+
     case WRDSE_UNDEF:
     case WRDSE_UNDEF:
       if (defstr)
       if (defstr)
 	{
 	{
@@ -1287,11 +1284,11 @@ expvar (struct wordsplit *wsp, const char *str, size_t len,
 	      value = ws.ws_wordv[0];
 	      value = ws.ws_wordv[0];
 	      ws.ws_wordv[0] = NULL;
 	      ws.ws_wordv[0] = NULL;
 	      wordsplit_free (&ws);
 	      wordsplit_free (&ws);
-	      
+
 	      if (defstr[-1] == '=')
 	      if (defstr[-1] == '=')
 		wsplt_assign_var (wsp, str, i, value);
 		wsplt_assign_var (wsp, str, i, value);
 	    }
 	    }
-	  else 
+	  else
 	    {
 	    {
 	      if (*defstr == '?')
 	      if (*defstr == '?')
 		{
 		{
@@ -1339,7 +1336,7 @@ expvar (struct wordsplit *wsp, const char *str, size_t len,
 	    }
 	    }
 	}
 	}
       break;
       break;
-      
+
     case WRDSE_NOSPACE:
     case WRDSE_NOSPACE:
       return _wsplt_nomem (wsp);
       return _wsplt_nomem (wsp);
 
 
@@ -1357,7 +1354,8 @@ expvar (struct wordsplit *wsp, const char *str, size_t len,
     {
     {
       if (flg & _WSNF_QUOTE)
       if (flg & _WSNF_QUOTE)
 	{
 	{
-	  if (wsnode_new (wsp, &newnode))
+	  newnode = wsnode_new (wsp);
+	  if (!newnode)
 	    {
 	    {
 	      free (value);
 	      free (value);
 	      return 1;
 	      return 1;
@@ -1371,7 +1369,8 @@ expvar (struct wordsplit *wsp, const char *str, size_t len,
 	{
 	{
 	  free (value);
 	  free (value);
 	  /* Empty string is a special case */
 	  /* Empty string is a special case */
-	  if (wsnode_new (wsp, &newnode))
+	  newnode = wsnode_new (wsp);
+	  if (!newnode)
 	    return 1;
 	    return 1;
 	  wsnode_insert (wsp, newnode, *ptail, 0);
 	  wsnode_insert (wsp, newnode, *ptail, 0);
 	  *ptail = newnode;
 	  *ptail = newnode;
@@ -1381,7 +1380,7 @@ expvar (struct wordsplit *wsp, const char *str, size_t len,
 	{
 	{
 	  struct wordsplit ws;
 	  struct wordsplit ws;
 	  int rc;
 	  int rc;
-	  
+
 	  rc = _wsplt_subsplit (wsp, &ws, value, strlen (value),
 	  rc = _wsplt_subsplit (wsp, &ws, value, strlen (value),
 				WRDSF_NOVAR | WRDSF_NOCMD |
 				WRDSF_NOVAR | WRDSF_NOCMD |
 				WRDSF_QUOTE
 				WRDSF_QUOTE
@@ -1404,7 +1403,8 @@ expvar (struct wordsplit *wsp, const char *str, size_t len,
     {
     {
       size_t size = *pend - start + 1;
       size_t size = *pend - start + 1;
 
 
-      if (wsnode_new (wsp, &newnode))
+      newnode = wsnode_new (wsp);
+      if (!newnode)
 	return 1;
 	return 1;
       wsnode_insert (wsp, newnode, *ptail, 0);
       wsnode_insert (wsp, newnode, *ptail, 0);
       *ptail = newnode;
       *ptail = newnode;
@@ -1417,7 +1417,8 @@ expvar (struct wordsplit *wsp, const char *str, size_t len,
     }
     }
   else
   else
     {
     {
-      if (wsnode_new (wsp, &newnode))
+      newnode = wsnode_new (wsp);
+      if (!newnode)
 	return 1;
 	return 1;
       wsnode_insert (wsp, newnode, *ptail, 0);
       wsnode_insert (wsp, newnode, *ptail, 0);
       *ptail = newnode;
       *ptail = newnode;
@@ -1486,7 +1487,7 @@ node_expand (struct wordsplit *wsp, struct wordsplit_node *node,
     }
     }
   return 0;
   return 0;
 }
 }
-  
+
 /* Remove NULL nodes from the list */
 /* Remove NULL nodes from the list */
 static void
 static void
 wsnode_nullelim (struct wordsplit *wsp)
 wsnode_nullelim (struct wordsplit *wsp)
@@ -1539,7 +1540,7 @@ expcmd (struct wordsplit *wsp, const char *str, size_t len,
   size_t j;
   size_t j;
   char *value;
   char *value;
   struct wordsplit_node *newnode;
   struct wordsplit_node *newnode;
-  
+
   str++;
   str++;
   len--;
   len--;
 
 
@@ -1566,7 +1567,7 @@ expcmd (struct wordsplit *wsp, const char *str, size_t len,
     }
     }
   else
   else
     rc = wsp->ws_command (&value, str, j, NULL, wsp->ws_closure);
     rc = wsp->ws_command (&value, str, j, NULL, wsp->ws_closure);
-  
+
   if (rc == WRDSE_NOSPACE)
   if (rc == WRDSE_NOSPACE)
     return _wsplt_nomem (wsp);
     return _wsplt_nomem (wsp);
   else if (rc)
   else if (rc)
@@ -1585,7 +1586,8 @@ expcmd (struct wordsplit *wsp, const char *str, size_t len,
     {
     {
       if (flg & _WSNF_QUOTE)
       if (flg & _WSNF_QUOTE)
 	{
 	{
-	  if (wsnode_new (wsp, &newnode))
+	  newnode = wsnode_new (wsp);
+	  if (!newnode)
 	    return 1;
 	    return 1;
 	  wsnode_insert (wsp, newnode, *ptail, 0);
 	  wsnode_insert (wsp, newnode, *ptail, 0);
 	  *ptail = newnode;
 	  *ptail = newnode;
@@ -1596,7 +1598,8 @@ expcmd (struct wordsplit *wsp, const char *str, size_t len,
 	{
 	{
 	  free (value);
 	  free (value);
 	  /* Empty string is a special case */
 	  /* Empty string is a special case */
-	  if (wsnode_new (wsp, &newnode))
+	  newnode = wsnode_new (wsp);
+	  if (!newnode)
 	    return 1;
 	    return 1;
 	  wsnode_insert (wsp, newnode, *ptail, 0);
 	  wsnode_insert (wsp, newnode, *ptail, 0);
 	  *ptail = newnode;
 	  *ptail = newnode;
@@ -1627,7 +1630,8 @@ expcmd (struct wordsplit *wsp, const char *str, size_t len,
     }
     }
   else
   else
     {
     {
-      if (wsnode_new (wsp, &newnode))
+      newnode = wsnode_new (wsp);
+      if (!newnode)
 	return 1;
 	return 1;
       wsnode_insert (wsp, newnode, *ptail, 0);
       wsnode_insert (wsp, newnode, *ptail, 0);
       *ptail = newnode;
       *ptail = newnode;
@@ -1674,13 +1678,13 @@ wordsplit_trimws (struct wordsplit *wsp)
 	    ;
 	    ;
 	  p->v.segm.beg = n;
 	  p->v.segm.beg = n;
 	}
 	}
-      
+
       while (p->next && (p->flags & _WSNF_JOIN))
       while (p->next && (p->flags & _WSNF_JOIN))
 	p = p->next;
 	p = p->next;
-      
+
       if (p->flags & _WSNF_QUOTE)
       if (p->flags & _WSNF_QUOTE)
 	continue;
 	continue;
-      
+
       /* Trim trailing whitespace */
       /* Trim trailing whitespace */
       for (n = p->v.segm.end;
       for (n = p->v.segm.end;
 	   n > p->v.segm.beg && ISWS (wsp->ws_input[n - 1]); n--);
 	   n > p->v.segm.beg && ISWS (wsp->ws_input[n - 1]); n--);
@@ -1699,7 +1703,7 @@ wordsplit_tildexpand (struct wordsplit *wsp)
   struct wordsplit_node *p;
   struct wordsplit_node *p;
   char *uname = NULL;
   char *uname = NULL;
   size_t usize = 0;
   size_t usize = 0;
-  
+
   for (p = wsp->ws_head; p; p = p->next)
   for (p = wsp->ws_head; p; p = p->next)
     {
     {
       const char *str;
       const char *str;
@@ -1714,7 +1718,7 @@ wordsplit_tildexpand (struct wordsplit *wsp)
 	  size_t slen = wsnode_len (p);
 	  size_t slen = wsnode_len (p);
 	  struct passwd *pw;
 	  struct passwd *pw;
 	  char *newstr;
 	  char *newstr;
-	  
+
 	  for (i = 1; i < slen && str[i] != '/'; i++)
 	  for (i = 1; i < slen && str[i] != '/'; i++)
 	    ;
 	    ;
 	  if (i == slen)
 	  if (i == slen)
@@ -1788,7 +1792,7 @@ wordsplit_pathexpand (struct wordsplit *wsp)
   if (wsp->ws_options & WRDSO_DOTGLOB)
   if (wsp->ws_options & WRDSO_DOTGLOB)
     flags = GLOB_PERIOD;
     flags = GLOB_PERIOD;
 #endif
 #endif
-  
+
   for (p = wsp->ws_head; p; p = next)
   for (p = wsp->ws_head; p; p = next)
     {
     {
       const char *str;
       const char *str;
@@ -1807,23 +1811,23 @@ wordsplit_pathexpand (struct wordsplit *wsp)
 	  glob_t g;
 	  glob_t g;
 	  struct wordsplit_node *prev;
 	  struct wordsplit_node *prev;
 	  char *pattern;
 	  char *pattern;
-	  
+
 	  pattern = malloc (slen + 1);
 	  pattern = malloc (slen + 1);
 	  if (!pattern)
 	  if (!pattern)
 	    return _wsplt_nomem (wsp);
 	    return _wsplt_nomem (wsp);
 	  memcpy (pattern, str, slen);
 	  memcpy (pattern, str, slen);
 	  pattern[slen] = 0;
 	  pattern[slen] = 0;
-      
+
 	  switch (glob (pattern, flags, NULL, &g))
 	  switch (glob (pattern, flags, NULL, &g))
 	    {
 	    {
 	    case 0:
 	    case 0:
 	      free (pattern);
 	      free (pattern);
 	      break;
 	      break;
-	      
+
 	    case GLOB_NOSPACE:
 	    case GLOB_NOSPACE:
 	      free (pattern);
 	      free (pattern);
 	      return _wsplt_nomem (wsp);
 	      return _wsplt_nomem (wsp);
-	      
+
 	    case GLOB_NOMATCH:
 	    case GLOB_NOMATCH:
 	      if (wsp->ws_options & WRDSO_NULLGLOB)
 	      if (wsp->ws_options & WRDSO_NULLGLOB)
 		{
 		{
@@ -1846,7 +1850,7 @@ wordsplit_pathexpand (struct wordsplit *wsp)
 		}
 		}
 	      free (pattern);
 	      free (pattern);
 	      continue;
 	      continue;
-	      
+
 	    default:
 	    default:
 	      free (pattern);
 	      free (pattern);
 	      return _wsplt_seterr (wsp, WRDSE_GLOBERR);
 	      return _wsplt_seterr (wsp, WRDSE_GLOBERR);
@@ -1855,10 +1859,10 @@ wordsplit_pathexpand (struct wordsplit *wsp)
 	  prev = p;
 	  prev = p;
 	  for (i = 0; i < g.gl_pathc; i++)
 	  for (i = 0; i < g.gl_pathc; i++)
 	    {
 	    {
-	      struct wordsplit_node *newnode;
+	      struct wordsplit_node *newnode = wsnode_new (wsp);
 	      char *newstr;
 	      char *newstr;
-	      
-	      if (wsnode_new (wsp, &newnode))
+
+	      if (!newnode)
 		return 1;
 		return 1;
 	      newstr = strdup (g.gl_pathv[i]);
 	      newstr = strdup (g.gl_pathv[i]);
 	      if (!newstr)
 	      if (!newstr)
@@ -1975,7 +1979,7 @@ scan_word (struct wordsplit *wsp, size_t start, int consume_all)
   int join = 0;
   int join = 0;
   unsigned flags = 0;
   unsigned flags = 0;
   struct wordsplit_node *np = wsp->ws_tail;
   struct wordsplit_node *np = wsp->ws_tail;
-  
+
   size_t i = start;
   size_t i = start;
 
 
   if (i >= len)
   if (i >= len)
@@ -2064,7 +2068,7 @@ scan_word (struct wordsplit *wsp, size_t start, int consume_all)
   wsp->ws_endp = i;
   wsp->ws_endp = i;
   if (wsp->ws_flags & WRDSF_INCREMENTAL)
   if (wsp->ws_flags & WRDSF_INCREMENTAL)
     return _WRDS_EOF;
     return _WRDS_EOF;
-  
+
   if (consume_all)
   if (consume_all)
     {
     {
       if (!np)
       if (!np)
@@ -2075,7 +2079,7 @@ scan_word (struct wordsplit *wsp, size_t start, int consume_all)
 	  np = np->next;
 	  np = np->next;
 	}
 	}
     }
     }
-  
+
   return _WRDS_OK;
   return _WRDS_OK;
 }
 }
 
 
@@ -2342,7 +2346,7 @@ wordsplit_process_list (struct wordsplit *wsp, size_t start)
   if (wsp->ws_flags & WRDSF_SHOWDBG)
   if (wsp->ws_flags & WRDSF_SHOWDBG)
     wsp->ws_debug (_("(%02d) Input:%.*s;"),
     wsp->ws_debug (_("(%02d) Input:%.*s;"),
 		   wsp->ws_lvl, (int) wsp->ws_len, wsp->ws_input);
 		   wsp->ws_lvl, (int) wsp->ws_len, wsp->ws_input);
-  
+
   if ((wsp->ws_flags & WRDSF_NOSPLIT)
   if ((wsp->ws_flags & WRDSF_NOSPLIT)
       || ((wsp->ws_options & WRDSO_MAXWORDS)
       || ((wsp->ws_options & WRDSO_MAXWORDS)
 	  && wsp->ws_wordi + 1 == wsp->ws_maxwords))
 	  && wsp->ws_wordi + 1 == wsp->ws_maxwords))
@@ -2438,7 +2442,7 @@ wordsplit_run (const char *command, size_t length, struct wordsplit *wsp,
 }
 }
 
 
 int
 int
-wordsplit_len (const char *command, size_t length, struct wordsplit *wsp, 
+wordsplit_len (const char *command, size_t length, struct wordsplit *wsp,
                unsigned flags)
                unsigned flags)
 {
 {
   return wordsplit_run (command, length, wsp, flags, 0);
   return wordsplit_run (command, length, wsp, flags, 0);
@@ -2559,4 +2563,3 @@ wordsplit_perror (struct wordsplit *wsp)
       wsp->ws_error ("%s", wordsplit_strerror (wsp));
       wsp->ws_error ("%s", wordsplit_strerror (wsp));
     }
     }
 }
 }
-

+ 5 - 3
src/buffer.c

@@ -28,6 +28,7 @@
 #include <fnmatch.h>
 #include <fnmatch.h>
 #include <human.h>
 #include <human.h>
 #include <quotearg.h>
 #include <quotearg.h>
+#include <verify.h>
 
 
 #include "common.h"
 #include "common.h"
 #include <rmt.h>
 #include <rmt.h>
@@ -1325,8 +1326,8 @@ new_volume (enum access_mode mode)
   if (verify_option)
   if (verify_option)
     verify_volume ();
     verify_volume ();
 
 
-  assign_string (&volume_label, NULL);
-  assign_string (&continued_file_name, NULL);
+  assign_null (&volume_label);
+  assign_null (&continued_file_name);
   continued_file_size = continued_file_offset = 0;
   continued_file_size = continued_file_offset = 0;
   current_block = record_start;
   current_block = record_start;
 
 
@@ -1505,7 +1506,7 @@ try_new_volume (void)
       ASSIGN_STRING_N (&volume_label, current_header->header.name);
       ASSIGN_STRING_N (&volume_label, current_header->header.name);
       set_next_block_after (header);
       set_next_block_after (header);
       header = find_next_block ();
       header = find_next_block ();
-      if (header->header.typeflag != GNUTYPE_MULTIVOL)
+      if (! (header && header->header.typeflag == GNUTYPE_MULTIVOL))
         break;
         break;
       FALLTHROUGH;
       FALLTHROUGH;
     case GNUTYPE_MULTIVOL:
     case GNUTYPE_MULTIVOL:
@@ -1688,6 +1689,7 @@ _write_volume_label (const char *str)
     {
     {
       union block *label = find_next_block ();
       union block *label = find_next_block ();
 
 
+      assume (label);
       memset (label, 0, BLOCKSIZE);
       memset (label, 0, BLOCKSIZE);
 
 
       strcpy (label->header.name, str);
       strcpy (label->header.name, str);

+ 5 - 7
src/common.h

@@ -43,18 +43,13 @@
 # define GLOBAL extern
 # define GLOBAL extern
 #endif
 #endif
 
 
-#if 7 <= __GNUC__
-# define FALLTHROUGH __attribute__ ((__fallthrough__))
-#else
-# define FALLTHROUGH ((void) 0)
-#endif
-
 #define TAREXIT_SUCCESS PAXEXIT_SUCCESS
 #define TAREXIT_SUCCESS PAXEXIT_SUCCESS
 #define TAREXIT_DIFFERS PAXEXIT_DIFFERS
 #define TAREXIT_DIFFERS PAXEXIT_DIFFERS
 #define TAREXIT_FAILURE PAXEXIT_FAILURE
 #define TAREXIT_FAILURE PAXEXIT_FAILURE
 
 
 
 
 #include "arith.h"
 #include "arith.h"
+#include <attribute.h>
 #include <backupfile.h>
 #include <backupfile.h>
 #include <exclude.h>
 #include <exclude.h>
 #include <full-write.h>
 #include <full-write.h>
@@ -633,7 +628,10 @@ void skip_member (void);
 #define max(a, b) ((a) < (b) ? (b) : (a))
 #define max(a, b) ((a) < (b) ? (b) : (a))
 
 
 char const *quote_n_colon (int n, char const *arg);
 char const *quote_n_colon (int n, char const *arg);
-void assign_string (char **dest, const char *src);
+void assign_string_or_null (char **dest, const char *src)
+  ATTRIBUTE_NONNULL ((1));
+void assign_string (char **dest, const char *src) ATTRIBUTE_NONNULL ((1, 2));
+void assign_null (char **dest) ATTRIBUTE_NONNULL ((1));
 void assign_string_n (char **string, const char *value, size_t n);
 void assign_string_n (char **string, const char *value, size_t n);
 #define ASSIGN_STRING_N(s,v) assign_string_n (s, v, sizeof (v))
 #define ASSIGN_STRING_N(s,v) assign_string_n (s, v, sizeof (v))
 int unquote_string (char *str);
 int unquote_string (char *str);

+ 11 - 11
src/extract.c

@@ -520,7 +520,7 @@ delay_set_stat (char const *file_name, struct tar_stat_info const *st,
   data->change_dir = chdir_current;
   data->change_dir = chdir_current;
   data->cntx_name = NULL;
   data->cntx_name = NULL;
   if (st)
   if (st)
-    assign_string (&data->cntx_name, st->cntx_name);
+    assign_string_or_null (&data->cntx_name, st->cntx_name);
   if (st && st->acls_a_ptr)
   if (st && st->acls_a_ptr)
     {
     {
       data->acls_a_ptr = xmemdup (st->acls_a_ptr, st->acls_a_len + 1);
       data->acls_a_ptr = xmemdup (st->acls_a_ptr, st->acls_a_len + 1);
@@ -1329,7 +1329,7 @@ extract_file (char *file_name, int typeflag)
    first. If it doesn't exist, there is no matching entry in the list.
    first. If it doesn't exist, there is no matching entry in the list.
    Otherwise, look for the entry in list which has the matching dev
    Otherwise, look for the entry in list which has the matching dev
    and ino numbers.
    and ino numbers.
-   
+
    This approach avoids scanning the singly-linked list in obvious cases
    This approach avoids scanning the singly-linked list in obvious cases
    and does not rely on comparing file names, which may differ for
    and does not rely on comparing file names, which may differ for
    various reasons (e.g. relative vs. absolute file names).
    various reasons (e.g. relative vs. absolute file names).
@@ -1342,14 +1342,14 @@ find_delayed_link_source (char const *name)
 
 
   if (!delayed_link_head)
   if (!delayed_link_head)
     return NULL;
     return NULL;
-  
+
   if (fstatat (chdir_fd, name, &st, AT_SYMLINK_NOFOLLOW))
   if (fstatat (chdir_fd, name, &st, AT_SYMLINK_NOFOLLOW))
     {
     {
       if (errno != ENOENT)
       if (errno != ENOENT)
 	stat_error (name);
 	stat_error (name);
       return NULL;
       return NULL;
     }
     }
-  
+
   for (dl = delayed_link_head; dl; dl = dl->next)
   for (dl = delayed_link_head; dl; dl = dl->next)
     {
     {
       if (dl->dev == st.st_dev && dl->ino == st.st_ino)
       if (dl->dev == st.st_dev && dl->ino == st.st_ino)
@@ -1357,7 +1357,7 @@ find_delayed_link_source (char const *name)
     }
     }
   return dl;
   return dl;
 }
 }
-  
+
 /* Create a placeholder file with name FILE_NAME, which will be
 /* Create a placeholder file with name FILE_NAME, which will be
    replaced after other extraction is done by a symbolic link if
    replaced after other extraction is done by a symbolic link if
    IS_SYMLINK is true, and by a hard link otherwise.  Set
    IS_SYMLINK is true, and by a hard link otherwise.  Set
@@ -1385,7 +1385,7 @@ create_placeholder_file (char *file_name, bool is_symlink, bool *interdir_made,
 	   */
 	   */
 	  return 0;
 	  return 0;
 	}
 	}
-      
+
       switch (maybe_recoverable (file_name, false, interdir_made))
       switch (maybe_recoverable (file_name, false, interdir_made))
 	{
 	{
 	case RECOVER_OK:
 	case RECOVER_OK:
@@ -1442,7 +1442,7 @@ create_placeholder_file (char *file_name, bool is_symlink, bool *interdir_made,
       p->sources->next = 0;
       p->sources->next = 0;
       strcpy (p->sources->string, file_name);
       strcpy (p->sources->string, file_name);
       p->cntx_name = NULL;
       p->cntx_name = NULL;
-      assign_string (&p->cntx_name, current_stat_info.cntx_name);
+      assign_string_or_null (&p->cntx_name, current_stat_info.cntx_name);
       p->acls_a_ptr = NULL;
       p->acls_a_ptr = NULL;
       p->acls_a_len = 0;
       p->acls_a_len = 0;
       p->acls_d_ptr = NULL;
       p->acls_d_ptr = NULL;
@@ -1467,7 +1467,7 @@ extract_link (char *file_name, int typeflag)
   char const *link_name;
   char const *link_name;
   int rc;
   int rc;
   struct delayed_link *dl;
   struct delayed_link *dl;
-  
+
   link_name = current_stat_info.link_name;
   link_name = current_stat_info.link_name;
 
 
   if (! absolute_names_option && contains_dot_dot (link_name))
   if (! absolute_names_option && contains_dot_dot (link_name))
@@ -1475,7 +1475,7 @@ extract_link (char *file_name, int typeflag)
   dl = find_delayed_link_source (link_name);
   dl = find_delayed_link_source (link_name);
   if (dl)
   if (dl)
     return create_placeholder_file (file_name, false, &interdir_made, dl);
     return create_placeholder_file (file_name, false, &interdir_made, dl);
-  
+
   do
   do
     {
     {
       struct stat st1, st2;
       struct stat st1, st2;
@@ -1697,7 +1697,7 @@ prepare_to_extract (char const *file_name, int typeflag, tar_extractor_t *fun)
 
 
     case GNUTYPE_VOLHDR:
     case GNUTYPE_VOLHDR:
       return false;
       return false;
-      
+
     case GNUTYPE_MULTIVOL:
     case GNUTYPE_MULTIVOL:
       ERROR ((0, 0,
       ERROR ((0, 0,
 	      _("%s: Cannot extract -- file is continued from another volume"),
 	      _("%s: Cannot extract -- file is continued from another volume"),
@@ -1753,7 +1753,7 @@ prepare_to_extract (char const *file_name, int typeflag, tar_extractor_t *fun)
 	}
 	}
     }
     }
   *fun = extractor;
   *fun = extractor;
-  
+
   return true;
   return true;
 }
 }
 
 

+ 26 - 7
src/misc.c

@@ -42,11 +42,28 @@ quote_n_colon (int n, char const *arg)
 
 
 /* Assign STRING to a copy of VALUE if not zero, or to zero.  If
 /* Assign STRING to a copy of VALUE if not zero, or to zero.  If
    STRING was nonzero, it is freed first.  */
    STRING was nonzero, it is freed first.  */
+void
+assign_string_or_null (char **string, const char *value)
+{
+  if (value)
+    assign_string (string, value);
+  else
+    assign_null (string);
+}
+
 void
 void
 assign_string (char **string, const char *value)
 assign_string (char **string, const char *value)
 {
 {
   free (*string);
   free (*string);
-  *string = value ? xstrdup (value) : 0;
+  *string = xstrdup (value);
+}
+
+void
+assign_null (char **string)
+{
+  char *old = *string;
+  *string = NULL;
+  free (old);
 }
 }
 
 
 void
 void
@@ -61,6 +78,8 @@ assign_string_n (char **string, const char *value, size_t n)
       p[l] = 0;
       p[l] = 0;
       *string = p;
       *string = p;
     }
     }
+  else
+    *string = NULL;
 }
 }
 
 
 #if 0
 #if 0
@@ -715,7 +734,7 @@ maybe_backup_file (const char *file_name, bool this_is_the_archive)
      possible, real problems are unlikely.  Doing any better would require a
      possible, real problems are unlikely.  Doing any better would require a
      convention, GNU-wide, for all programs doing backups.  */
      convention, GNU-wide, for all programs doing backups.  */
 
 
-  assign_string (&after_backup_name, 0);
+  assign_null (&after_backup_name);
 
 
   /* Check if we really need to backup the file.  */
   /* Check if we really need to backup the file.  */
 
 
@@ -758,7 +777,7 @@ maybe_backup_file (const char *file_name, bool this_is_the_archive)
       ERROR ((0, e, _("%s: Cannot rename to %s"),
       ERROR ((0, e, _("%s: Cannot rename to %s"),
 	      quotearg_colon (before_backup_name),
 	      quotearg_colon (before_backup_name),
 	      quote_n (1, after_backup_name)));
 	      quote_n (1, after_backup_name)));
-      assign_string (&after_backup_name, 0);
+      assign_null (&after_backup_name);
       return false;
       return false;
     }
     }
 }
 }
@@ -782,7 +801,7 @@ undo_last_backup (void)
 	fprintf (stdlis, _("Renaming %s back to %s\n"),
 	fprintf (stdlis, _("Renaming %s back to %s\n"),
 		 quote_n (0, after_backup_name),
 		 quote_n (0, after_backup_name),
 		 quote_n (1, before_backup_name));
 		 quote_n (1, before_backup_name));
-      assign_string (&after_backup_name, 0);
+      assign_null (&after_backup_name);
     }
     }
 }
 }
 
 
@@ -1041,11 +1060,11 @@ tar_getcdpath (int idx)
     {
     {
       int i;
       int i;
       int save_cwdi = chdir_current;
       int save_cwdi = chdir_current;
-      
+
       for (i = idx; i >= 0; i--)
       for (i = idx; i >= 0; i--)
 	if (wd[i].abspath)
 	if (wd[i].abspath)
 	  break;
 	  break;
-      
+
       while (++i <= idx)
       while (++i <= idx)
 	{
 	{
 	  chdir_do (i);
 	  chdir_do (i);
@@ -1069,7 +1088,7 @@ tar_getcdpath (int idx)
 
 
       chdir_do (save_cwdi);
       chdir_do (save_cwdi);
     }
     }
-	   
+
   return wd[idx].abspath;
   return wd[idx].abspath;
 }
 }