Mercurial > hg > Members > tobaru > cbc > CbC_llvm
diff lib/Support/Unix/Program.inc @ 121:803732b1fca8
LLVM 5.0
author | kono |
---|---|
date | Fri, 27 Oct 2017 17:07:41 +0900 |
parents | 7d135dc70f03 |
children |
line wrap: on
line diff
--- a/lib/Support/Unix/Program.inc Fri Nov 25 19:14:25 2016 +0900 +++ b/lib/Support/Unix/Program.inc Fri Oct 27 17:07:41 2017 +0900 @@ -40,9 +40,6 @@ #include <unistd.h> #endif #ifdef HAVE_POSIX_SPAWN -#ifdef __sun__ -#define _RESTRICT_KYWD -#endif #include <spawn.h> #if defined(__APPLE__) @@ -96,7 +93,7 @@ return errc::no_such_file_or_directory; } -static bool RedirectIO(const StringRef *Path, int FD, std::string* ErrMsg) { +static bool RedirectIO(Optional<StringRef> Path, int FD, std::string* ErrMsg) { if (!Path) // Noop return false; std::string File; @@ -147,8 +144,7 @@ static void TimeOutHandler(int Sig) { } -static void SetMemoryLimits (unsigned size) -{ +static void SetMemoryLimits(unsigned size) { #if HAVE_SYS_RESOURCE_H && HAVE_GETRLIMIT && HAVE_SETRLIMIT struct rlimit r; __typeof__ (r.rlim_cur) limit = (__typeof__ (r.rlim_cur)) (size) * 1048576; @@ -163,24 +159,14 @@ r.rlim_cur = limit; setrlimit (RLIMIT_RSS, &r); #endif -#ifdef RLIMIT_AS // e.g. NetBSD doesn't have it. - // Don't set virtual memory limit if built with any Sanitizer. They need 80Tb - // of virtual memory for shadow memory mapping. -#if !LLVM_MEMORY_SANITIZER_BUILD && !LLVM_ADDRESS_SANITIZER_BUILD - // Virtual memory. - getrlimit (RLIMIT_AS, &r); - r.rlim_cur = limit; - setrlimit (RLIMIT_AS, &r); -#endif -#endif #endif } } -static bool Execute(ProcessInfo &PI, StringRef Program, const char **args, - const char **envp, const StringRef **redirects, - unsigned memoryLimit, std::string *ErrMsg) { +static bool Execute(ProcessInfo &PI, StringRef Program, const char **Args, + const char **Envp, ArrayRef<Optional<StringRef>> Redirects, + unsigned MemoryLimit, std::string *ErrMsg) { if (!llvm::sys::fs::exists(Program)) { if (ErrMsg) *ErrMsg = std::string("Executable \"") + Program.str() + @@ -191,7 +177,7 @@ // If this OS has posix_spawn and there is no memory limit being implied, use // posix_spawn. It is more efficient than fork/exec. #ifdef HAVE_POSIX_SPAWN - if (memoryLimit == 0) { + if (MemoryLimit == 0) { posix_spawn_file_actions_t FileActionsStore; posix_spawn_file_actions_t *FileActions = nullptr; @@ -200,11 +186,12 @@ // so we copy any StringRefs into this variable. std::string RedirectsStorage[3]; - if (redirects) { + if (!Redirects.empty()) { + assert(Redirects.size() == 3); std::string *RedirectsStr[3] = {nullptr, nullptr, nullptr}; for (int I = 0; I < 3; ++I) { - if (redirects[I]) { - RedirectsStorage[I] = *redirects[I]; + if (Redirects[I]) { + RedirectsStorage[I] = *Redirects[I]; RedirectsStr[I] = &RedirectsStorage[I]; } } @@ -216,8 +203,7 @@ if (RedirectIO_PS(RedirectsStr[0], 0, ErrMsg, FileActions) || RedirectIO_PS(RedirectsStr[1], 1, ErrMsg, FileActions)) return false; - if (redirects[1] == nullptr || redirects[2] == nullptr || - *redirects[1] != *redirects[2]) { + if (!Redirects[1] || !Redirects[2] || *Redirects[1] != *Redirects[2]) { // Just redirect stderr if (RedirectIO_PS(RedirectsStr[2], 2, ErrMsg, FileActions)) return false; @@ -229,20 +215,20 @@ } } - if (!envp) + if (!Envp) #if !USE_NSGETENVIRON - envp = const_cast<const char **>(environ); + Envp = const_cast<const char **>(environ); #else // environ is missing in dylibs. - envp = const_cast<const char **>(*_NSGetEnviron()); + Envp = const_cast<const char **>(*_NSGetEnviron()); #endif // Explicitly initialized to prevent what appears to be a valgrind false // positive. pid_t PID = 0; int Err = posix_spawn(&PID, Program.str().c_str(), FileActions, - /*attrp*/nullptr, const_cast<char **>(args), - const_cast<char **>(envp)); + /*attrp*/nullptr, const_cast<char **>(Args), + const_cast<char **>(Envp)); if (FileActions) posix_spawn_file_actions_destroy(FileActions); @@ -267,13 +253,12 @@ // Child process: Execute the program. case 0: { // Redirect file descriptors... - if (redirects) { + if (!Redirects.empty()) { // Redirect stdin - if (RedirectIO(redirects[0], 0, ErrMsg)) { return false; } + if (RedirectIO(Redirects[0], 0, ErrMsg)) { return false; } // Redirect stdout - if (RedirectIO(redirects[1], 1, ErrMsg)) { return false; } - if (redirects[1] && redirects[2] && - *(redirects[1]) == *(redirects[2])) { + if (RedirectIO(Redirects[1], 1, ErrMsg)) { return false; } + if (Redirects[1] && Redirects[2] && *Redirects[1] == *Redirects[2]) { // If stdout and stderr should go to the same place, redirect stderr // to the FD already open for stdout. if (-1 == dup2(1,2)) { @@ -282,24 +267,24 @@ } } else { // Just redirect stderr - if (RedirectIO(redirects[2], 2, ErrMsg)) { return false; } + if (RedirectIO(Redirects[2], 2, ErrMsg)) { return false; } } } // Set memory limits - if (memoryLimit!=0) { - SetMemoryLimits(memoryLimit); + if (MemoryLimit!=0) { + SetMemoryLimits(MemoryLimit); } // Execute! std::string PathStr = Program; - if (envp != nullptr) + if (Envp != nullptr) execve(PathStr.c_str(), - const_cast<char **>(args), - const_cast<char **>(envp)); + const_cast<char **>(Args), + const_cast<char **>(Envp)); else execv(PathStr.c_str(), - const_cast<char **>(args)); + const_cast<char **>(Args)); // If the execve() failed, we should exit. Follow Unix protocol and // return 127 if the executable was not found, and 126 otherwise. // Use _exit rather than exit so that atexit functions and static @@ -446,7 +431,8 @@ return EC; } -bool llvm::sys::commandLineFitsWithinSystemLimits(StringRef Program, ArrayRef<const char*> Args) { +bool llvm::sys::commandLineFitsWithinSystemLimits(StringRef Program, + ArrayRef<const char *> Args) { static long ArgMax = sysconf(_SC_ARG_MAX); // System says no practical limit. @@ -457,13 +443,23 @@ long HalfArgMax = ArgMax / 2; size_t ArgLength = Program.size() + 1; - for (ArrayRef<const char*>::iterator I = Args.begin(), E = Args.end(); - I != E; ++I) { - ArgLength += strlen(*I) + 1; + for (const char* Arg : Args) { + size_t length = strlen(Arg); + + // Ensure that we do not exceed the MAX_ARG_STRLEN constant on Linux, which + // does not have a constant unlike what the man pages would have you + // believe. Since this limit is pretty high, perform the check + // unconditionally rather than trying to be aggressive and limiting it to + // Linux only. + if (length >= (32 * 4096)) + return false; + + ArgLength += length + 1; if (ArgLength > size_t(HalfArgMax)) { return false; } } + return true; } }