pwd/grp: fix pwd _r reentrancy, new tests, clean up
getpwnam_r() and getpwuid_r() clobber the storage used by getpwnam()
and getpwuid(). This isn't likely to be a big issue, but since we do
this right for the group functions, fix this as well as add a test.
Both use more space in buf than is actually required, but well below
their sysconf() suggested values, so we accept that to keep the code
concise.
Add tests for dealing with unaligned input buffers, particularly for
getgrnam_r() and getgrgid_r(), as they require alignment but this
wasn't being tested.
Refactor common initialization code for both passwd and group state
structs.
Remove extraneous null pointer checks; the values they were testing
were offsets of a previous pointer, so guaranteed to never actually be
null. If the underlying pointer is actually null, we're beyond repair
anyway, so accept that we'll crash.
Test: pwd/grp unit tests
Change-Id: I60c4d00e9ab3cf55daf8314c5029fd914025b696
diff --git a/tests/grp_pwd_test.cpp b/tests/grp_pwd_test.cpp
index b46839b..ebc357c 100644
--- a/tests/grp_pwd_test.cpp
+++ b/tests/grp_pwd_test.cpp
@@ -217,6 +217,89 @@
TEST(pwd, getpwnam_app_id_u1_i0) {
check_get_passwd("u1_i0", 190000, TYPE_APP);
}
+
+TEST(pwd, getpwnam_r_alignment) {
+#if defined(__BIONIC__)
+ passwd pwd_storage;
+ alignas(16) char buf[512];
+ passwd* pwd;
+ int result = getpwnam_r("root", &pwd_storage, buf + 1, sizeof(buf) - 1, &pwd);
+ ASSERT_EQ(0, result);
+ check_passwd(pwd, "root", 0, TYPE_SYSTEM, true);
+#else
+ GTEST_SKIP() << "bionic-only test";
+#endif
+}
+
+TEST(pwd, getpwuid_r_alignment) {
+#if defined(__BIONIC__)
+ passwd pwd_storage;
+ alignas(16) char buf[512];
+ passwd* pwd;
+ int result = getpwuid_r(0, &pwd_storage, buf + 1, sizeof(buf) - 1, &pwd);
+ ASSERT_EQ(0, result);
+ check_passwd(pwd, "root", 0, TYPE_SYSTEM, true);
+#else
+ GTEST_SKIP() << "bionic-only test";
+#endif
+}
+
+TEST(pwd, getpwnam_r_reentrancy) {
+#if defined(__BIONIC__)
+ passwd pwd_storage[2];
+ char buf[2][512];
+ passwd* pwd[3];
+ int result = getpwnam_r("root", &pwd_storage[0], buf[0], sizeof(buf[0]), &pwd[0]);
+ ASSERT_EQ(0, result);
+ check_passwd(pwd[0], "root", 0, TYPE_SYSTEM, true);
+ pwd[1] = getpwnam("system");
+ ASSERT_NE(nullptr, pwd[1]);
+ check_passwd(pwd[1], "system", 1000, TYPE_SYSTEM, true);
+ result = getpwnam_r("radio", &pwd_storage[1], buf[1], sizeof(buf[1]), &pwd[2]);
+ ASSERT_EQ(0, result);
+ check_passwd(pwd[2], "radio", 1001, TYPE_SYSTEM, true);
+ check_passwd(pwd[0], "root", 0, TYPE_SYSTEM, true);
+ check_passwd(pwd[1], "system", 1000, TYPE_SYSTEM, true);
+#else
+ GTEST_SKIP() << "bionic-only test";
+#endif
+}
+
+TEST(pwd, getpwuid_r_reentrancy) {
+#if defined(__BIONIC__)
+ passwd pwd_storage[2];
+ char buf[2][512];
+ passwd* pwd[3];
+ int result = getpwuid_r(0, &pwd_storage[0], buf[0], sizeof(buf[0]), &pwd[0]);
+ ASSERT_EQ(0, result);
+ check_passwd(pwd[0], "root", 0, TYPE_SYSTEM, true);
+ pwd[1] = getpwuid(1000);
+ ASSERT_NE(nullptr, pwd[1]);
+ check_passwd(pwd[1], "system", 1000, TYPE_SYSTEM, true);
+ result = getpwuid_r(1001, &pwd_storage[1], buf[1], sizeof(buf[1]), &pwd[2]);
+ ASSERT_EQ(0, result);
+ check_passwd(pwd[2], "radio", 1001, TYPE_SYSTEM, true);
+ check_passwd(pwd[0], "root", 0, TYPE_SYSTEM, true);
+ check_passwd(pwd[1], "system", 1000, TYPE_SYSTEM, true);
+#else
+ GTEST_SKIP() << "bionic-only test";
+#endif
+}
+
+TEST(pwd, getpwnam_r_large_enough_suggested_buffer_size) {
+#if defined(__BIONIC__)
+ long size = sysconf(_SC_GETPW_R_SIZE_MAX);
+ ASSERT_GT(size, 0);
+ char buf[size];
+ passwd pwd_storage;
+ passwd* pwd;
+ ASSERT_EQ(0, getpwnam_r("root", &pwd_storage, buf, size, &pwd));
+ check_passwd(pwd, "root", 0, TYPE_SYSTEM, true);
+#else
+ GTEST_SKIP() << "bionic-only test";
+#endif
+}
+
#if defined(__BIONIC__)
template <typename T>
static void expect_ids(const T& ids) {
@@ -477,6 +560,32 @@
check_get_group("u1_i0", 190000);
}
+TEST(grp, getgrnam_r_alignment) {
+#if defined(__BIONIC__)
+ group grp_storage;
+ alignas(16) char buf[512];
+ group* grp;
+ int result = getgrnam_r("root", &grp_storage, buf + 1, sizeof(buf) - 1, &grp);
+ ASSERT_EQ(0, result);
+ check_group(grp, "root", 0);
+#else
+ GTEST_SKIP() << "bionic-only test";
+#endif
+}
+
+TEST(grp, getgrgid_r_alignment) {
+#if defined(__BIONIC__)
+ group grp_storage;
+ alignas(16) char buf[512];
+ group* grp;
+ int result = getgrgid_r(0, &grp_storage, buf + 1, sizeof(buf) - 1, &grp);
+ ASSERT_EQ(0, result);
+ check_group(grp, "root", 0);
+#else
+ GTEST_SKIP() << "bionic-only test";
+#endif
+}
+
TEST(grp, getgrnam_r_reentrancy) {
#if defined(__BIONIC__)
group grp_storage[2];