My (TCP) Smack client disconnects on certain incoming invalid messages. This happens even if a relaxed ParsingExceptionCallback is configured. This disconnected client causes an unwanted (temporary) service disruption.
Example: A message containing an invalid XForm like
<x xmlns="jabber:x:data">
<field/>
</a>
makes DataFormProvider#parseField to raise a NullPointerException because the logic expects the fieldName (var) not to be null.
This isn’t properly handled by AbstractXMPPConnection#parseAndProcessStanza via ParsingExceptionCallback because the NullPointerException isn’t caught here. The connection gets closed instead.
I assume that this can be easily solved by catching the generic java.lang.Exception rather than XmlPullParserException | SmackParsingException | IOException | IllegalArgumentException inside #parseAndProcessStanza.
This would add more overall robustness to a Smack client because there might be other kind of exceptions lurking in the ExtensionElement implementations.
May I create a PR for applying my proposal?
Greetings Peter
BTW: Thank you very much for your great work on Smack and Openfire!
I’m not sure if catching additional (runtime) exceptions is a good or bad thing. The benefit that you describe may not outweigh the benefit of this identifying bugs in code. I’ll leave it up to @Flow to determine if additional exceptions should be caught.
In this example, I would consider DataFormProcessor#parseField to not throw a SmackParsingException to be a bug.
If you do want to make a contribution, then one that fixes DataFormProcessor would be a very welcome one! I suggest to make use of ParserUtils#getRequiredAttribute (and friends) to make that implementation more robust!
Sure, adjusting the DataForm parser so that it handles such situation more graceful would be definitely a good thing.
Anyway, I’m aiming a solution that is even more robust against bugs inside the ExtensionElement handlers that have not been found yet but which would cause the same situation that the connection is closed. Malicious persons might use this for disrupting services.
When looking at parseAndProcessStanza I can’t imagine that there would be any kind of Exception in this context that would be worth not being caught and not being handled by the ParsingExceptionCallback. It may be even decided inside this ParsingExceptionCallback to re-throw the exception and terminate the connection.
java.lang.NullPointerException: Cannot invoke "String.equals(Object)" because "fieldName" is null
at org.jivesoftware.smackx.xdata.provider.DataFormProvider.parseField(DataFormProvider.java:243)
at org.jivesoftware.smackx.xdata.provider.DataFormProvider.parseField(DataFormProvider.java:144)
at org.jivesoftware.smackx.xdata.provider.DataFormProvider.parse(DataFormProvider.java:92)
at org.jivesoftware.smackx.xdata.provider.DataFormProvider.parse(DataFormProvider.java:61)
at org.jivesoftware.smack.provider.Provider.parse(Provider.java:53)
at org.jivesoftware.smack.util.PacketParserUtils.parseExtensionElement(PacketParserUtils.java:841)
at org.jivesoftware.smack.util.PacketParserUtils.parseMessage(PacketParserUtils.java:186)
at org.jivesoftware.smack.util.PacketParserUtils.parseStanza(PacketParserUtils.java:111)
at org.jivesoftware.smack.AbstractXMPPConnection.parseAndProcessStanza(AbstractXMPPConnection.java:1449)
at org.jivesoftware.smack.tcp.XMPPTCPConnection.access$1000(XMPPTCPConnection.java:131)
at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader.parsePackets(XMPPTCPConnection.java:972)
at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader.access$700(XMPPTCPConnection.java:916)
at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader$1.run(XMPPTCPConnection.java:939)
at java.base/java.lang.Thread.run(Thread.java:1589)
I’d like to avoid catch Exception when possible. But you are right that a faulty parser implementation should not open a DoS vector. Therefore I made the handling more robust with
I also fixed the original issue in the data form provider