ankitpokhrel / tus-php

🚀 A pure PHP server and client for the tus resumable upload protocol v1.0.0

Home Page:https://tus.io

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Corrupted file (got bigger than source) falsely successfully uploaded

heladrion opened this issue · comments

Hello!

I had a weird upload problem. The resulting upload file was bigger than the actual file.
The resulting meta info in the cache said: offset and filesize are the same.
During the upload was in fact a problem. I can see in the server log, that there was an error 409 followed with an HEAD command to continue the upload.

After reading the code the last 3 hours a thousand times, I figured it out, what happened:

File.php

public const APPEND_BINARY = 'ab';

$input  = $this->open($this->getInputStream(), self::READ_BINARY);
$output = $this->open($this->getFilePath(), self::APPEND_BINARY);

$this->seek($output, $this->offset);

Or short:

$output = @fopen($filePath, "ab");
$position = fseek($output, $offset, SEEK_SET);

if (-1 === $position) {
  throw new FileException('Cannot move pointer to desired position.');
}

So the fseek is there to rewind and rewrite a broken chunk... BUT fseek cannot rewind, when openend with the mode "a"! It always appends. Thats why the meta data was thinking everything is fine, but in reality the file got bigger.

Additional context
https://www.php.net/manual/en/function.fseek.php

If you have opened the file in append (a or a+) mode, any data you write to the file will always be appended, regardless of the file position, and the result of calling fseek() will be undefined.

To Reproduce
PATCH 100 Bytes
PATCH 100 Bytes
PATCH 100 Bytes (fails and writes only 40 Bytes - meta stays at 200 Bytes)
PATCH 100 Bytes reports error 409
HEAD -> Gets 200 Bytes as correct offset
PATCH 100 Bytes starting with offset 200
=>
fseek sets offset 200, but a file opened with a=append, doesn't support seek, so the file write continues at 240!

I think adding a
public const READ_WRITE_BINARY = 'r+b';

and using it for the patch function would fix it. The ab is probably still be needed for the merge function

This issue has been automatically marked as stale because it has not had
recent activity. It will be closed if no further activity occurs. Thank you
for your contributions.

Closing because of inactivity.