diff options
Diffstat (limited to 'pwd')
-rw-r--r-- | pwd/tst-getpw.c | 83 |
1 files changed, 77 insertions, 6 deletions
diff --git a/pwd/tst-getpw.c b/pwd/tst-getpw.c index 059c9e0..e3e101b 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 () |