Description of problem: The getXXXent_r functions return ENOENT at end of data but they leave errno unchanged. This is a particular problem if an earlier getXXXent_r had set errno to ERANGE. Code sees status!=0 and errno=ERANGE and tries again with a larger buffer until memory is exhausted. Perl's getXXXent functions are affected by this, which explains why they blow up on large systems but not test systems. WebMin is a popular system administration tool which blows up as a result of this. Google reveals a number of reports for which this bug is the explanation. The relevant maintainers seem to have rejected the bug reports as unreproducible because they didn't have long enough lines in their /etc/group. Version-Release number of selected component (if applicable): Reproduced in glibc-2.3.2-27.9.7, glibc-2.3.3-27, and glibc-2.3.3-53. How reproducible: Always. Steps to Reproduce: 1. Run attached program. 2. 3. Actual results: At end of /etc/group it keeps retrying with ever larger buffer sizes. Expected results: Should have set errno=ENOENT when it returned ENOENT, i.e. as soon as it had a large enough buffer. Additional info:
Created attachment 105803 [details] Sample getgrent_r tester which demonstrates glibc bug.
That is not a glibc bug. errno is not defined after getgrent_r call. man getgrent_r has: RETURN VALUE On success, these functions return 0 and *gbufp is a pointer to the struct group. On error, these functions return an error value and *gbufp is NULL. No words about errno being set. POSIX doesn't cover getgrent_r, but getgrnam_r is similar enough and covered by POSIX: ^[TSF] [Option Start] If successful, the getgrnam_r() function shall return zero; otherwise, an error number shall be returned to indicate the error. [Option End] So, your testcase should be checking } else if (rc == ENOENT) { ... } else if (rc != ERANGE) { ... } else { ... }
Does this mean that it is a bug that getgrent_r clobbers errno without warning in the ERANGE case?
errno is undefined after getgrent_r call. See http://www.opengroup.org/onlinepubs/009695399/functions/errno.html The value of errno should only be examined when it is indicated to be valid by a function's return value. ... The setting of errno after a successful call to a function is unspecified unless the description of that function specifies that errno shall not be modified. http://www.opengroup.org/onlinepubs/009695399/functions/getgrnam.html doesn't indicate errno is not modified, nor claims errno is always set, nor does have any return value that indicates errno is valid. Therefore after you call getgrnam_r errno should not be examined. getgrent_r is not covered by POSIX, but behaves in this regard like getgrnam_r (and man getgrent_r describes this).
PERL bug report updated with your information: https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=137202