php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #30924 move_uploaded_file() misbehaves
Submitted: 2004-11-29 01:29 UTC Modified: 2005-02-19 01:00 UTC
Votes:17
Avg. Score:4.1 ± 0.9
Reproduced:16 of 16 (100.0%)
Same Version:5 (31.2%)
Same OS:9 (56.2%)
From: himself at zhwau dot net Assigned:
Status: No Feedback Package: Filesystem function related
PHP Version: 5.0.2 OS: Windows XP
Private report: No CVE-ID: None
 [2004-11-29 01:29 UTC] himself at zhwau dot net
Description:
------------
When trying to POST upload a file with the proper <FORM> tag, including the proper enctype and all (but without size restriction with MAX_FILE_SIZE as in manual example), the receiving script defined in ACTION results in move_uploaded_file() returning TRUE even though the file wasn't moved at all.

Odd things happen when you try reloading the ACTION target page which makes Firefox repost the data - the second time around, the PHP script moves the file, even though it is assigned a different temp file name. Then everything works fine.

Could this be the result of a write-behind process for the filesystem which makes move_uploaded_file() return true even if it didn't move the actual file?

Reproduce code:
---------------
<?php
  // The receiving script
  $ime = $_FILES['slika']['name'];
  if (move_uploaded_file($_FILES['slika']['tmp_name'], $ime)) {
    // Here i execute the code responsible for handling the file
  }
  else {
    // Report that the upload failed
  }
?>

Expected result:
----------------
Should execute the 'ELSE' part of the sentence, since the move_upload_file() should return true in the case of a failed file move - unless it only detects whether or not the tmp_name file exists.

Actual result:
--------------
First time around, the move_uploaded_file() returns true (meaning the temp file exists) but the file isn't moved to $ime (i.e. the same dir where the script is executed).

If you reload the page (and repost the same data), the tmp_name changes while all stays the same and the file is successfully moved.

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2004-11-30 21:26 UTC] tony2001@php.net
Not enough information was provided for us to be able
to handle this bug. Please re-read the instructions at
http://bugs.php.net/how-to-report.php

If you can provide more information, feel free to add it
to this bug and change the status back to "Open".

Thank you for your interest in PHP.


Please, provide more info about your system: webserver version, used SAPI, reproduce code etc.
 [2004-12-01 00:54 UTC] himself at zhwau dot net
The system the command was run on has the following configuration:
- Athlon XP 2000+ 512MB RAM
- Windows XP SP2
- Apache 2.0.52
- PHP 5.0.2 (running as Apache module, php5_module)

The input form that sends the file via POST is as follows:

<FORM enctype="multipart/form-data" action="vnos.php" method="post">
<INPUT type="file" name="slika" size=50>
<INPUT type="submit" value="Poslji">
</FORM>

The receiving page (vnos.php) contains the following code:

<?php
  $ime = $_FILES['slika']['name'];
  $tmp = $_FILES['slika']['tmp_name'];
  if (move_uploaded_file($tmp, $ime)) {
    echo '<H2>File uploaded!';
  }
  else {
    echo '<H2>Error during transfer.</H2>';
  }
?>

If you submit the file in the first file, move_uploaded_file in the second file (vnos.php) returns TRUE, but the file isn't moved. Also, the vardump on $_FILES does return the appropriate information about the contents and properties of the file submitted via POST.

Using Firefox, if you reload the page and acknowledge resending the POSTDATA, then the script executes exactly the same, only this time, the file gets moved. I haven't tested subsequent reloads, but I'm assuming the file gets overwritten.

In short - the function 'move_uploaded_file' does NOT move the file on the first run, but resubmitting the POST data makes the function work properly.

The temp file directory resides in one of the subdirs on the root of the webserver, and the webserver has full access to any file or dir in the document root.
 [2004-12-27 09:33 UTC] himself at zhwau dot net
An update on the problem:

Seems that using copy() to move the file DOES work as expected (ie, as move_uploaded_file is supposed to work). What move_uploaded_file() did first time round is move the uploaded file not to the current path (from where the script is running) but rather to the server root directory - in my case, being something like C:\Progs\Apache2.

Is this a design feature for this function?
 [2005-02-19 01:00 UTC] php-bugs at lists dot php dot net
No feedback was provided for this bug for over a week, 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".
 [2006-12-01 04:17 UTC] alex at mintpixels dot com
I can also confirm that this is a problem in 5.2.0.

I am using move_uploaded_file to move a file from /tmp/<tmpname> to <docroot>/worksheets/3.jpg

On the initial upload, I get no openbase_dir message, and the file writes successfully and the function returns true (as I expected).

On the second upload to the file (where the file exists already), I get an openbase_dir error message in the error log and the file does not write successfully, but the function still returns a true value anyway (not as expected).

I have also witnessed a case where I get no openbase_dir message and the new file writes successfully.  
I verified this by checking the file size had changed between requests (as I had uploaded a different file), which it had.  But I am now unable to reproduce that problem.

In all cases however the function is returning true.

I am using PHP 5.2.0 on Apache 2.0.59 on Linux 2.6.9-42.0.2.ELsmp i686 athlon i386 GNU/Linux.

The permissions of the directory/file are clearly correct because the first upload is writing correctly.  I have also verified the permissions independently by doing $h=fopen("$docroot/worksheets/3.jpg"); fwrite($h,"test"); fclose($h);
The file is created and contains the line as expected.

--------------------------------------------------------
In line with the guidelines, I have downloaded the latest build from CVS, and the following behaviour has changed.

I now get an open_basedir warning message on the initial upload in the log, but the file is written anyway, and the function still returns true.

the same behaviour persists with the second upload.
 [2006-12-01 04:27 UTC] alex at mintpixels dot com
I have created a simple test case:

<html><body><form method='POST' action='testUpload.php' accept-charset="UTF-8" enctype="multipart/form-data">
<input type='hidden' name='MAX_FILE_SIZE' value="300000000"/>
<input type='file' name='worksheet_new'/><br/>
<input type='submit' value='submit'/>
</body>
</html>

posts to 

<?php
$location="<path to my directory>";
if (move_uploaded_file($_FILES['worksheet_new']['tmp_name'],$location)) {

}
 [2006-12-01 04:28 UTC] alex at mintpixels dot com
oops - hit tab then space, so it submitted before I was done:

if (move_uploaded_file($_FILES['worksheet_new']['tmp_name'],$location)) {
  echo "Success";
} else {
  echo "Failure";
}

This prints the warning message, then "Success" when executed.
 [2009-01-11 21:56 UTC] a1bert at atlas dot cz
I am experiencing simillar issue:

move_uploaded_file() launches warning about:
"move_uploaded_file() [function.move-uploaded-file]: open_basedir 
restriction in effect. File(/var/tmp/php/phpDvi4ra) is not within 
the allowed path(s):"

but returns success and file is successfully moved (even when 
replacing existing file)

PHP Version 5.2.0-8+etch13
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Fri Oct 04 21:01:27 2024 UTC