package: libc6 version: 2.3.6.ds1-13etch2 severity: wishlist Possible partial fix for fgets and alternatives. Bug #57729 is marked as done. It could be fixed for real. I have found null escapes a pretty reliable way of breaking many C programs including various editors. The standard C <stdio.h> fgets function is just plain wrong. fputs stops at a '\0', but fgets may only stop at '\n' even if a '\0' is encountered. There is no way of knowing how much is read by fgets. These functions are inconsistent and are not binary safe. The standard should be fixed. In fcat2.c I add a function int fngets(char *s, int size, FILE *stream); which has similar functionality to GNU getline. This can be used with fwrite. As fngets does not exist it could be added by any <stdio.h> user and will be portable. In fcat.c I simply fix the broken fputs function in such a way that it should not break existing use. I also suggest some macros to check the <stdio.h> buffer so that more efficient <unistd.h> can be mixed, even though POSIX makes it clear that this should not be done. How many extra CPU cycles to match '\n' or '\0' rather than just match '\n' in the library fgets functions? I give ESMTP as an example of a new line matching problem as this often uses <stdio.h> and is often exploited by remote. Many other applications match new lines and could also be fed '\0's by remote. Trivial examples attached. These are not thread safe.
tag 451886 + wontfix thanks The libc will follow the standard, and the standard will never ever "fix" things like that. If you're going to read binary data, indeed, you should not use FILE* or fgets, but plain read(1) calls with non blocking sockets in a select loop. Anyway, the glibc _packaging_ team will never ever take the liberty to introduce new symbols that arent in the upstream glibc, it would be way too disruptive, so please bring this upstream, we don't have the resources to do that for you. and yes btw fputs stops at the first \0 because it puts a string, and strings in C are NUL terminated. fgets has a disruptive API, and _yes_ I would very much prefer that fgets had this API intead of the current: ssize_t fgets(char *buf, size_t len); with the usual semantics that -1 means error (with errno set properly), and else the return value would be the amount of bytes written in the buffer buf, not counting the last '\0', meaning that the return value would be at most equal to len - 1. Or even name this fgetline as it's what it does for real. Sadly it's not the case, blame the C committee. Meanwhile I'm leaving that bug as wontfix.
In support of this not being a bug, I have code which uses the correct, standards-compliant behavior of fgets. Contrary to Andrew's report, it's very easy to know how much is read by fgets and use it with data containing '\0'. Simply ensure the buffer does not contain any occurrances of '\n' (for instance memset to all '\0') before reading, then use memchr to search for '\n' in the results. If you find '\n', its position tells how many bytes were read. If not, the entire buffer was filled without reaching a newline.