diff --git a/test/syscalls/linux/BUILD b/test/syscalls/linux/BUILD index c4dae36ff..5f87dc420 100644 --- a/test/syscalls/linux/BUILD +++ b/test/syscalls/linux/BUILD @@ -1820,6 +1820,7 @@ cc_binary( "//test/util:file_descriptor", "//test/util:fs_util", "//test/util:mount_util", + "@com_google_absl//absl/algorithm:container", "@com_google_absl//absl/container:node_hash_set", "@com_google_absl//absl/strings", "@com_google_absl//absl/strings:str_format", diff --git a/test/syscalls/linux/proc.cc b/test/syscalls/linux/proc.cc index af417a919..1fde07a45 100644 --- a/test/syscalls/linux/proc.cc +++ b/test/syscalls/linux/proc.cc @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include @@ -48,6 +49,7 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +#include "absl/algorithm/container.h" #include "absl/container/node_hash_set.h" #include "absl/strings/ascii.h" #include "absl/strings/match.h" @@ -1483,12 +1485,32 @@ TEST(ProcLoadavg, Fields) { class ProcPidStatTest : public ::testing::TestWithParam {}; +// Parses /proc//stat output to a vector of string. We need a more +// complicated approach than absl::StrSplit because COMM can contain spaces. +PosixErrorOr> ParseProcPidStat( + absl::string_view proc_pid_stat) { + auto comm_start = proc_pid_stat.find('('); + auto comm_end = proc_pid_stat.rfind(')'); + if (comm_start == proc_pid_stat.npos || comm_end == proc_pid_stat.npos) { + return PosixError(EINVAL, absl::StrCat("Invalid /proc//stat")); + } + std::vector fields = + absl::StrSplit(proc_pid_stat.substr(0, comm_start - 1), ' '); + fields.push_back(std::string{proc_pid_stat.substr(comm_start, comm_end + 1)}); + absl::c_transform(absl::StrSplit(proc_pid_stat.substr(comm_end + 2), ' '), + std::back_inserter(fields), + [](auto sv) { return std::string{sv}; }); + return fields; +} + TEST_P(ProcPidStatTest, HasBasicFields) { std::string proc_pid_stat = ASSERT_NO_ERRNO_AND_VALUE( GetContents(absl::StrCat("/proc/", GetParam(), "/stat"))); ASSERT_FALSE(proc_pid_stat.empty()); - std::vector fields = absl::StrSplit(proc_pid_stat, ' '); + std::vector fields = + ASSERT_NO_ERRNO_AND_VALUE(ParseProcPidStat(proc_pid_stat)); + ASSERT_GE(fields.size(), 24); EXPECT_EQ(absl::StrCat(getpid()), fields[0]); // fields[1] is the thread name. @@ -1546,7 +1568,8 @@ PosixErrorOr CurrentRSS() { return PosixError(EINVAL, "empty /proc/self/stat"); } - std::vector fields = absl::StrSplit(proc_self_stat, ' '); + ASSIGN_OR_RETURN_ERRNO(std::vector fields, + ParseProcPidStat(proc_self_stat)); if (fields.size() < 24) { return PosixError( EINVAL,