Don't leak when expanding response files.

Before this patch we would strdup each argument. If one was a response file,
we would replace it with the response file contents, leaking the original
strdup result.

We now don't strdup the originals and let StringSaver free any memory it
allocated. This also saves a bit of malloc traffic when response files are
not used.

Leak found by the valgrind build bot.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@187042 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Rafael Espindola
2013-07-24 14:32:01 +00:00
parent 7976842791
commit 1e3c0a4c77

View File

@@ -563,8 +563,19 @@ bool cl::ExpandResponseFiles(StringSaver &Saver, TokenizerCallback Tokenizer,
namespace { namespace {
class StrDupSaver : public StringSaver { class StrDupSaver : public StringSaver {
std::vector<char*> Dups;
public:
~StrDupSaver() {
for (std::vector<char *>::iterator I = Dups.begin(), E = Dups.end();
I != E; ++I) {
char *Dup = *I;
free(Dup);
}
}
const char *SaveString(const char *Str) LLVM_OVERRIDE { const char *SaveString(const char *Str) LLVM_OVERRIDE {
return strdup(Str); char *Dup = strdup(Str);
Dups.push_back(Dup);
return Dup;
} }
}; };
} }
@@ -588,20 +599,14 @@ void cl::ParseEnvironmentOptions(const char *progName, const char *envVar,
// Get program's "name", which we wouldn't know without the caller // Get program's "name", which we wouldn't know without the caller
// telling us. // telling us.
SmallVector<const char *, 20> newArgv; SmallVector<const char *, 20> newArgv;
newArgv.push_back(strdup(progName)); StrDupSaver Saver;
newArgv.push_back(Saver.SaveString(progName));
// Parse the value of the environment variable into a "command line" // Parse the value of the environment variable into a "command line"
// and hand it off to ParseCommandLineOptions(). // and hand it off to ParseCommandLineOptions().
StrDupSaver Saver;
TokenizeGNUCommandLine(envValue, Saver, newArgv); TokenizeGNUCommandLine(envValue, Saver, newArgv);
int newArgc = static_cast<int>(newArgv.size()); int newArgc = static_cast<int>(newArgv.size());
ParseCommandLineOptions(newArgc, &newArgv[0], Overview); ParseCommandLineOptions(newArgc, &newArgv[0], Overview);
// Free all the strdup()ed strings.
for (SmallVectorImpl<const char *>::iterator i = newArgv.begin(),
e = newArgv.end();
i != e; ++i)
free(const_cast<char *>(*i));
} }
void cl::ParseCommandLineOptions(int argc, const char * const *argv, void cl::ParseCommandLineOptions(int argc, const char * const *argv,
@@ -618,7 +623,7 @@ void cl::ParseCommandLineOptions(int argc, const char * const *argv,
// Expand response files. // Expand response files.
SmallVector<const char *, 20> newArgv; SmallVector<const char *, 20> newArgv;
for (int i = 0; i != argc; ++i) for (int i = 0; i != argc; ++i)
newArgv.push_back(strdup(argv[i])); newArgv.push_back(argv[i]);
StrDupSaver Saver; StrDupSaver Saver;
ExpandResponseFiles(Saver, TokenizeGNUCommandLine, newArgv); ExpandResponseFiles(Saver, TokenizeGNUCommandLine, newArgv);
argv = &newArgv[0]; argv = &newArgv[0];
@@ -914,13 +919,6 @@ void cl::ParseCommandLineOptions(int argc, const char * const *argv,
PositionalOpts.clear(); PositionalOpts.clear();
MoreHelp->clear(); MoreHelp->clear();
// Free the memory allocated by ExpandResponseFiles.
// Free all the strdup()ed strings.
for (SmallVectorImpl<const char *>::iterator i = newArgv.begin(),
e = newArgv.end();
i != e; ++i)
free(const_cast<char *>(*i));
// If we had an error processing our arguments, don't let the program execute // If we had an error processing our arguments, don't let the program execute
if (ErrorParsing) exit(1); if (ErrorParsing) exit(1);
} }