libnui/nui3 — Issue #25: File copy via PipeTo can lead to infinite loop
Author: mathieugarcia
Created: 2011-11-29 13:16:20+00:00
State: open

When copying a file via `nglPath::Copy`, `nglIStream::PipeTo` is used:

```
while (( istate == eStreamReady || istate == eStreamWait ) && ( ostate == eStreamEnd || ostate == eStreamWait ))
{
piped_in = Read( buffer, PIPE_BUF_SIZE, 1 );
istate = this->GetState();

while ( piped_in > 0 && ( ostate == eStreamEnd || ostate == eStreamWait ) )
{
piped_out = rTarget.Write( buffer, piped_in, 1 );

ostate = rTarget.GetState();
piped_in -= piped_out;
total_piped += piped_out;
}
}
```

Let's see `nglFile::Write`:

```
done = ngl_fwrite(pData, 1, (size_t)(WordCount * WordSize), mFD);

if (swapped)
free ((void*)pData); // Force const-check (it's OK)
if (mAutoFlush)
Flush();

if (WordSize == 1)
return done;
rest = done % WordSize;
if (rest != 0)
SetPos (rest, eFileRewind);
done /= WordSize;
return done;
}
```
There, `ngl_fwrite()` call can return 0 or -1. If -1 is returned, `done /= WordSize` will result in done being 0.
Maybe all Write() wrappers should threat -1 as an error.

Going back into `PipeTo`, 0 can be returned from the above Write call:

```
piped_in -= piped_out;
total_piped += piped_out;
```

`piped_in` is never decreased, resulting in an infinite loop.