php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #81145 copy() and stream_copy_to_stream() fail for +4GB files
Submitted: 2021-06-16 09:43 UTC Modified: 2021-06-16 11:04 UTC
From: php at bitm dot sg Assigned: cmb (profile)
Status: Closed Package: Filesystem function related
PHP Version: 7.4 OS: Windows 10.0.19042.985 x64
Private report: No CVE-ID: None
 [2021-06-16 09:43 UTC] php at bitm dot sg
Description:
------------
Using copy() or stream_copy_to_stream() fails on Windows with files over 4GB, even if the underlying volume (NTFS) supports it and Windows + PHP are 64 bit.

Test script:
---------------
<?php
	//Both files must be on an NTFS volume. You may use the same volume.
	$src='C:/temp/4G.src.bin';
	$dst='C:/temp/4G.dst.bin';
	define('SIZE_4G',0x100000000);

	@unlink($src);
	//Create file and append random content at the 4GB boundary
	exec('fsutil file createnew ' . escapeshellarg($src) . ' ' . (SIZE_4G-0x100));
	$fp=fopen($src,'ab');
	fwrite($fp,random_bytes(0x200));
	fclose($fp);
	copy($src,$dst);
	if(filesize($src)!==filesize($dst)){die('Files have different sizes!');}
	$f1=fopen($src,'rb') or die('src open failed');
	$f2=fopen($dst,'rb') or die('dst open failed');
	//Seek to 4 GB boundary, as this is the location where the problem occurs
	fseek($f1,SIZE_4G-0x100,SEEK_SET);
	fseek($f2,SIZE_4G-0x100,SEEK_SET);
	echo (fread($f1,0x200)===fread($f2,0x200)?'Identical':'Copy failed');
	fclose($f1);
	fclose($f2);


Expected result:
----------------
The functions should copy files and streams as-is and the script should print "Identical"

Actual result:
--------------
Script prints "Copy failed"

Only the first 4 GB of the source file are copied.
This is actually done repeatedly until the destination is as large as the source. So if the file is 13 GB, the destination will contain the first 4 GB of the source 3 times, followed by the first GB again.

using "fwrite($b,fread($a,$buffer))" to manually copy files works.

Patches

Add a Patch

Pull Requests

Pull requests:

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2021-06-16 09:56 UTC] nikic@php.net
-Assigned To: +Assigned To: cmb
 [2021-06-16 09:56 UTC] nikic@php.net
Seems to work fine on Linux.
 [2021-06-16 10:14 UTC] php at bitm dot sg
-Operating System: Microsoft Windows [Version 1 x64 +Operating System: Windows 10.0.19042.985 x64
 [2021-06-16 10:14 UTC] php at bitm dot sg
Fixed the Windows version because it was cut off.
 [2021-06-16 11:04 UTC] cmb@php.net
-Status: Assigned +Status: Analyzed -PHP Version: 8.0.7 +PHP Version: 7.4
 [2021-06-16 11:04 UTC] cmb@php.net
Confirmed (affects PHP-7.4 on Windows as well).

Thanks for the helpful analysis on reddit[1].

[1] <https://www.reddit.com/r/PHP/comments/o0oqhg/problems_copying_large_files/h1y9a5t/>
 [2021-06-16 11:19 UTC] cmb@php.net
The following pull request has been associated:

Patch Name: Fix #81145: copy() and stream_copy_to_stream() fail for +4GB files
On GitHub:  https://github.com/php/php-src/pull/7158
Patch:      https://github.com/php/php-src/pull/7158.patch
 [2021-06-17 11:19 UTC] git@php.net
Automatic comment on behalf of cmb69
Revision: https://github.com/php/php-src/commit/2555efadbc1f8124448fcd73c1c208f3abe430e5
Log: Fix #81145: copy() and stream_copy_to_stream() fail for +4GB files
 [2021-06-17 11:19 UTC] git@php.net
-Status: Analyzed +Status: Closed
 
PHP Copyright © 2001-2021 The PHP Group
All rights reserved.
Last updated: Fri Sep 17 18:03:38 2021 UTC