From:             [EMAIL PROTECTED]
Operating system: Linux 2.4.7-10, Redhat 7.2
PHP version:      4.1.1
PHP Bug Type:     Reproducible crash
Bug description:  copy() causes bus error with files which change size

The copy() function (actually php_copy_file() at ext/standard/file.c:1934)
uses mmap() when available.  The mmap() function has the documented
"feature" (bug!) that if the file that is mapped is truncated (e.g. by
another process) after mmap() is called, a SIGBUS (bus error) signal is
generated during the write() to the destination file using the mmap'ed
pointer as the source of the write.  This, of course, crashes php.

I can not find a workaround for this.  I have not been able to find any
combination of flags to pass to mmap such that mmap() will fail gracefully
rather than write() failing non-gracefully.  Don't use mmep()?  That would
be a shame, but seems to be the solution.

Simple example.  Note that /computers/win95 is an smbmount'ed file system.
 The file being accessed here, a Window's swap file, is of course changing
all the time.

<?php
copy("/computers/win95/C/WINDOWS/WIN386.SWP", "/tmp/zzz");
?>

Here's a simple C program which replicates what's going on in
php_copy_file()

#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>

int main(int argc, char * argv[])
{
  int             fdSrc;
  int             fdDest;
  int             len;
  char            buf[8192];
  void *          srcfile;
  struct stat     sbuf;


  if ((fdSrc = open("/computers/win95/C/WINDOWS/WIN386.SWP", 0)) < 0)
    {
      perror("open");
      exit(1);
    }

  if ((fdDest = creat("/tmp/zzz", 0777)) < 0)
    {
      perror("creat");
      exit(1);
    }

  if (fstat(fdSrc, &sbuf))
    {
      perror("fstat");
      exit(1);
    }

  srcfile = mmap(NULL, sbuf.st_size, PROT_READ, MAP_SHARED, fdSrc, 0);
  printf("srcfile=%p\n", srcfile);
  if (srcfile != (void *) MAP_FAILED)
    {
      if ((len = write(fdDest, srcfile, sbuf.st_size)) != sbuf.st_size)
        {
          printf("write returned %d; expected %d\n", len, sbuf.st_size);
        }
      munmap(srcfile, sbuf.st_size);
    }

  printf("Success\n");
  close(fdSrc);
  close(fdDest);
  exit(0);
}

-- 
Edit bug report at: http://bugs.php.net/?id=15327&edit=1


-- 
PHP Development Mailing List <http://www.php.net/>
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
To contact the list administrators, e-mail: [EMAIL PROTECTED]

Reply via email to