From 3048e4b9f5b5dbcc0dfb82399fef7cab2a7abbf0 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Thu, 25 Jul 2019 15:21:50 +0200 Subject: [PATCH] LibC: Make sure we always return the intended errno from execvpe(). --- Libraries/LibC/unistd.cpp | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/Libraries/LibC/unistd.cpp b/Libraries/LibC/unistd.cpp index bac122e660..b912544efd 100644 --- a/Libraries/LibC/unistd.cpp +++ b/Libraries/LibC/unistd.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -53,28 +54,28 @@ int execve(const char* filename, char* const argv[], char* const envp[]) int execvpe(const char* filename, char* const argv[], char* const envp[]) { - // NOTE: We scope everything here to make sure that setting errno on exit is sticky. - { - int rc = execve(filename, argv, envp); + ScopedValueRollback errno_rollback(errno); + int rc = execve(filename, argv, envp); + if (rc < 0 && errno != ENOENT) { + errno_rollback.set_override_rollback_value(errno); + dbg() << "execvpe() failed on first with" << strerror(errno); + return rc; + } + String path = getenv("PATH"); + if (path.is_empty()) + path = "/bin:/usr/bin"; + auto parts = path.split(':'); + for (auto& part : parts) { + auto candidate = String::format("%s/%s", part.characters(), filename); + int rc = execve(candidate.characters(), argv, envp); if (rc < 0 && errno != ENOENT) { - dbg() << "execvpe() failed on first with" << strerror(errno); + errno_rollback.set_override_rollback_value(errno); + dbg() << "execvpe() failed on attempt (" << candidate << ") with " << strerror(errno); return rc; } - String path = getenv("PATH"); - if (path.is_empty()) - path = "/bin:/usr/bin"; - auto parts = path.split(':'); - for (auto& part : parts) { - auto candidate = String::format("%s/%s", part.characters(), filename); - int rc = execve(candidate.characters(), argv, envp); - if (rc < 0 && errno != ENOENT) { - dbg() << "execvpe() failed on attempt (" << candidate << ") with " << strerror(errno); - return rc; - } - } - dbg() << "execvpe() leaving :("; } - errno = ENOENT; + errno_rollback.set_override_rollback_value(ENOENT); + dbg() << "execvpe() leaving :("; return -1; }