Skip to content

ext/zip: add ZipArchive::openString method#21205

Open
tstarling wants to merge 7 commits intophp:masterfrom
tstarling:add-ziparchive-openbuffer
Open

ext/zip: add ZipArchive::openString method#21205
tstarling wants to merge 7 commits intophp:masterfrom
tstarling:add-ziparchive-openbuffer

Conversation

@tstarling
Copy link
Contributor

@tstarling tstarling commented Feb 12, 2026

  • Add ZipArchive::openString().
  • For consistency with ::open(), return int|bool, don't throw an exception on error. Provide error information via existing properties and accessors.
  • Share buffer handling with ZipArchive::addFromString().
  • If there is an error from zip_close() during a call to ZipArchive::open(), emit a warning but proceed to open the archive, don't return early. Add test.
  • When buffers are saved by ZipArchive::addFromString(), release them in ZipArchive::close() and ::open(), don't accumulate buffers until the free_obj handler is called.
  • Increase width of integers buffers_cnt and filename_len

Co-authored-by: @shyim
Forked from #14078

@iluuu1994
Copy link
Member

Just a heads-up: ext/zip doesn't currently have any active primary maintainers. I'm not sure who would be most qualified to review this. Maybe @devnexen or @ndossche? (Though note that @ndossche is a volunteer and busy with uni).

@tstarling
Copy link
Contributor Author

Just a heads-up: ext/zip doesn't currently have any active primary maintainers. I'm not sure who would be most qualified to review this. Maybe @devnexen or @ndossche? (Though note that @ndossche is a volunteer and busy with uni).

@ndossche is definitely the most qualified and it would be great to have his review. My work here carries on from his ZipArchive::addFromString() commit in November.

Regarding this commit and future directions: the read-only restriction is somewhat arbitrary -- we could provide an interface allowing a zip archive to be modified in memory, although I'm not sure exactly what that would look like. Maybe there would be a getter for the modified string. Then openString() could take a $flags argument, like open(). If we want to do that, $flags should be introduced here, since ZipArchive::open() defaults to read/write mode, and it would make sense for openString to do that too.

@tstarling
Copy link
Contributor Author

Since zip_close() does the writing, there's no point providing an accessor for the updated zip archive string before that is called. So maybe we could have ZipArchive::closeToString(), which closes the archive and returns it as a string.

We could then have a default for the first parameter of ZipArchive::openString to open an empty archive in read/write mode.

php_zipobj_add_buffer(ze_obj, buffer);
ze_obj->za = intern;
zip_error_fini(&err);
RETURN_TRUE;
Copy link
Member

Choose a reason for hiding this comment

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

Why not just return 0? Having a return type of int|true is incredibly weird.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

For consistency with ZipArchive::open. #14078 proposed to throw exceptions instead, but @remicollet complained that it was inconsistent with ZipArchive::open, so here I am proposing to make it consistent. ZipArchive::open has a couple of error cases which can return false, but they don't apply here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If you're prepared to take responsibility for this PR and hit the merge button when it meets your requirements, I'll make it return whatever you want.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

For forwards compatibility and consistency with ZipArchive::open, it would be better if the method was declared as returning int|bool, not int|true. Callers should check for a false return in case some future version returns false. But I don't care enough to delay the merge. Daniel asked for int|true, so it returns int|true.

Copy link
Member

Choose a reason for hiding this comment

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

If there is a reason to use int|bool, i.e. because you want to be able to return false in some future version, I have no objections - I just wanted to make sure that if there wasn't a reason to have bool in the type, that it would be narrowed, so that people wouldn't check for false values unnecessarily - future compatibility is a valid reason

Copy link
Contributor Author

Choose a reason for hiding this comment

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

OK, I changed it to bool|int.

shyim and others added 4 commits February 16, 2026 12:54
Signed-off-by: Soner Sayakci <s.sayakci@shopware.com>
Fixes to php#14078:

* Rename ZipArchive::openBuffer() to ::openString().
* For consistency with ::open(), return int|bool, don't throw an
  exception on error. Provide error information via existing properties
  and accessors.
* Fix memory leak when ::openString() is called but ::close() is not
  called. Add test.
