php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #15327 copy() causes bus error with files which change size
Submitted: 2002-02-01 13:37 UTC Modified: 2002-07-23 01:00 UTC
Votes:2
Avg. Score:4.5 ± 0.5
Reproduced:2 of 2 (100.0%)
Same Version:0 (0.0%)
Same OS:0 (0.0%)
From: derrell at vis-av dot com Assigned:
Status: No Feedback Package: Reproducible crash
PHP Version: 4.1.1 OS: Linux 2.4.7-10, Redhat 7.2
Private report: No CVE-ID: None
Have you experienced this issue?
Rate the importance of this bug to you:

 [2002-02-01 13:37 UTC] derrell at vis-av dot com
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);
}

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2002-06-17 20:14 UTC] sniper@php.net
Can you please try this snapshot:

http://snaps.php.net/php4-latest.tar.gz

 [2002-07-23 01:00 UTC] php-bugs at lists dot php dot net
No feedback was provided for this bug for over a month, so it is
being suspended automatically. If you are able to provide the
information that was originally requested, please do so and change
the status of the bug back to "Open".
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Fri Apr 26 18:01:31 2024 UTC