libnui / nui3

libnui v3
http://libnui.net
Mozilla Public License 2.0
163 stars 31 forks source link

File copy via PipeTo can lead to infinite loop #25

Open mathieugarcia opened 12 years ago

mathieugarcia commented 12 years ago

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);

        // [stripped]

    if (WordSize == 1)
        return done;

        // [stripped]

    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.

mathieugarcia commented 12 years ago

Will typically happen when no space is left on device.