]> git.ipfire.org Git - thirdparty/tar.git/commitdiff
Diagnose argp overflow
authorPaul Eggert <eggert@cs.ucla.edu>
Sat, 3 Aug 2024 18:55:39 +0000 (11:55 -0700)
committerPaul Eggert <eggert@cs.ucla.edu>
Sun, 4 Aug 2024 08:41:43 +0000 (01:41 -0700)
* src/names.c (handle_option):
* src/tar.c (parse_default_options):
Report an error if wordsplitting yields more than INT_MAX words,
rather than misbehaving.  argp_parse can’t handle more than
INT_MAX, unfortunately.

src/names.c
src/tar.c

index 77b285c6b92694920b220da171a55d330c063108..143fbef7c736c509e007d7fc75c170339ec14cdb 100644 (file)
@@ -988,7 +988,6 @@ static int
 handle_option (const char *str, struct name_elt const *ent)
 {
   struct wordsplit ws;
-  int i;
   struct option_locus loc;
 
   while (*str && c_isspace (*str))
@@ -1000,14 +999,15 @@ handle_option (const char *str, struct name_elt const *ent)
   if (wordsplit (str, &ws, WRDSF_DEFFLAGS|WRDSF_DOOFFS))
     FATAL_ERROR ((0, 0, _("cannot split string '%s': %s"),
                  str, wordsplit_strerror (&ws)));
+  int argc;
+  if (ckd_add (&argc, ws.ws_wordc, ws.ws_offs))
+    FATAL_ERROR ((0, 0, _("too many options")));
   ws.ws_wordv[0] = (char *) program_name;
   loc.source = OPTS_FILE;
   loc.name = ent->v.file.name;
   loc.line = ent->v.file.line;
-  more_options (ws.ws_wordc+ws.ws_offs, ws.ws_wordv, &loc);
-  for (i = 0; i < ws.ws_wordc+ws.ws_offs; i++)
-    ws.ws_wordv[i] = NULL;
-
+  more_options (argc, ws.ws_wordv, &loc);
+  memset (ws.ws_wordv, 0, argc * sizeof *ws.ws_wordv);
   wordsplit_free (&ws);
   return 0;
 }
index 4d592caf74814d7364c470f7c25dc1a049459a75..4cb074687acc7c68b1e64587ad8c14f12a394353 100644 (file)
--- a/src/tar.c
+++ b/src/tar.c
@@ -2387,10 +2387,11 @@ parse_default_options (struct tar_args *args)
       ws.ws_wordv[0] = (char*) program_name;
       save_loc_ptr = args->loc;
       args->loc = &loc;
-      if (argp_parse (&argp,
-                     ws.ws_offs + ws.ws_wordc,
-                     ws.ws_wordv,
-                     ARGP_IN_ORDER|ARGP_NO_EXIT, &idx, args))
+      int argc;
+      if (ckd_add (&argc, ws.ws_offs, ws.ws_wordc))
+       FATAL_ERROR ((0, 0, "too many options"));
+      if (argp_parse (&argp, argc, ws.ws_wordv,
+                     ARGP_IN_ORDER | ARGP_NO_EXIT, &idx, args))
        abort (); /* shouldn't happen */
       args->loc = save_loc_ptr;
       if (name_more_files ())