* Fix memory leak when a call to ::open() is followed by a call to
  ::openString(). Add test.
* Let libzip own the source, don't call zip_source_keep().
* Share buffer handling with ZipArchive::addFromString().

Elsewhere:

* If there is an error from zip_close() during a call to
  ZipArchive::open(), emit a warning but proceed to open the archive,
  don't return early. Add test.
* When buffers are saved by ZipArchive::addFromString(), release them
  in ZipArchive::close() and ::open(), don't accumulate buffers until
  the free_obj handler is called.
* Factor out buffer handling and reuse it in ZipArchive::openString()
@tstarling tstarling force-pushed the add-ziparchive-openbuffer branch from efbdd09 to 1d8a567 Compare February 16, 2026 01:56
@ndossche ndossche self-requested a review February 24, 2026 20:04
@ndossche
Copy link
Member

Pushed on my todo stack for wednesday.

RETURN_THROWS();
}

ze_zip_object *ze_obj = Z_ZIP_P(self);
Copy link
Member

Choose a reason for hiding this comment

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

I'd use Z_ZIP_P(ZEND_THIS) instead of storing ZEND_THIS in a variable.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Every method in this class uses this pattern. I can clean it up in a separate PR if you like. Maybe it makes sense for performance if ZEND_THIS is accessed more than once, but the original author decided to be consistent about it regardless of how many times it's accessed.

@tstarling
Copy link
Contributor Author

Are there any remaining issues blocking the merge of this PR?

@ndossche
Copy link
Member

ndossche commented Mar 5, 2026

I'll have another look this weekend, I've just been busy with other things and not being super motivated to look after PHP.
You might want to shoot an email to internal in case this hasn't happened yet to see if there's any objections or concerns. If we had a maintainer for this extension then they could in principle decide on their own; but we don't have a dedicated person assigned for this.

@ndossche ndossche self-requested a review March 5, 2026 22:15
@tstarling
Copy link
Contributor Author

I sent an email to internals: https://www.mail-archive.com/internals@lists.php.net/msg122329.html

@remicollet
Copy link
Member

If we had a maintainer for this extension

I'm terribly sad to read this.
AFAIK I'm still in the CREDITS and EXTENSIONS files

For memory, most zip features were developed in https://github.com/pierrejoye/php_zip, especially keeping libzip and ext/zip in peace.
This repository was also designed to make downstream packaging easier (updating ext in sync with libzip, rather than with php)
Also remind this extension is one with its own version (not using PHP one)

But because of lack of respect for this work, I'm alone to take care of this. And I'm tired, exhausted...

@ndossche
Copy link
Member

ndossche commented Mar 6, 2026

If we had a maintainer for this extension

I'm terribly sad to read this. AFAIK I'm still in the CREDITS and EXTENSIONS files

(...)

But because of lack of respect for this work, I'm alone to take care of this. And I'm tired, exhausted...

This wasn't meant as a disrespect or anything like that. We recently talked internally how the EXTENSIONS file is terribly outdated and how it cannot be really used, some even suggesting dropping it. I see you're listed in there but only until 2020, so that's what I go off by. I think most of us mostly look at the CODEOWNERS file to determine active maintenance.
I know you maintain the external repository, and I do respect that.

@tstarling
Copy link
Contributor Author

For memory, most zip features were developed in https://github.com/pierrejoye/php_zip, especially keeping libzip and ext/zip in peace. This repository was also designed to make downstream packaging easier (updating ext in sync with libzip, rather than with php) Also remind this extension is one with its own version (not using PHP one)

I can make a PR against that repo instead, assuming you can push it back to php-src when it's merged. Although I admit I don't understand the technical rationale for it. I see you're updating the Fedora package as we speak. Wikimedia is a Debian shop, I haven't touched Fedora packaging since 2004, so I can't meaningfully comment on it.

@remicollet
Copy link
Member

remicollet commented Mar 6, 2026

Although I admit I don't understand the technical rationale for it

Such new feature will only be available to PHP version 8.6 with ext/zip users
But to all pecl/zip extension users, whatever PHP version

I can make a PR against that repo instead

Having review here is fine.
But PR in other repo welcome (after merge)

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.

9 participants