View Issue Details

IDProjectCategoryView StatusLast Update
00019531003.1(2013)/Issue7+TC1System Interfacespublic2025-10-27 21:39
Reportereblake Assigned To 
PrioritynormalSeverityObjectionTypeClarification Requested
Status NewResolutionOpen 
NameEric Blake
OrganizationRed Hat
User Referenceeblake.getdelim
SectionXSH getdelim
Page Number1114
Line Number38262
Interp Status---
Final Accepted Text
Summary0001953: getdelim() behavior is ambiguous on empty file
DescriptionWhen Issue 7 added getdelim() and getline() in 2008, the intent was that we would be standardizing the interface already implemented by glibc at the time.

However, a recent glibc bug report complained that the wording in POSIX disagrees with the behavior of glibc when calling getdelim() on an empty file: https://sourceware.org/bugzilla/show_bug.cgi?id=28038. According to the bug report, if the file is empty, then getdelim() immediately encounters end-of-file and must return -1, but even though it is returning -1, it is NOT returning an error (errno is not set and the stream error indicator is clear), so the argument was that POSIX requires *lineptr to be an empty string (truncating any contents already in lineptr from an earlier invocation). But the glibc behavior at the time POSIX added the interface was to leave the contents of *lineptr unchanged unless returning a non-negative value for success (although lineptr itself might be modified, as it could have been allocated prior to detecting end-of-file).

So glibc recently patched its behavior to guarantee that on encountering EOF that a NUL terminator is added, but this has the observable side effect that where you could previously use a loop of getline() until returning -1 to grab the last line of a file (think, for example, of the summary line of a du invocation), now such a loop leaves lineptr on an empty string rather than the last line of the file.

While POSIX is clear that encountering EOF on success must use a null terminator, it is less obvious whether returning -1 falls under the same rules, or whether POSIX should have allowed the traditional glibc behavior. On the one hand, guaranteeing that a non-NULL lineptr always has a null terminator even when getdelim() fails makes it harder for a programmer mistake to escalate into a SEGFAULT for reading beyond the bounds of the array. On the other hand, forcefully terminating lineptr to an empty string after the last non-empty line with a proper terminator takes away a convenient access to the contents of the last line of a file, although it is not quite obvious whether that was ever portable.

The desired action lists two approaches: one to relax things to explicitly permit the older glibc behavior and warn the user that the contents of *lineptr are not necessarily usable on a return of -1 (although this still does not guarantee stable access to the last line of the file); the other to tighten the specification to mandate that any time *lineptr is returned non-NULL, it must be null terminated even if the overall function fails for any other reason. I'm not sure which of the two options the group will prefer.
Desired ActionOption 1 (relax behavior on returning -1):

Change line 38262 from
The characters read, including any delimiter, shall be stored in the object, and a terminating NUL added when the delimiter or end-of-file is encountered.
to
If any characters are read, the characters read, including any delimiter, shall be stored in the object, and a terminating NUL added when the delimiter or end-of-file is encountered.


Add a sentence to the paragraph ending at line 38276:
If the return value is -1, the contents of *lineptr are indeterminate.


At line 38314, change
Although a null terminator is always supplied after the line,
to
Although a null terminator is always supplied after the line on success,


Option 2 (guarantee null terminator even on failure):

Add a sentence to the paragraph ending at line 38276:
If the return value is -1, and *lineptr is not a null pointer, its contents shall be an empty string.
TagsNo tags attached.

Activities

There are no notes attached to this issue.

Issue History

Date Modified Username Field Change
2025-10-27 21:39 eblake New Issue