[ 
https://issues.apache.org/jira/browse/WSCOMMONS-372?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Andreas Veithen updated WSCOMMONS-372:
--------------------------------------

         Priority: Critical  (was: Minor)
    Fix Version/s: Axiom 1.2.8

The explanation for this issue is as follows:
* OMElementImpl#internalSerialize uses an OMChildrenIterator to iterator over 
its own children.
* OMChildrenIterator actually swallows any exception thrown by the 
StAXOMBuilder, and therefore by the underlying StAX parser. In this case it is 
the exception indicating the premature end of stream that is swallowed.
* Since OMElementImpl#internalSerialize doesn't exit at this point, it will end 
up calling StAXOMBuilder again, which will request new events from the StAX 
parser.
* One would expect that a call to next() on an XMLStreamReader that has already 
thrown an exception before would fail again (especially when the underlying 
input stream is closed). However when Woodstox is used, this is not the case, 
at least not in the example shown here.

There are therefore three issues that contribute to the problem described here:
1. OMChildrenIterator swallows exceptions.
2. Axiom may call next() on an XMLStreamReader that has already thrown an 
exception before.
3. After throwing an exception, the Woodstox parser is left in an inconsistent 
state (at least for the end of stream case).

These three factors can lead to an infinite recursion which eventually causes 
an OutOfMemoryError. When I opened this issue, I considered it more as a 
problem in error reporting in Axiom. However, it is more serious than I 
initially thought, because the same situation could occur in any piece of code 
using OMChildrenIterator, if the XML being parsed is invalid or when an I/O 
error occurs. This could either be unintentional (e.g. network error) or 
intentional (i.e. this flaw could potentially be used to carry out a denial of 
service attack against software built using Axiom).

To solve this issue I would suggest the following changes:
1. Let OMChildrenIterator#next() throw OMExceptions (again).
2. Add a flag to StAXOMBuilder that is set when an exception is thrown by the 
StAX parser and prevent it from calling the parser again once this flag is set.

Note that the current behavior of OMChildrenIterator#next() was implemented as 
part of WSCOMMONS-91 and AXIS2-919. The rationale was that

[quote] According to the Sun documentation for the java.util.Iterator 
interface, the following loop:

    while (iterator.hasNext())
         iterator.next();

should not throw any exceptions at all, ever, unless there is a bug in the 
program. [/quote]

and that therefore the previous implementation (which threw OMExceptions) would 
violate the java.util.Iterator contract. However I was unable to find any 
documentation or specification that explicitly forbids implementations of 
Iterator#next() to throw unchecked exceptions (other than 
NoSuchElementException and ConcurrentModificationException). I believe that the 
above statement is primarily based on a very orthodox interpretation of the 
Java API, namely that unchecked exceptions should only be used to indicate 
programming bugs. It should be noted that Axiom itself doesn't follow that 
paradigm, OMException being a runtime exception.

Also I believe that the risk of breaking existing code by changing the behavior 
of OMChildrenIterator#next() is negligibly small. The reason is that if the 
code uses OMChildrenIterator, then it will almost certainly use other methods 
of the Axiom API which can throw OMExceptions, and the code must therefore be 
prepared for this type of exceptions anyway. One could argue (and that was one 
of the arguments in AXIS2-919) that the OMChildrenIterator could also be used 
by code that "may not be aware that the Iterator that they have been handed is 
actually an Iterator from OMElement". However, whatever such code may do with 
an OMException thrown by next() could not be worse than the current behavior of 
the next() method, i.e. to discard the exception completely.

Therefore I currently don't see any valid reason not to change the behavior of 
OMChildrenIterator#next().

> Sometimes accessing an AXIOM tree while the underlying input stream is closed 
> causes an OutOfMemoryError
> --------------------------------------------------------------------------------------------------------
>
>                 Key: WSCOMMONS-372
>                 URL: https://issues.apache.org/jira/browse/WSCOMMONS-372
>             Project: WS-Commons
>          Issue Type: Bug
>          Components: AXIOM
>         Environment: Mac OS X
> java version "1.5.0_13"
> AXIOM revision 686026
>            Reporter: Andreas Veithen
>            Priority: Critical
>             Fix For: Axiom 1.2.8
>
>         Attachments: Test.java
>
>
> Under some circumstances, accessing an AXIOM tree while the underlying input 
> stream is closed doesn't throw a proper exception but causes an 
> OutOfMemoryError. The attached Java code provides an example of this behavior.

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.

Reply via email to