ppkarwasz opened a new pull request, #73: URL: https://github.com/apache/commons-secure-xml/pull/73
A schema loader expands a repeated particle into content-model nodes while building the DFA. That happens after parsing and without the reader, so none of the limits the injected secure reader carries can reach it — entity expansion is bounded there (`BillionLaughsTest`), content-model expansion is not. The bound for it is the implementation's own secure-processing limit, and it is opt-in on external Xerces: `maxOccurLimit` is installed only when `FEATURE_SECURE_PROCESSING` is set on the `SchemaFactory`, which the wrapper deliberately did not set. The stock JDK applies its limit unconditionally and was never affected. Measured on external Xerces through `SecureSchemaFactory` with a 512 MB heap, before this change: `maxOccurs="10000"` validated in 13.7 s, `maxOccurs="100000"` ended in `OutOfMemoryError`. Both are rejected once the feature is set. The fix sets `FEATURE_SECURE_PROCESSING` on the wrapped factory, failing closed through the same helper shape the other recipes use. The JAXP 1.5 `ACCESS_EXTERNAL_*` properties are still not set explicitly, so the caller-resolver opt-in path the wrapper's Javadoc protects is untouched: `schemaFetchesIdentifierOnlyOptIn` (an identifier-only `LSInput`, the case where the implementation must fetch the named resource itself) and `schemaResolvesAllowListed` pass on every schema execution, on Java 8 as well as the default JDK. One behavioural note for reviewers: because the set fails closed, a `SchemaFactory` implementation that rejects `FEATURE_SECURE_PROCESSING` now throws instead of returning an unsecured factory. That matches the documented contract for a required setting, but it is a change for implementations outside the recognized set. The new `SchemaContentModelLimitTest` validates an instance rather than only compiling the schema, because the expansion is lazy on Xerces — `newSchema` returns in milliseconds whatever `maxOccurs` says. Its unbounded control skips where the implementation applies the limit unconditionally, since there is no unbounded run to compare against. Verified with the full surefire matrix on the default JDK and on Java 8. 🤖 Generated with [Claude Code](https://claude.com/claude-code) -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
