summaryrefslogtreecommitdiff
path: root/rts/RtsFlags.c
diff options
context:
space:
mode:
authorSimon Marlow <marlowsd@gmail.com>2011-12-14 10:42:47 +0000
committerSimon Marlow <marlowsd@gmail.com>2011-12-14 10:49:43 +0000
commitdff852b1b65d07a4a400d3f20c854172c8fcecaf (patch)
tree528e05df92d9e51dea1255056bc5c8992b0bac06 /rts/RtsFlags.c
parentac051fc05f6aab261d56d22261f4cb9c2cb1f474 (diff)
downloadhaskell-dff852b1b65d07a4a400d3f20c854172c8fcecaf.tar.gz
Fix a memory allocation bug (rts_argv wasn't big enough)
Diffstat (limited to 'rts/RtsFlags.c')
-rw-r--r--rts/RtsFlags.c27
1 files changed, 22 insertions, 5 deletions
diff --git a/rts/RtsFlags.c b/rts/RtsFlags.c
index 2685d2e945..421e81ef07 100644
--- a/rts/RtsFlags.c
+++ b/rts/RtsFlags.c
@@ -41,6 +41,7 @@ char **full_prog_argv = NULL;
char *prog_name = NULL; /* 'basename' of prog_argv[0] */
int rts_argc = 0; /* ditto */
char **rts_argv = NULL;
+int rts_argv_size = 0;
#if defined(mingw32_HOST_OS)
// On Windows, we want to use GetCommandLineW rather than argc/argv,
// but we need to mutate the command line arguments for withProgName and
@@ -409,6 +410,19 @@ strequal(const char *a, const char * b)
return(strcmp(a, b) == 0);
}
+// We can't predict up front how much space we'll need for rts_argv,
+// because it involves parsing ghc_rts_opts and GHCRTS, so we
+// expand it on demand.
+static void appendRtsArg (char *arg)
+{
+ if (rts_argc == rts_argv_size) {
+ rts_argv_size *= 2;
+ rts_argv = stgReallocBytes(rts_argv, rts_argv_size * sizeof (char *),
+ "RtsFlags.c:appendRtsArg");
+ }
+ rts_argv[rts_argc++] = arg;
+}
+
static void splitRtsFlags(const char *s)
{
const char *c1, *c2;
@@ -425,7 +439,7 @@ static void splitRtsFlags(const char *s)
t = stgMallocBytes(c2-c1+1, "RtsFlags.c:splitRtsFlags()");
strncpy(t, c1, c2-c1);
t[c2-c1] = '\0';
- rts_argv[rts_argc++] = t;
+ appendRtsArg(t);
c1 = c2;
} while (*c1 != '\0');
@@ -463,11 +477,12 @@ void setupRtsFlags (int *argc, char *argv[],
*argc = 1;
rts_argc = 0;
- rts_argv = stgCallocBytes(total_arg + 1, sizeof (char *), "setupRtsFlags");
+ rts_argv_size = total_arg + 1;
+ rts_argv = stgMallocBytes(rts_argv_size * sizeof (char *), "setupRtsFlags");
rts_argc0 = rts_argc;
- // process arguments from the ghc_rts_opts global variable first.
+ // process arguments from the -with-rtsopts compile-time flag first
// (arguments from the GHCRTS environment variable and the command
// line override these).
{
@@ -517,7 +532,7 @@ void setupRtsFlags (int *argc, char *argv[],
mode = PGM;
}
else if (mode == RTS) {
- rts_argv[rts_argc++] = copyArg(argv[arg]);
+ appendRtsArg(copyArg(argv[arg]));
}
else {
argv[(*argc)++] = argv[arg];
@@ -528,10 +543,11 @@ void setupRtsFlags (int *argc, char *argv[],
argv[(*argc)++] = argv[arg];
}
argv[*argc] = (char *) 0;
- rts_argv[rts_argc] = (char *) 0;
procRtsOpts(rts_argc0, rtsOptsEnabled);
+ appendRtsArg((char *)0);
+
normaliseRtsOpts();
setProgArgv(*argc, argv);
@@ -1798,6 +1814,7 @@ freeRtsArgv(void)
freeArgv(rts_argc,rts_argv);
rts_argc = 0;
rts_argv = NULL;
+ rts_argv_size = 0;
}
/* ----------------------------------------------------------------------------