88 lines
2.8 KiB
Diff
88 lines
2.8 KiB
Diff
From 7219e1ddc1e8606dda18c1105df0d45d8e8e0e09 Mon Sep 17 00:00:00 2001
|
|
From: Richard Levitte <richard@levitte.org>
|
|
Date: Mon, 29 Jun 2020 11:56:00 -0400
|
|
Subject: [PATCH] Fix incorrect handling of leftovers with poptStuffArgs
|
|
|
|
If poptStuffArgs() is used twice with the same context, it will invariably
|
|
cause memory corruption and possibly memory leaks or a crash.
|
|
|
|
Change the allocation of leftOvers so it adapts to the input on the fly
|
|
instead of trying to pre-allocate it in one go.
|
|
---
|
|
src/popt.c | 24 ++++++++++++++++++++++--
|
|
src/poptint.h | 1 +
|
|
2 files changed, 23 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/src/popt.c b/src/popt.c
|
|
index b7d9478..ab7b54f 100644
|
|
--- a/src/popt.c
|
|
+++ b/src/popt.c
|
|
@@ -168,6 +168,7 @@ poptContext poptGetContext(const char * name, int argc, const char ** argv,
|
|
con->os->next = 1; /* skip argv[0] */
|
|
|
|
con->leftovers = calloc( (size_t)(argc + 1), sizeof(*con->leftovers) );
|
|
+ con->allocLeftovers = argc + 1;
|
|
con->options = options;
|
|
con->aliases = NULL;
|
|
con->numAliases = 0;
|
|
@@ -1272,8 +1273,21 @@ int poptGetNextOpt(poptContext con)
|
|
con->os->nextArg = xstrdup(origOptString);
|
|
return 0;
|
|
}
|
|
- if (con->leftovers != NULL) /* XXX can't happen */
|
|
- con->leftovers[con->numLeftovers++] = origOptString;
|
|
+ if (con->leftovers != NULL) { /* XXX can't happen */
|
|
+ /* One might think we can never overflow the leftovers
|
|
+ array. Actually, that's true, as long as you don't
|
|
+ use poptStuffArgs()... */
|
|
+ if ((con->numLeftovers + 1) >= (con->allocLeftovers)) {
|
|
+ con->allocLeftovers += 10;
|
|
+ con->leftovers =
|
|
+ realloc(con->leftovers,
|
|
+ sizeof(*con->leftovers) * con->allocLeftovers);
|
|
+ }
|
|
+ con->leftovers[con->numLeftovers++]
|
|
+ = xstrdup(origOptString); /* so a free of a stuffed
|
|
+ argv doesn't give us a
|
|
+ dangling pointer */
|
|
+ }
|
|
continue;
|
|
}
|
|
|
|
@@ -1521,6 +1535,8 @@ poptItem poptFreeItems(poptItem items, int nitems)
|
|
|
|
poptContext poptFreeContext(poptContext con)
|
|
{
|
|
+ int i;
|
|
+
|
|
if (con == NULL) return con;
|
|
poptResetContext(con);
|
|
|
|
@@ -1530,7 +1546,11 @@ poptContext poptFreeContext(poptContext con)
|
|
con->execs = poptFreeItems(con->execs, con->numExecs);
|
|
con->numExecs = 0;
|
|
|
|
+ for (i = 0; i < con->numLeftovers; i++) {
|
|
+ con->leftovers[i] = _free(&con->leftovers[i]);
|
|
+ }
|
|
con->leftovers = _free(con->leftovers);
|
|
+
|
|
con->finalArgv = _free(con->finalArgv);
|
|
con->appName = _free(con->appName);
|
|
con->otherHelp = _free(con->otherHelp);
|
|
diff --git a/src/poptint.h b/src/poptint.h
|
|
index b64e123..d4d6e90 100644
|
|
--- a/src/poptint.h
|
|
+++ b/src/poptint.h
|
|
@@ -94,6 +94,7 @@ struct poptContext_s {
|
|
struct optionStackEntry * os;
|
|
poptArgv leftovers;
|
|
int numLeftovers;
|
|
+ int allocLeftovers;
|
|
int nextLeftover;
|
|
const struct poptOption * options;
|
|
int restLeftover;
|
|
--
|
|
2.27.0
|
|
|