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
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: derrell at vis-av dot com
New email:
PHP Version: OS:

 

 [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

Pull Requests

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: Sun Dec 22 11:01:30 2024 UTC