From: Paul Eggert Date: Sat, 3 Aug 2024 18:55:39 +0000 (-0700) Subject: Diagnose argp overflow X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=dab2830e38b40e2f32c916d42a9c5946d7685ed1;p=thirdparty%2Ftar.git Diagnose argp overflow * 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. --- diff --git a/src/names.c b/src/names.c index 77b285c6..143fbef7 100644 --- a/src/names.c +++ b/src/names.c @@ -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; } diff --git a/src/tar.c b/src/tar.c index 4d592caf..4cb07468 100644 --- 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 ())