php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #71630 copy function does not work if destination file does not exist
Submitted: 2016-02-19 12:39 UTC Modified: 2016-02-19 17:49 UTC
Votes:1
Avg. Score:5.0 ± 0.0
Reproduced:0 of 0 (0.0%)
From: vladimir at volomp dot com Assigned: cmb (profile)
Status: Not a bug Package: *General Issues
PHP Version: 5.5.32 OS: linux/all
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: vladimir at volomp dot com
New email:
PHP Version: OS:

 

 [2016-02-19 12:39 UTC] vladimir at volomp dot com
Description:
------------
Fails to copy a.txt to b.txt if b.txt is missing.
If we just touch b.txt, copy will work.


There is possibly relevant code in ext/standard/file.c in function php_copy_file_ctx() where dest is checked the same way source is (suspected copy&paste).

        switch (php_stream_stat_path_ex(dest, PHP_STREAM_URL_STAT_QUIET | PHP_STREAM_URL_STAT_NOCACHE, &dest_s, ctx)) {
                case -1:
                        /* non-statable stream */
                        goto safe_to_copy;
                        break;
                case 0:
                        break;
                default: /* failed to stat file, does not exist? */
                        return ret;
        }


So it is unclear if PHP_STREAM_URL_STAT_QUIET has any influence on return code - but I guess NO, so then this block of code is incorrect and should have default goto safe_to_copy.

This code is more-less same for php 5.6 and 7, however 5.2.17 which we still use do not have this bug as check is done differently:

        if (php_stream_stat_path_ex(dest, PHP_STREAM_URL_STAT_QUIET, &dest_s, NULL) != 0) {
                goto safe_to_copy;
        }




Test script:
---------------
copy( "a.txt", "b.txt" );




Patches

php_copy_file_ctx-destination-check-fix (last revision 2016-02-19 12:40 UTC by vladimir at volomp dot com)

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2016-02-19 13:28 UTC] danack@php.net
-Status: Open +Status: Feedback
 [2016-02-19 13:28 UTC] danack@php.net
Please can you provide some context of how you are encountering a problem. i.e. provide a reproduce scripts.


The code below works for me:

<?php

file_put_contents("a.txt", "These are some words");
copy("a.txt", "b.txt");
var_dump(file_exists("b.txt"));

//output is bool(true)

without b.txt existing first.
 [2016-02-19 13:38 UTC] vladimir at volomp dot com
-Status: Feedback +Status: Open
 [2016-02-19 13:38 UTC] vladimir at volomp dot com
Your script is just fine for testing. I get bool(false) consistently.

php --version

PHP 5.5.16 (cli) (built: Aug 31 2014 16:22:37)
Copyright (c) 1997-2014 The PHP Group
Zend Engine v2.5.0, Copyright (c) 1998-2014 Zend Technologies
    with Zend OPcache v7.0.4-dev, Copyright (c) 1999-2014, by Zend Technologies


<?php

file_put_contents("a.txt", "These are some words");
copy("a.txt", "b.txt");
var_dump(file_exists("b.txt"));



I will git clone and check completely stock .32
 [2016-02-19 13:48 UTC] danack@php.net
Please can you confirm that you don't have any security modules active that would prevent creation of new files - such as SELinux or Suhosin?

I think it is far more likely that it is some problem unique to your computer rather than a general bug with copy().
 [2016-02-19 13:56 UTC] vladimir at volomp dot com
I have patched my server with same check as in 5.2.17 and it now works flawlessly. Could somebody explain how could this actually work? 

Is it php_stream_stat_path_ex() supposed to return 0 if file is not found?  This code just doesn't seem right.
 [2016-02-19 14:03 UTC] vladimir at volomp dot com
Seems that git 5.5.32 works just fine, as expected. I do have other patches inside, as this is redhat based rpm. Sorry, off I go to check further. But still I do not understand how could it possibly work with this switch/case?

When file does not exist, should -1 as 'non-statable stream' be expected, or some other error code?
 [2016-02-19 14:28 UTC] danack@php.net
-Status: Open +Status: Feedback
 [2016-02-19 14:28 UTC] danack@php.net
> When file does not exist, should -1 as 'non-statable stream' be expected,

I believe that is correct.

> Is it php_stream_stat_path_ex() supposed to return 0 if file is not found?

I believe the return values mirror those of standard system stat calls - 0 indicates success, other values a errors. http://linux.die.net/man/2/stat


If you're not seeing the error on git 5.5.32, then you'll need to isolate where the error has been introduced as we are unable to reproduce it.
 [2016-02-19 15:40 UTC] vladimir at volomp dot com
-Status: Feedback +Status: Open
 [2016-02-19 15:40 UTC] vladimir at volomp dot com
Danack, thanks for your input. I have solved the problem - it was indeed one of the custom patches that was faulty, causing stat to return a bit unexpected value 2, that came from errno by mistake.
 [2016-02-19 17:49 UTC] cmb@php.net
-Status: Open +Status: Not a bug -Assigned To: +Assigned To: cmb
 [2016-02-19 17:49 UTC] cmb@php.net
So closing as "not a bug".
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Fri Dec 27 03:01:28 2024 UTC