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]

Reply via email to