about summary refs log tree commit diff
path: root/pwd
diff options
context:
space:
mode:
Diffstat (limited to 'pwd')
-rw-r--r--pwd/tst-getpw.c83
1 files changed, 77 insertions, 6 deletions
diff --git a/pwd/tst-getpw.c b/pwd/tst-getpw.c
index 059c9e0217..e3e101b9f4 100644
--- a/pwd/tst-getpw.c
+++ b/pwd/tst-getpw.c
@@ -15,28 +15,99 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
+#include <stdio.h>
 #include <pwd.h>
+#include <errno.h>
+#include <stdbool.h>
+
+/* We want to test getpw by calling it with a uid that does
+   exist and one that doesn't exist. We track if we've met those
+   conditions and exit. We also track if we've failed due to lack
+   of memory. That constitutes all of the standard failure cases.  */
+bool seen_hit;
+bool seen_miss;
+bool seen_oom;
+
+/* How many errors we've had while running the test.  */
+int errors;
 
 static void
 check (uid_t uid)
 {
+  int ret;
   char buf[1024];
 
-  (void) getpw (uid, buf);
+  ret = getpw (uid, buf);
+
+  /* Successfully read a password line.  */
+  if (ret == 0 && !seen_hit)
+    {
+      printf ("PASS: Read a password line given a uid.\n");
+      seen_hit = true;
+    }
+
+  /* Failed to read a password line. Why?  */
+  if (ret == -1)
+    {
+      /* No entry?  Technically the errno could be any number
+	 of values including ESRCH, EBADP or EPERM depending
+	 on the quality of the nss module that implements the
+	 underlying lookup. It should be 0 for getpw.*/
+      if (errno == 0 && !seen_miss)
+	{
+	  printf ("PASS: Found an invalid uid.\n");
+	  seen_miss = true;
+	  return;
+	}
+
+      /* Out of memory?  */
+      if (errno == ENOMEM && !seen_oom)
+	{
+	  printf ("FAIL: Failed with ENOMEM.\n");
+	  seen_oom = true;
+	  errors++;
+	}
+
+      /* We don't expect any other values for errno.  */
+      if (errno != ENOMEM && errno != 0)
+	errors++;
+    }
 }
 
 static int
 do_test (void)
 {
+  int ret;
   uid_t uid;
 
-  /* Just call it a different number of times the range should be
-     large enough to find some existing and some non existing uids.  */
+  /* Should return -1 and set errnot to EINVAL.  */
+  ret = getpw (0, NULL);
+  if (ret == -1 && errno == EINVAL)
+    {
+      printf ("PASS: NULL buffer returns -1 and sets errno to EINVAL.\n");
+    }
+  else
+    {
+      printf ("FAIL: NULL buffer did not return -1 or set errno to EINVAL.\n");
+      errors++;
+    }
+
+  /* Look for one matching uid, one non-found uid and then stop.
+     Set an upper limit at the 16-bit UID mark; no need to go farther.  */
+  for (uid = 0; uid < ((uid_t) 65535); ++uid)
+    {
+      check (uid);
+      if (seen_miss && seen_hit)
+	break;
+    }
+
+  if (!seen_hit)
+    printf ("FAIL: Did not read even one password line given a uid.\n");
 
-  for (uid = 0; uid < 2000; ++uid)
-    check (uid);
+  if (!seen_miss)
+    printf ("FAIL: Did not find even one invalid uid.\n");
 
-  return 0;
+  return errors;
 }
 
 #define TEST_FUNCTION do_test ()