Fix NPE in Roster's presence listeners if 'from' is not set

The NPE is caused by an inbound presence stanza without the 'from'
attribute set. The stacktrace of the NPE is:

FATAL EXCEPTION: Smack Cached Executor
Process: de.fhg.ivi.senetz.mobile.android.mbk.debug, PID: 13365
java.lang.NullPointerException: Attempt to invoke virtual method 'int java.lang.Object.hashCode()' on a null object reference
    at java.util.concurrent.ConcurrentHashMap.get(ConcurrentHashMap.java:944)
    at org.jivesoftware.smack.roster.Roster.getPresencesInternal(Roster.java:374)
    at org.jivesoftware.smack.roster.Roster.getOrCreatePresencesInternal(Roster.java:388)
    at org.jivesoftware.smack.roster.Roster.access$1100(Roster.java:94)
    at org.jivesoftware.smack.roster.Roster$PresencePacketListener$1.run(Roster.java:1519)
    at org.jivesoftware.smack.AsyncButOrdered$Handler.run(AsyncButOrdered.java:121)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)
    at java.lang.Thread.run(Thread.java:764)

Thanks to Marcel Heckel for reporting this.

Fixes SMACK-861.
This commit is contained in:
Florian Schmaus 2019-04-01 22:02:36 +02:00
parent 25b3f35421
commit 9be498c440
1 changed files with 23 additions and 1 deletions

View File

@ -1471,7 +1471,29 @@ public final class Roster extends Manager {
final Presence presence = (Presence) packet;
final Jid from = presence.getFrom();
final BareJid key = from != null ? from.asBareJid() : null;
final BareJid key;
if (from != null) {
key = from.asBareJid();
} else {
XMPPConnection connection = connection();
if (connection == null) {
LOGGER.finest("Connection was null while trying to handle exotic presence stanza: " + presence);
return;
}
// Assume the presence come "from the users account on the server" since no from was set (RFC 6120 §
// 8.1.2.1 4.). Note that getUser() may return null, but should never return null in this case as where
// connected.
EntityFullJid myJid = connection.getUser();
if (myJid == null) {
LOGGER.info(
"Connection had no local address in Roster's presence listener."
+ " Possibly we received a presence without from before being authenticated."
+ " Presence: " + presence);
return;
}
LOGGER.info("Exotic presence stanza without from received: " + presence);
key = myJid.asBareJid();
}
asyncButOrdered.performAsyncButOrdered(key, new Runnable() {
@Override