Dear Cygwin developers,
Can you please take a look? - We came across a couple problems (times two, because they're identical for /etc/group as well): 1. When '/etc/passwd' gets reloaded, it can't add the last (default) line for uid=-1 because pretty_ls[] has already been parsed (':'s replaced with '\0'), and can't be parsed again. 2. When there's fork(), a fresh copy of the pretty_ls seems to be loaded, which does not have '\0's in place of ':'s, while the parsed addressed are kept on heap and are still valid. NOTE. The default entry (uid=-1) is needed in case when code runs from a service account(NT SERVICE\...), which can't map to any POSIX UID/GID, so they fail back to -1. The exposition is below, for each bug (WARNING: BUG1 will cause /etc/passwd to be "touch"ed): $ gcc -DBUG1 pwd.c $ ./a.exe pw_name = (0x6118ad2c)???????? pw_passwd = (0x6118ad35)* pw_uid = 4294967295 pw_gid = 4294967295 pw_gecos = (0x6118ad3d) pw_dir = (0x6118ad3e) pw_shell = (0x6118ad3f) pwd = NULL $ gcc -DBUG2 pwd.c $ ./a.exe pw_name = (0x6118ad2c)???????? pw_passwd = (0x6118ad35)* pw_uid = 4294967295 pw_gid = 4294967295 pw_gecos = (0x6118ad3d) pw_dir = (0x6118ad3e) pw_shell = (0x6118ad3f) pw_name = (0x6118ad2c)????????:*:-1:-1::: pw_passwd = (0x6118ad35)*:-1:-1::: pw_uid = 4294967295 pw_gid = 4294967295 pw_gecos = (0x6118ad3d):: pw_dir = (0x6118ad3e): pw_shell = (0x6118ad3f) Best regards, Q. --------------------------------------- #include <pwd.h> #include <grp.h> #include <time.h> #include <stdio.h> #include <string.h> #include <utime.h> #include <unistd.h> #include <stdlib.h> #include <sys/time.h> //#define BUG1 //#define BUG2 static void s_GetPwUid(uid_t uid) { const struct passwd* pwd = getpwuid(uid); if (pwd) { printf("pw_name = (%p)%s\n" "pw_passwd = (%p)%s\n" "pw_uid = %u\n" "pw_gid = %u\n" "pw_gecos = (%p)%s\n" "pw_dir = (%p)%s\n" "pw_shell = (%p)%s\n\n", pwd->pw_name, pwd->pw_name ? pwd->pw_name : "NULL", pwd->pw_passwd, pwd->pw_passwd ? pwd->pw_passwd : "NULL", (unsigned int) pwd->pw_uid, (unsigned int) pwd->pw_gid, pwd->pw_gecos, pwd->pw_gecos ? pwd->pw_gecos : "NULL", pwd->pw_dir, pwd->pw_dir ? pwd->pw_dir : "NULL", pwd->pw_shell, pwd->pw_shell ? pwd->pw_shell : "NULL"); } else { printf("pwd = NULL\n\n"); } } int main(void) { s_GetPwUid(-1); #ifdef BUG1 { time_t t; struct timeval tv[2]; sleep(2); t = time(0); memset(tv, 0, sizeof(tv)); tv[0].tv_sec = t; tv[1].tv_sec = t; utimes("/etc/passwd", tv); s_GetPwUid(-1); } #endif #ifdef BUG2 if (fork()) return 0; s_GetPwUid(-1); #endif return 0; } -- Problem reports: http://cygwin.com/problems.html FAQ: http://cygwin.com/faq/ Documentation: http://cygwin.com/docs.html Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple