ppkarwasz opened a new pull request, #45:
URL: https://github.com/apache/commons-xml/pull/45

   Recognizes Saxon factories by package prefix instead of an exact class-name 
set, addressing finding f008.
   
   ## Problem
   
   `TransformerHardener` and `XPathHardener` route a factory to `SaxonProvider` 
(the only recipe that installs Saxon's locked-down `Configuration`) by matching 
its class name against a fixed set of three names. Saxon-HE ships a second 
public `TransformerFactory`, `net.sf.saxon.BasicTransformerFactory` (a subclass 
of the registered `net.sf.saxon.TransformerFactoryImpl`), selectable through 
the standard `javax.xml.transform.TransformerFactory` system property. It is 
not in the set, so it falls to the generic branch. That branch wraps the 
factory (FSP, the URIResolver floor, the Source rewrite) and looks successful, 
but never installs the empty `CollectionFinder`, so `fn:collection` fetches 
directly and stays open.
   
   ## Changes
   
   - `SaxonProvider` gains a package-private `isSaxon(Class<?>)` that matches 
the `net.sf.saxon.` and `com.saxonica.` package prefixes. The outer class 
references no Saxon types (they live in the inner configurer), so it still 
loads without Saxon on the classpath.
   - `TransformerHardener` and `XPathHardener` drop their exact-name sets and 
call `SaxonProvider.isSaxon(...)`; javadoc updated from "recognized by class 
name" to "recognized by package prefix", noting that subclasses such as 
`BasicTransformerFactory` now route to the same recipe.
   - `SaxonProvider.configure(...)` now catches the cast `ClassCastException` 
and rethrows it as a `HardeningException` naming the factory class: with prefix 
matching, a hypothetical Saxon-package factory that is not castable to 
`SaxonTransformerFactory`/`XPathFactoryImpl` fails closed with a message rather 
than a bare `ClassCastException` (the exact-name set previously made the cast 
infallible).
   
   ## Tests
   
   New `SaxonAlternateFactoryTest` (`@Tag("trax")`, reflective load of 
`BasicTransformerFactory`, skipped when Saxon is absent, so effective on 
test-saxon and test-saxon-xerces):
   
   - `hardenedBasicFactoryDoesNotLeakCollection`: routes a 
`BasicTransformerFactory` through `TransformerHardener.harden(...)` and runs a 
stylesheet whose `collection()` would pull `LEAKED_MARKER` into the output; 
blocks-or-does-not-leak.
   - `unconfiguredBasicFactoryLeaksCollection`: the bare factory resolves it 
(leak control).
   
   `collection()` is the deliberately chosen channel: it bypasses Saxon's 
resource-resolution chain, so only the empty `CollectionFinder` in 
`SaxonProvider` closes it. Verified by probe on the pinned Saxon-HE 13.0 that 
`collection()` leaks through both the bare factory and the generic 
`HardeningTransformerFactory` branch but returns empty through 
`SaxonProvider.configure`. Discrimination confirmed: with the exact-name 
recognition temporarily restored, the hardened test fails on both Saxon 
executions while the leak control passes. (The report's suggested 
`unparsed-text()` probe does not discriminate on Saxon 13, since the generic 
branch's URIResolver floor already covers that channel; `collection()` is the 
one it does not.)
   
   Full `mvn clean` and plain `mvn` (checkstyle, spotbugs, pmd, javadoc, whole 
surefire matrix) green, plus a post-build non-vacuous `spotbugs:check`.
   
   ## Note
   
   `TransformerHardener` is also rewritten by open PR #41 (Saxon wrapped like 
every other implementation) and `XPathHardener` by open PR #44; whichever lands 
later reconciles small conflicts, and the `SaxonProvider.isSaxon` prefix 
recognition should be carried into #41's routing.
   
   🤖 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