Skip to content

Fix stream double free in phar #19035

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: PHP-8.3
Choose a base branch
from
Open

Conversation

nielsdos
Copy link
Member

@nielsdos nielsdos commented Jul 5, 2025

The copy function does two things wrong:

  • The error recovery logic is a hack that temporarily moves the fp
    pointer to cfp, even though it's not compressed. The respective error
    recovery it talks about is not present in the code, nor is it
    necessary. This is the direct cause of the double free in the original
    reproducer. Fixing this makes it crash in another location though.
  • The link following logic is inconsistent and illogical. It cannot be a
    link at this point.

The root cause, after fixing the above issues, is that the file pointers
are not reset properly for the copy. The file pointer need to be the
original ones to perform the copy from the right source, but after that
they need to be set properly to NULL (because fp_type == PHAR_FP).

Replaces GH-18953.
Will squash on merge.

The copy function does two things wrong:
- The error recovery logic is a hack that temporarily moves the fp
  pointer to cfp, even though it's not compressed. The respective error
  recovery it talks about is not present in the code, nor is it
  necessary. This is the direct cause of the double free in the original
  reproducer. Fixing this makes it crash in another location though.
- The link following logic is inconsistent and illogical. It cannot be a
  link at this point.

The root cause, after fixing the above issues, is that the file pointers
are not reset properly for the copy. The file pointer need to be the
original ones to perform the copy from the right source, but after that
they need to be set properly to NULL (because fp_type == PHAR_FP).
@nielsdos nielsdos marked this pull request as ready for review July 5, 2025 07:44
nielsdos added a commit to nielsdos/php-src that referenced this pull request Jul 5, 2025
There are two bugfixes here.
The first was a crash that I discovered while working on phpGH-19035.
The check for when a file pointer was still occupied was wrong, leading
to a UAF. Strangely, zip got this right.

The second issue was that even after fixing the first one, the file
contents were garbage. This is because the file write offset for the
phar stream was wrong.
Copy link
Member

@Girgias Girgias left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks reasonable

@@ -1941,26 +1942,14 @@ static int phar_copy_file_contents(phar_entry_info *entry, php_stream *fp) /* {{
}

/* copy old contents in entirety */
phar_seek_efp(entry, 0, SEEK_SET, 0, 1);
phar_seek_efp(entry, 0, SEEK_SET, 0, 0);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Follow-up: phar_seek_efp() should have its type changed from int to bool

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants