Repository navigation
Conversation
likemusic
force-pushed
the
soap-wsdl-exceptions
branch
from
October 15, 2026 20:58
be835f4 to
849350c
Compare
WSDL and XML schema errors were raised with soap_errorN(E_ERROR, ...). SoapClient turned the fatal error into a SoapFault and caught the bailout in SOAP_CLIENT_END_CODE(), but zend_bailout() had already called gc_protect(1), so the cycle collector stayed off for the rest of the request (phpGH-10026). The WSDL and schema loaders now throw the SoapFault with soap_throw_error() and return an error to their callers, which release what they own on the way out. The message and the fault code ("WSDL") are the same as before. SoapServer and SoapClient with the "exceptions" option disabled keep reporting these errors as fatal errors: the constructor turns the SoapFault back into the same E_ERROR once the loader has cleaned up. Since nothing bails out of the loaders any more, the error paths that existed only to survive a bailout are gone: the zend_try in load_wsdl_ex(), requestify_string() and the copies of targetNamespace in schema_load_file(). delete_type() now also frees an unresolved "ref", which an error before schema_pass2() can leave behind. Errors from encoding and decoding values still bail out and are not covered by this change. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
likemusic
force-pushed
the
soap-wsdl-exceptions
branch
from
October 15, 2026 21:57
849350c to
31ac172
Compare
Author
|
Encoding and decoding errors are in a follow-up on top of this one: #24367. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This is the direction suggested in the review of #24338: instead of a special bailout, the WSDL and XML schema loaders of ext/soap now report errors by throwing the
SoapFaultand returning, soSoapClientno longer goes throughzend_bailout()for them. That is the case reported in #10026: a broken WSDL leftgc_status()['protected']attruefor the rest of the request.What changes
soap_throw_error()throws the sameSoapFaultthat the error handler used to build fromsoap_errorN(E_ERROR, ...): sameSOAP-ERROR: ...message, same fault code (WSDL).soap_errorN()calls inphp_sdl.candphp_schema.cuse it now, and every function on the way up returns an error instead of relying on the bailout. Objects that are not yet owned by thesdlare freed where the error happens; everything else is freed bydelete_sdl().is_wsdl_element()returns-1after throwing for an unknown required extension, so callers can tell that apart from "not a WSDL element".SoapServerandSoapClientwithexceptions => falsekeep the current behaviour: after the loader has cleaned up, the constructor turns theSoapFaultback into the sameE_ERROR(soap_fault_to_error()), so the server still answers with a SOAP fault and the client still dies with the same fatal error.zend_tryaround WSDL imports inload_wsdl_ex(),requestify_string()and thetargetNamespacecopies inschema_load_file().delete_type()now frees an unresolvedref, which an error beforeschema_pass2()can leave behind.The diff of
load_wsdl()is mostly re-indentation after removing itszend_try; it reads better with whitespace changes hidden (?w=1).Encoding and decoding errors in
php_encoding.cstill bail out, so #10026 is not fully fixed by this PR alone: an encoding error in a call (for exampleSOAP-ERROR: Encoding: object has no 'x' property) still leavesprotectedattrue. I would do that in a follow-up in the same way, unless you prefer it in this PR.Testing
Debug build of master (
0b4a5a84492), unless noted otherwise. After rebasing ontode7ff46337f(no changes inext/soapin between),ext/soapwas run again: all tests pass.ext/soap: all tests pass.bugs/gh10026.phpt, andwsdl_errors_no_bailout.phpt, which goes through 48 broken WSDL/schema files, one per error path with its own cleanup. On a debug build any leak on those paths fails the test. Both tests fail on unpatched master, and only on the lines that check the GC state; the messages are the same.SoapClientwith exceptions,SoapClientwithexceptions => false, andSoapServer:SoapFaultmessage and fault code are identical in all 218 cases;protectedistrueafter 216 of them on unpatched master and after none of them with the patch; no leaks, no assertions;exceptions => falseandSoapServer: output is byte-for-byte identical before and after (216 fatal errors / SOAP faults, 2 valid WSDLs);Couldn't load from '%s'without a libxml error,Missing 'name' attribute for <binding>(a binding without a name is rejected earlier, inload_wsdl_ex()), and the secondunexpected <%s> in union(after a loop that only ends withtrav == NULL).USE_ZEND_ALLOC=0: the 218-file corpus in all three modes gives no ASAN or UBSAN report (leak detection off, since the fatal-error modes end the request without freeing; leaks are covered by the debug build above).run-tests --asanonext/soap: both new tests pass; 6 other tests fail with LeakSanitizer reports (bug37013,bug55323,gh16318,gh22585,r3_groupE_list_005w,r3_groupE_list_006w), and they fail the same way without this patch.🤖 Generated with Claude Code