php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #22362 Certain combinations of fseek() and fwrite() produce unexpected results
Submitted: 2003-02-21 13:58 UTC Modified: 2003-02-22 12:55 UTC
Votes:3
Avg. Score:5.0 ± 0.0
Reproduced:3 of 3 (100.0%)
Same Version:2 (66.7%)
Same OS:1 (33.3%)
From: php at codewhore dot org Assigned: wez (profile)
Status: Closed Package: Filesystem function related
PHP Version: 4.3.1 OS: Linux 2.4
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: php at codewhore dot org
New email:
PHP Version: OS:

 

 [2003-02-21 13:58 UTC] php at codewhore dot org
In PHP:

<?php
  $fp = fopen('./foo', 'w+');
  fwrite($fp, 'quxbar', 6);
  fseek($fp, 3, SEEK_SET);
  fread($fp, 1);
  fseek($fp, 4, SEEK_SET);
  fwrite($fp, '!', 1);
  fseek($fp, 0, SEEK_SET);
  $buf = fread($fp, 4095);
  echo "$buf\n";
?>

In C:

#include <stdio.h>

int main()
{
  static char buf[4096];
  FILE *f = fopen("./foo", "w+");
  fwrite("quxbar", 6, 1, f);
  fseek(f, 3, SEEK_SET);
  fread(&buf, 1, 1, f);
  fseek(f, 4, SEEK_SET);
  fwrite("!", 1, 1, f);
  fseek(f, 0, SEEK_SET);
  fread(&buf, 4095, 1, f);
  printf("%s\n", buf);
  return 0;
}

The PHP version outputs 'quxbar!.
The C version outputs 'quxb!r'.

In fact, for any PHP code of the structure:
<?php
  fseek($fp, $x, SEEK_SET);
  fread($fp, $n);
  fseek($fp, $y, SEEK_SET);
  fwrite($fp, '!', 1);
?>

the data from the fwrite always gets written to the end of the stream when $x < $y and $n is exactly 1. I can reproduce this with different whence parameters, but it seems to only happen with a seek followed by a single-byte read.

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2003-02-21 14:43 UTC] php at codewhore dot org
I've verified that this behavior still exists in today's snapshot (php4-STABLE-200302212030.tar.gz).
 [2003-02-21 17:02 UTC] php at codewhore dot org
I'm still mostly lost, but commenting out the following segment of code fixes the problem for the test case. Obviously this isn't the solution, but I think I have it narrowed down to _php_stream_seek thinking that the underlying file position matches the seek offset when it doesn't in reality.

PHPAPI int _php_stream_seek(php_stream *stream, off_t offset, int whence TSRMLS_DC)
{
    /* not moving anywhere */
#if 0
    if ((offset == 0 && whence == SEEK_CUR) || (offset == stream->position && whence == SEEK_SET))
        return 0;
#endif
 [2003-02-21 17:44 UTC] php at codewhore dot org
FWIW, the problem also occurs in the following piece of code:

<?php
  $fp = fopen('./foo', 'w+');
  fwrite($fp, 'quxbar', 6);
  fseek($fp, 3, SEEK_SET);
  fread($fp, 1);
  fwrite($fp, '!', 1);
  fseek($fp, 0, SEEK_SET);
  $buf = fread($fp, 4095);
  echo "$buf\n";
?>

There's no fseek() between the fread() and fwrite(), so my previous theory seems to be quite wrong. I'll do more digging as time permits...
 [2003-02-21 18:40 UTC] wez@php.net
Save yourself some energy :)

I'm going to look into this this weekend; I know precisely
how to fix this, and it most likely not something you
would have time to think of by the time I've sorted it
out :)

I will update this report when it is fixed and you will be able to try the fix using a stable snapshot.

Thanks for your efforts so far!
 [2003-02-21 19:38 UTC] php at codewhore dot org
Thanks. Glad I could be of (some) help. :)
 [2003-02-21 20:46 UTC] wez@php.net
Please try using this CVS snapshot:

  http://snaps.php.net/php4-STABLE-latest.tar.gz
 
For Windows:
 
  http://snaps.php.net/win32/php4-win32-STABLE-latest.zip

Try the next stable snapshot.
 [2003-02-22 12:55 UTC] php at codewhore dot org
I just pulled from the PHP_4_3 branch of CVS, and the problem is indeed fixed.

Thanks again. :)
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Dec 26 12:01:30 2024 UTC