The example input/output handler in this EXAMPLE is subject to introducing subtle bugs if the input stream contains literal null bytes. Subsequently, there should be some warning that this occurs, or an alternative using fwrite(3) might be better. ( I also note there's no obvious direction in the printf(3) pages what one should do if they expect their data to contain nulls, but clarifying that is much harder in such an already lengthy document ) Context: - Relative C novice, have experience, but dated and in need of refresh - Aware there are fun security concerns in C, but not fully able to remember them all - Wanted to use a "Safe" way to handle input linewise, internet searches lead me to getline - Made implementation of a simple thing I wanted ( purpose was to simply skip a fixed number of lines from input before writing them to output ) - Basically copied example with minor adjustments - Compared output of chunks of /dev/urandom with my program with a perl oneliner that did the same - Anomalous problems happened. - Output analysis with `xxd` showed me \0 - *remembers how strings in C work* - Have to work out how to output strings with nulls - Eventually discover fwrite() Granted a more seasoned C programmer would have likely not made this mistake, but I consider it an implementation bug in the example as-is that it silently mutates data. --- #define _GNU_SOURCE #include <stdio.h> #include <stdlib.h> int main(void) { FILE *stream = stdin; char *line = NULL; size_t len = 0; ssize_t read; if (stream == NULL) exit(EXIT_FAILURE); while ((read = getline(&line, &len, stream)) != -1) { printf("Retrieved line of length %zu :\n", read); printf("%s", line); } free(line); fclose(stream); exit(EXIT_SUCCESS); } --- echo -e 'hello\0world\nthis is a test\n' | /tmp/getline Retrieved line of length 12 : helloRetrieved line of length 15 : this is a test Retrieved line of length 1 : --- > This page is part of release 4.09 of the Linux man-pages project
I've modified the example to use fwrite(3) (and also made a few other fixes to the program). Closing this report. #define _GNU_SOURCE #include <stdio.h> #include <stdlib.h> int main(int argc, char *argv[]) { FILE *stream; char *line = NULL; size_t len = 0; ssize_t nread; if (argc != 2) { fprintf(stderr, "Usage: %s <file>\n", argv[1]); exit(EXIT_FAILURE); } stream = fopen(argv[1], "r"); if (stream == NULL) { perror("fopen"); exit(EXIT_FAILURE); } while ((nread = getline(&line, &len, stream)) != -1) { printf("Retrieved line of length %zu:\n", nread); fwrite(line, nread, 1, stdout); } free(line); fclose(stream); exit(EXIT_SUCCESS); }