eclipse-archived / smarthome

Eclipse SmartHome™ project
https://www.eclipse.org/smarthome/
Eclipse Public License 2.0
862 stars 787 forks source link

Fixed possible NPE in FirmwareUpdateService #6859

Closed alex-kostadinov closed 5 years ago

alex-kostadinov commented 5 years ago

Basically, the method private synchronized void processFirmwareStatusInfo(FirmwareUpdateHandler firmwareUpdateHandler, FirmwareStatusInfo newFirmwareStatusInfo, @Nullable Firmware latestFirmware) performs the following operation:

FirmwareStatusInfo previousFirmwareStatusInfo = firmwareStatusInfoMap.put(newFirmwareStatusInfo.getThingUID(), newFirmwareStatusInfo);

However, since put(...) returns the previous value associated with key, during the first time we set the value for the exact thing UID previousFirmwareStatusInfo is effectively assigned null.

Further ahead,processFirmwareStatusInfo(...) calls private void transferLatestFirmware(final FirmwareUpdateBackgroundTransferHandler fubtHandler, final Firmware latestFirmware, final FirmwareStatusInfo previousFirmwareStatusInfo), inside which the following operation is performed:

firmwareStatusInfoMap.put(fubtHandler.getThing().getUID(), previousFirmwareStatusInfo);

This, in case previousFirmwareStatusInfo is null directly throws a NPE, since null values cannot go in a ConcurrentHashMap:

java.lang.NullPointerException
     at java.util.concurrent.ConcurrentHashMap.putVal(Unknown Source)
     at java.util.concurrent.ConcurrentHashMap.put(Unknown Source)
     at org.eclipse.smarthome.core.thing.internal.firmware.FirmwareUpdateServiceImpl$2.run(FirmwareUpdateServiceImpl.java:345)
     at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
     at java.util.concurrent.FutureTask.run(Unknown Source)
     at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(Unknown Source)
     at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(Unknown Source)
     at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
     at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
     at java.lang.Thread.run(Unknown Source)

In order to prevent this, a simple non-null check is added.