[libc-commits] [libc] [libc] Add getpwent_r entrypoint (PR #226966)

Jeff Bailey via libc-commits libc-commits at lists.llvm.org
Mon Sep 28 04:44:58 PDT 2026


https://github.com/kaladron created https://github.com/llvm/llvm-project/pull/226966

Add the reentrant password database iteration entrypoint getpwent_r.

getpwent_r reads the next password database record from the stream into the caller-supplied struct passwd and buffer, returning 0 on success, ENOENT at end-of-file, or an error number (such as ERANGE) on failure. When a record exceeds the caller buffer size, FlatFileDatabase::getnext rewinds the stream to the beginning of that record so that a subsequent retry with a larger buffer reads the same entry.

* Add getpwent_r entrypoint and pwd::read_next fixed-buffer overload
* Rewind stream on ERANGE in FlatFileDatabase::getnext(EntryType *, span<char>)
* Define getpwent_r in include/pwd.yaml and Linux entrypoints.txt
* Add unit tests for getpwent_r

Assisted-by: Automated tooling, human reviewed.

>From ca5fddc744a6f6eb50f2d027403968b6345b9179 Mon Sep 17 00:00:00 2001
From: Jeff Bailey <jbailey at raspberryginger.com>
Date: Tue, 22 Sep 2026 20:40:10 +0100
Subject: [PATCH] [libc] Add getpwent_r entrypoint

Add the reentrant password database iteration entrypoint getpwent_r.

getpwent_r reads the next password database record from the stream into
the caller-supplied struct passwd and buffer, returning 0 on success,
ENOENT at end-of-file, or an error number (such as ERANGE) on failure.
When a record exceeds the caller buffer size, FlatFileDatabase::getnext
rewinds the stream to the beginning of that record so that a subsequent
retry with a larger buffer reads the same entry.

* Add getpwent_r entrypoint and pwd::read_next fixed-buffer overload
* Rewind stream on ERANGE in FlatFileDatabase::getnext(EntryType *, span<char>)
* Define getpwent_r in include/pwd.yaml and Linux entrypoints.txt
* Add unit tests for getpwent_r

Assisted-by: Automated tooling, human reviewed.
---
 libc/config/linux/aarch64/entrypoints.txt |   1 +
 libc/config/linux/arm/entrypoints.txt     |   1 +
 libc/config/linux/i386/entrypoints.txt    |   1 +
 libc/config/linux/riscv/entrypoints.txt   |   1 +
 libc/config/linux/x86_64/entrypoints.txt  |   1 +
 libc/include/pwd.yaml                     |  10 ++
 libc/src/__support/pwd/flat_file_db.h     |  16 +-
 libc/src/pwd/CMakeLists.txt               |  17 ++
 libc/src/pwd/getpwent_r.cpp               |  46 ++++++
 libc/src/pwd/getpwent_r.h                 |  28 ++++
 libc/src/pwd/pwd_utils.cpp                |   4 +
 libc/src/pwd/pwd_utils.h                  |   4 +
 libc/test/src/pwd/CMakeLists.txt          |  26 +++
 libc/test/src/pwd/getpwent_r_test.cpp     | 188 ++++++++++++++++++++++
 14 files changed, 341 insertions(+), 3 deletions(-)
 create mode 100644 libc/src/pwd/getpwent_r.cpp
 create mode 100644 libc/src/pwd/getpwent_r.h
 create mode 100644 libc/test/src/pwd/getpwent_r_test.cpp

diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index 15a5367f5fc95..e2402b1264931 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -62,6 +62,7 @@ set(TARGET_LIBC_ENTRYPOINTS
     # pwd.h entrypoints
     libc.src.pwd.endpwent
     libc.src.pwd.getpwent
+    libc.src.pwd.getpwent_r
     libc.src.pwd.getpwnam
     libc.src.pwd.getpwnam_r
     libc.src.pwd.getpwuid
diff --git a/libc/config/linux/arm/entrypoints.txt b/libc/config/linux/arm/entrypoints.txt
index 1441146393c5f..f2a7f8e182658 100644
--- a/libc/config/linux/arm/entrypoints.txt
+++ b/libc/config/linux/arm/entrypoints.txt
@@ -45,6 +45,7 @@ set(TARGET_LIBC_ENTRYPOINTS
     # pwd.h entrypoints
     libc.src.pwd.endpwent
     libc.src.pwd.getpwent
+    libc.src.pwd.getpwent_r
     libc.src.pwd.getpwnam
     libc.src.pwd.getpwnam_r
     libc.src.pwd.getpwuid
diff --git a/libc/config/linux/i386/entrypoints.txt b/libc/config/linux/i386/entrypoints.txt
index b58956c166686..3ee6e68b466e8 100644
--- a/libc/config/linux/i386/entrypoints.txt
+++ b/libc/config/linux/i386/entrypoints.txt
@@ -14,6 +14,7 @@ set(TARGET_LIBC_ENTRYPOINTS
   # pwd.h entrypoints
   libc.src.pwd.endpwent
   libc.src.pwd.getpwent
+  libc.src.pwd.getpwent_r
   libc.src.pwd.getpwnam
   libc.src.pwd.getpwnam_r
   libc.src.pwd.getpwuid
diff --git a/libc/config/linux/riscv/entrypoints.txt b/libc/config/linux/riscv/entrypoints.txt
index 8f4dded27de68..b90ab97416a41 100644
--- a/libc/config/linux/riscv/entrypoints.txt
+++ b/libc/config/linux/riscv/entrypoints.txt
@@ -81,6 +81,7 @@ set(TARGET_LIBC_ENTRYPOINTS
     # pwd.h entrypoints
     libc.src.pwd.endpwent
     libc.src.pwd.getpwent
+    libc.src.pwd.getpwent_r
     libc.src.pwd.getpwnam
     libc.src.pwd.getpwnam_r
     libc.src.pwd.getpwuid
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 8ca73cc82cc2d..211476af8f712 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -81,6 +81,7 @@ set(TARGET_LIBC_ENTRYPOINTS
     # pwd.h entrypoints
     libc.src.pwd.endpwent
     libc.src.pwd.getpwent
+    libc.src.pwd.getpwent_r
     libc.src.pwd.getpwnam
     libc.src.pwd.getpwnam_r
     libc.src.pwd.getpwuid
diff --git a/libc/include/pwd.yaml b/libc/include/pwd.yaml
index 9301307d22d3a..f91fec9f33263 100644
--- a/libc/include/pwd.yaml
+++ b/libc/include/pwd.yaml
@@ -1,6 +1,7 @@
 header: pwd.h
 standards:
   - posix
+  - gnu
 types:
   - type_name: struct_passwd
   - type_name: gid_t
@@ -14,6 +15,15 @@ functions:
       - posix
     return_type: struct passwd *
     arguments: []
+  - name: getpwent_r
+    standards:
+      - gnu
+    return_type: int
+    arguments:
+      - type: struct passwd *
+      - type: char *
+      - type: size_t
+      - type: struct passwd **
   - name: setpwent
     standards:
       - posix
diff --git a/libc/src/__support/pwd/flat_file_db.h b/libc/src/__support/pwd/flat_file_db.h
index 319197872cd3b..4c6f01a5225e5 100644
--- a/libc/src/__support/pwd/flat_file_db.h
+++ b/libc/src/__support/pwd/flat_file_db.h
@@ -216,10 +216,13 @@ template <typename EntryType> class FlatFileDatabase {
   // Reads and parses the next record from the database into a fixed buffer.
   // Returns true if an entry was read, false if EOF was reached, or an Error on
   // failure. Blank lines are skipped. A record that does not fit in the buffer
-  // is reported as ERANGE.
+  // is reported as ERANGE and leaves the stream positioned at the start of
+  // that record so the caller can retry with a larger buffer.
   LIBC_INLINE ErrorOr<bool> getnext(EntryType *entry, cpp::span<char> buffer) {
     if (!entry)
       return Error(EINVAL);
+    if (buffer.size() < 2)
+      return Error(ERANGE);
 
     if (!file) {
       auto res = setdb();
@@ -228,6 +231,7 @@ template <typename EntryType> class FlatFileDatabase {
     }
 
     while (true) {
+      auto pos_or = file->tell();
       auto result = read_line(file, buffer);
       if (!result.has_value())
         return Error(result.error());
@@ -240,16 +244,22 @@ template <typename EntryType> class FlatFileDatabase {
       if (res.bytes_read == 0)
         continue;
 
-      if (res.truncated)
+      if (res.truncated) {
+        if (pos_or.has_value())
+          file->seek(pos_or.value(), SEEK_SET);
         return Error(ERANGE);
+      }
 
       // Slicing at bytes_read + 1 includes the terminating null byte written
       // by read_line; the remainder of the buffer serves as scratch space.
       auto parse_res =
           parse_line<EntryType>(buffer.first(res.bytes_read + 1),
                                 buffer.subspan(res.bytes_read + 1), entry);
-      if (!parse_res.has_value())
+      if (!parse_res.has_value()) {
+        if (parse_res.error() == ERANGE && pos_or.has_value())
+          file->seek(pos_or.value(), SEEK_SET);
         return Error(parse_res.error());
+      }
       return true;
     }
   }
diff --git a/libc/src/pwd/CMakeLists.txt b/libc/src/pwd/CMakeLists.txt
index 9ab145a1e3592..0e9097ad33faa 100644
--- a/libc/src/pwd/CMakeLists.txt
+++ b/libc/src/pwd/CMakeLists.txt
@@ -16,6 +16,23 @@ add_entrypoint_object(
     .pwd_utils
 )
 
+add_entrypoint_object(
+  getpwent_r
+  SRCS
+    getpwent_r.cpp
+  HDRS
+    getpwent_r.h
+  DEPENDS
+    libc.hdr.errno_macros
+    libc.hdr.types.size_t
+    libc.hdr.types.struct_passwd
+    libc.src.__support.CPP.span
+    libc.src.__support.common
+    libc.src.__support.macros.config
+    libc.src.__support.macros.null_check
+    .pwd_utils
+)
+
 add_entrypoint_object(
   setpwent
   SRCS
diff --git a/libc/src/pwd/getpwent_r.cpp b/libc/src/pwd/getpwent_r.cpp
new file mode 100644
index 0000000000000..f60b5670943cd
--- /dev/null
+++ b/libc/src/pwd/getpwent_r.cpp
@@ -0,0 +1,46 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// Implementation of getpwent_r.
+///
+//===----------------------------------------------------------------------===//
+
+#include "src/pwd/getpwent_r.h"
+#include "hdr/errno_macros.h"
+#include "hdr/types/size_t.h"
+#include "hdr/types/struct_passwd.h"
+#include "src/__support/CPP/span.h"
+#include "src/__support/common.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/macros/null_check.h"
+#include "src/pwd/pwd_utils.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(int, getpwent_r,
+                   (struct passwd * pwbuf, char *buf, size_t buflen,
+                    struct passwd **pwbufp)) {
+  LIBC_CRASH_ON_NULLPTR(pwbuf);
+  LIBC_CRASH_ON_NULLPTR(buf);
+  LIBC_CRASH_ON_NULLPTR(pwbufp);
+
+  *pwbufp = nullptr;
+
+  const auto res = pwd::read_next(pwbuf, cpp::span<char>(buf, buflen));
+  if (!res.has_value())
+    return res.error();
+
+  if (!res.value())
+    return ENOENT;
+
+  *pwbufp = pwbuf;
+  return 0;
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/pwd/getpwent_r.h b/libc/src/pwd/getpwent_r.h
new file mode 100644
index 0000000000000..d3c191a84afb6
--- /dev/null
+++ b/libc/src/pwd/getpwent_r.h
@@ -0,0 +1,28 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// Internal header for getpwent_r.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_PWD_GETPWENT_R_H
+#define LLVM_LIBC_SRC_PWD_GETPWENT_R_H
+
+#include "hdr/types/size_t.h"
+#include "hdr/types/struct_passwd.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+int getpwent_r(struct passwd *pwbuf, char *buf, size_t buflen,
+               struct passwd **pwbufp);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_PWD_GETPWENT_R_H
diff --git a/libc/src/pwd/pwd_utils.cpp b/libc/src/pwd/pwd_utils.cpp
index 8d865c3a0fc45..56aa34fd4733c 100644
--- a/libc/src/pwd/pwd_utils.cpp
+++ b/libc/src/pwd/pwd_utils.cpp
@@ -88,6 +88,10 @@ ErrorOr<struct passwd *> read_next() {
   return &pwd_entry;
 }
 
+ErrorOr<bool> read_next(struct passwd *pwd, cpp::span<char> buffer) {
+  return db.getnext(pwd, buffer);
+}
+
 namespace {
 
 // The lookups are shared between the caller-supplied fixed buffer used by the
diff --git a/libc/src/pwd/pwd_utils.h b/libc/src/pwd/pwd_utils.h
index b3d16f49893b5..ee8af26946ef2 100644
--- a/libc/src/pwd/pwd_utils.h
+++ b/libc/src/pwd/pwd_utils.h
@@ -112,6 +112,10 @@ ErrorOr<void> close();
 // Reads the next entry from the password database.
 ErrorOr<struct passwd *> read_next();
 
+// Reads the next entry from the password database into a caller-supplied
+// buffer.
+ErrorOr<bool> read_next(struct passwd *pwd, cpp::span<char> buffer);
+
 // Searches for a password entry matching the given username using the
 // static process-global buffer.
 ErrorOr<struct passwd *> find_by_name(cpp::string_view name);
diff --git a/libc/test/src/pwd/CMakeLists.txt b/libc/test/src/pwd/CMakeLists.txt
index f60bf7016b1e5..11573806c602f 100644
--- a/libc/test/src/pwd/CMakeLists.txt
+++ b/libc/test/src/pwd/CMakeLists.txt
@@ -40,6 +40,32 @@ add_libc_test(
     libc.test.UnitTest.ErrnoCheckingTest
 )
 
+add_libc_test(
+  getpwent_r_test
+  SUITE
+    libc_pwd_unittests
+  HDRS
+    pwd_test_utils.h
+  SRCS
+    getpwent_r_test.cpp
+  DEPENDS
+    libc.hdr.errno_macros
+    libc.hdr.signal_macros
+    libc.hdr.types.gid_t
+    libc.hdr.types.size_t
+    libc.hdr.types.struct_passwd
+    libc.hdr.types.uid_t
+    libc.src.__support.File.file
+    libc.src.__support.File.platform_file
+    libc.src.pwd.endpwent
+    libc.src.pwd.getpwent_r
+    libc.src.pwd.pwd_utils
+    libc.src.pwd.setpwent
+    libc.src.stdio.remove
+    libc.src.string.string_utils
+    libc.test.UnitTest.ErrnoCheckingTest
+)
+
 add_libc_test(
   getpwnam_test
   SUITE
diff --git a/libc/test/src/pwd/getpwent_r_test.cpp b/libc/test/src/pwd/getpwent_r_test.cpp
new file mode 100644
index 0000000000000..bf9773cef5c88
--- /dev/null
+++ b/libc/test/src/pwd/getpwent_r_test.cpp
@@ -0,0 +1,188 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// Unit tests for getpwent_r.
+///
+//===----------------------------------------------------------------------===//
+
+#include "hdr/errno_macros.h"
+#include "hdr/signal_macros.h"
+#include "hdr/types/gid_t.h"
+#include "hdr/types/size_t.h"
+#include "hdr/types/struct_passwd.h"
+#include "hdr/types/uid_t.h"
+#include "pwd_test_utils.h"
+#include "src/pwd/endpwent.h"
+#include "src/pwd/getpwent_r.h"
+#include "src/pwd/pwd_utils.h"
+#include "src/pwd/setpwent.h"
+#include "test/UnitTest/Test.h"
+
+using LlvmLibcGetpwentRTest = LlvmLibcPwdTest;
+
+TEST_F(LlvmLibcGetpwentRTest, SuccessAndEofReturnsEnoent) {
+  const char *content = "root:x:0:0:root:/root:/bin/bash\n"
+                        "bin:x:1:1:bin:/bin:/sbin/nologin\n";
+  ScopedPasswdFile test_file(
+      libc_make_test_file_path("getpwent_r_success.test"), content);
+
+  struct passwd pwd;
+  char buffer[256];
+  struct passwd *result = nullptr;
+
+  ASSERT_EQ(LIBC_NAMESPACE::getpwent_r(&pwd, buffer, sizeof(buffer), &result),
+            0);
+  ASSERT_EQ(result, &pwd);
+  EXPECT_STREQ(pwd.pw_name, "root");
+  EXPECT_STREQ(pwd.pw_passwd, "x");
+  EXPECT_EQ(pwd.pw_uid, static_cast<uid_t>(0));
+  EXPECT_EQ(pwd.pw_gid, static_cast<gid_t>(0));
+  EXPECT_STREQ(pwd.pw_gecos, "root");
+  EXPECT_STREQ(pwd.pw_dir, "/root");
+  EXPECT_STREQ(pwd.pw_shell, "/bin/bash");
+
+  result = nullptr;
+  ASSERT_EQ(LIBC_NAMESPACE::getpwent_r(&pwd, buffer, sizeof(buffer), &result),
+            0);
+  ASSERT_EQ(result, &pwd);
+  EXPECT_STREQ(pwd.pw_name, "bin");
+  EXPECT_EQ(pwd.pw_uid, static_cast<uid_t>(1));
+
+  result = reinterpret_cast<struct passwd *>(0xdeadbeef);
+  ASSERT_EQ(LIBC_NAMESPACE::getpwent_r(&pwd, buffer, sizeof(buffer), &result),
+            ENOENT);
+  EXPECT_EQ(result, static_cast<struct passwd *>(nullptr));
+}
+
+TEST_F(LlvmLibcGetpwentRTest, SetpwentRewindsAndEndpwentReopens) {
+  const char *content = "root:x:0:0:root:/root:/bin/bash\n"
+                        "bin:x:1:1:bin:/bin:/sbin/nologin\n";
+  ScopedPasswdFile test_file(libc_make_test_file_path("getpwent_r_rewind.test"),
+                             content);
+
+  struct passwd pwd;
+  char buffer[256];
+  struct passwd *result = nullptr;
+
+  ASSERT_EQ(LIBC_NAMESPACE::getpwent_r(&pwd, buffer, sizeof(buffer), &result),
+            0);
+  ASSERT_EQ(result, &pwd);
+  EXPECT_STREQ(pwd.pw_name, "root");
+
+  LIBC_NAMESPACE::setpwent();
+  result = nullptr;
+  ASSERT_EQ(LIBC_NAMESPACE::getpwent_r(&pwd, buffer, sizeof(buffer), &result),
+            0);
+  ASSERT_EQ(result, &pwd);
+  EXPECT_STREQ(pwd.pw_name, "root");
+
+  LIBC_NAMESPACE::endpwent();
+  result = nullptr;
+  ASSERT_EQ(LIBC_NAMESPACE::getpwent_r(&pwd, buffer, sizeof(buffer), &result),
+            0);
+  ASSERT_EQ(result, &pwd);
+  EXPECT_STREQ(pwd.pw_name, "root");
+}
+
+TEST_F(LlvmLibcGetpwentRTest, BufferTooSmallAndRetryReadsSameEntry) {
+  const char *content = "root:x:0:0:root:/root:/bin/bash\n"
+                        "bin:x:1:1:bin:/bin:/sbin/nologin\n";
+  ScopedPasswdFile test_file(libc_make_test_file_path("getpwent_r_erange.test"),
+                             content);
+
+  struct passwd pwd;
+  char small_buf[8];
+  struct passwd *result = reinterpret_cast<struct passwd *>(0xdeadbeef);
+
+  ASSERT_EQ(
+      LIBC_NAMESPACE::getpwent_r(&pwd, small_buf, sizeof(small_buf), &result),
+      ERANGE);
+  EXPECT_EQ(result, static_cast<struct passwd *>(nullptr));
+
+  result = reinterpret_cast<struct passwd *>(0xdeadbeef);
+  ASSERT_EQ(LIBC_NAMESPACE::getpwent_r(&pwd, small_buf, 0, &result), ERANGE);
+  EXPECT_EQ(result, static_cast<struct passwd *>(nullptr));
+
+  // Retrying with a sufficiently large buffer must read the first record
+  // ("root") rather than skipping past it.
+  char large_buf[256];
+  ASSERT_EQ(
+      LIBC_NAMESPACE::getpwent_r(&pwd, large_buf, sizeof(large_buf), &result),
+      0);
+  ASSERT_EQ(result, &pwd);
+  EXPECT_STREQ(pwd.pw_name, "root");
+}
+
+TEST_F(LlvmLibcGetpwentRTest, BlankLinesSkipped) {
+  const char *content = "\nroot:x:0:0:root:/root:/bin/bash\n\n\n"
+                        "bin:x:1:1:bin:/bin:/sbin/nologin\n\n";
+  ScopedPasswdFile test_file(libc_make_test_file_path("getpwent_r_blank.test"),
+                             content);
+
+  struct passwd pwd;
+  char buffer[256];
+  struct passwd *result = nullptr;
+
+  ASSERT_EQ(LIBC_NAMESPACE::getpwent_r(&pwd, buffer, sizeof(buffer), &result),
+            0);
+  ASSERT_EQ(result, &pwd);
+  EXPECT_STREQ(pwd.pw_name, "root");
+
+  ASSERT_EQ(LIBC_NAMESPACE::getpwent_r(&pwd, buffer, sizeof(buffer), &result),
+            0);
+  ASSERT_EQ(result, &pwd);
+  EXPECT_STREQ(pwd.pw_name, "bin");
+
+  ASSERT_EQ(LIBC_NAMESPACE::getpwent_r(&pwd, buffer, sizeof(buffer), &result),
+            ENOENT);
+  EXPECT_EQ(result, static_cast<struct passwd *>(nullptr));
+}
+
+TEST_F(LlvmLibcGetpwentRTest, FileOpenFailure) {
+  const auto missing_path =
+      libc_make_test_file_path("nonexistent_dir/getpwent_r_missing.test");
+  LIBC_NAMESPACE::pwd::TESTONLY_set_passwd_path(missing_path);
+
+  struct passwd pwd;
+  char buffer[256];
+  struct passwd *result = reinterpret_cast<struct passwd *>(0xdeadbeef);
+
+  ASSERT_EQ(LIBC_NAMESPACE::getpwent_r(&pwd, buffer, sizeof(buffer), &result),
+            ENOENT);
+  EXPECT_EQ(result, static_cast<struct passwd *>(nullptr));
+}
+
+#if defined(LIBC_ADD_NULL_CHECKS) && !defined(LIBC_TESTS_CAN_USE_MPFR)
+TEST_F(LlvmLibcGetpwentRTest, NullPointerCrash) {
+  struct passwd pwd;
+  char buffer[256];
+  struct passwd *result = nullptr;
+  ASSERT_DEATH(
+      [=]() {
+        LIBC_NAMESPACE::getpwent_r(nullptr, const_cast<char *>(buffer),
+                                   sizeof(buffer),
+                                   const_cast<struct passwd **>(&result));
+      },
+      WITH_SIGNAL(-1));
+  ASSERT_DEATH(
+      [=]() {
+        LIBC_NAMESPACE::getpwent_r(const_cast<struct passwd *>(&pwd), nullptr,
+                                   sizeof(buffer),
+                                   const_cast<struct passwd **>(&result));
+      },
+      WITH_SIGNAL(-1));
+  ASSERT_DEATH(
+      [=]() {
+        LIBC_NAMESPACE::getpwent_r(const_cast<struct passwd *>(&pwd),
+                                   const_cast<char *>(buffer), sizeof(buffer),
+                                   nullptr);
+      },
+      WITH_SIGNAL(-1));
+}
+#endif // LIBC_ADD_NULL_CHECKS && !LIBC_TESTS_CAN_USE_MPFR



More information about the libc-commits mailing list