Collectives™ on Stack Overflow
Find centralized, trusted content and collaborate around the technologies you use most.
Learn more about Collectives
Teams
Q&A for work
Connect and share knowledge within a single location that is structured and easy to search.
Learn more about Teams
I've got a C program that reproduces a server using FIFOs. The program reads two lines from an input FIFO — a number
n
and a string
str
— and writes on an output FIFO
n
lines, each of which is a single occurrence of
str
. I wrote the following code.
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#define MAX_SIZE 256
char *readline(int fd, char *buffer) {
char c;
int i = 0;
while (read(fd, &c, 1) != 0) {
if (c == '\n')
break;
buffer[i++] = c;
return buffer;
int main(int argc, char** argv) {
mkfifo(argv[1], 0666);
mkfifo(argv[2], 0666);
int in = open(argv[1], O_RDONLY);
int out = open(argv[2] ,O_WRONLY);
char line[MAX_SIZE];
memset(line, 0, MAX_SIZE);
int n, i;
while (1) {
strcpy(line, readline(in, line));
sscanf(line, "%d", &n);
strcpy(line, readline(in, line));
for (i = 0; i < n; i++) {
write(out, line, strlen(line));
write(out, "\n", 1);
close(in);
close(out);
return 0;
This program compiles and runs with no errors, but it outputs a different number of occurrences of the string at each execution. For example, if the two input lines in the input FIFO are 5\nhello
, it then prints out from 1 to 25 occurrences of hello
at each run (frequency appears to be completely random).
I've been stuck on this for two days. Please give me some help.
–
–
I make no claims or warrants that I even know what your program does, as it has been 20 years since I had any pressing need to work with FIFO's at the system level. But one thing is clear. Two days is a long time to work on something without ever running it in a debugger, of which doing so would have exposed a number of problems.
First, readline()
never terminates the string it is passed. This isn't as important the first time around as the second and beyond, since shorter data may be present in the input lines. Furthermore, read()
can fail, and in doing so does not return 0
, the only condition on your loop which will break. That failure should break the loop and be reflected in the return result. Because you return the buffer pointer, a reasonable failure-result could be NULL:
Consider something like this:
char *readline(int fd, char *buffer)
ssize_t res = 0;
char c = 0;
int i = 0;
for(;;)
res = read(fd, &c, 1);
if (res < 0)
return NULL;
else if (res == 0 || c == '\n')
break;
buffer[i++] = c;
buffer[i] = 0;
return buffer;
One could argue that it should return NULL if the buffer is empty, since you can't put a 0-length packet on a FIFO. I leave that for you to decide, but it is a potential hole in your algorithm, to be sure.
Next the strcpy()
function has undefined behavior if the buffers submitted overlap. Since readline()
returns the very buffer that was passed in, and since said-same buffer is also the target of strcpy()
is the same buffer, your program is executing UB. From all that I see, strcpy()
is useless in this program in the first place, and shouldn't even be there at all.
This is clearly wrong:
strcpy(line, readline(in, line));
sscanf(line, "%d", &n);
strcpy(line, readline(in, line));
for (i = 0; i < n; i++) {
write(out, line, strlen(line));
write(out, "\n", 1);
The above should be this:
if (readline(in, line))
if (sscanf(line, "%d", &n) == 1)
if (readline(in, line))
for (i = 0; i < n; i++)
write(out, line, strlen(line));
write(out, "\n", 1);
assuming the changes to readline()
as prescribed were made. These could be combined into a single three-expression if-clause, but as written above it is at-least debuggable. In other words, via short-circuit eval there should be no problems doing this:
if (readline(in, line) &&
sscanf(line, "%d", &n) == 1 &&
readline(in, line))
for (i = 0; i < n; i++)
write(out, line, strlen(line));
write(out, "\n", 1);
but I would advise you keep the former until you have thoroughly debugged this.
Finally, note that readline()
is still a buffer overflow just waiting to happen. You really should pass a max-len to that function and limit that potential possibility, or dynamically manage the buffer.
–
The code does not initalises line
for each iteration, so if readline()
does not read anything it leaves line
's content untouched.
And you do not test whether sscanf()
fails, the code does not recognize als n
is left unchanged and the last value of line
get printed out n
times and everything starts over again ...
Also readline()
misses to check whether read()
failed.
To learn from this exercise it to always test the result of a (system) call whether it failed or not.
int readline(int fd, char *buf, int nbytes) {
int numread = 0;
int value; /* read fonksiyonu sonunda okunan sayı degerini gore islem yapar */
/* Controls */
while (numread < nbytes - 1) {
value = read(fd, buf + numread, 1);
if ((value == -1) && (errno == EINTR))
continue;
if ( (value == 0) && (numread == 0) )
return 0;
if (value == 0)
break;
if (value == -1)
return -1;
numread++;
/* realocating for expand the buffer ...*/
if( numread == allocSize-2 ){
allocSize*=2; /* allocSize yeterli olmadıgı zaman buf ı genisletmemizi saglayarak
memory leak i onler */
buf=realloc(buf,allocSize);
if( buf == NULL ){
fprintf(stderr,"Failed to reallocate!\n");
return -1;
/* Eger gelen karakter \n ise return okudugu karakter sayısı */
if (buf[numread-1] == '\n') {
buf[numread] = '\0';
return numread;
errno = EINVAL;
return -1;
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.