Array out of bounds error in a data field can cause endless reboot loop
o The Environment:
Windows 10
Eclipse Oxygen (4.7.0)
Connect IQ 2.3.1
FR230 FW 7.10
o A detailed description of the issue
Under certain circumstances, an array out of bounds error in a data field can cause an endless reboot loop, which is impossible to get out of without resetting to factory (clearing user data). The key is to get the app installed in an activity without crashing. Once it's installed, if you can make it crash (e.g. on init), the device will reboot forever.
Tangentially, it seems like an array out of bounds error should be a normal exception. Or at the very least, the entire watch shouldn't reboot.
o Steps to reproduce the issue
- Create a new simple data field project.
- Build the Harmless Version of the code below and sideload it to an FR230 whose data you don't care about.
- Assign the data field to your running app. Exit the app to make sure everything is saved to flash.
- Build the Bad Version of the code below and sideload it to the FR230, replacing the Harmless Version. The bad version should have the same ID as the good version.
- When you disconnect the USB cable, the 230 will reboot endlessly, without giving the user a chance to do anything. I guess the running app is reinitialized when the USB cable is disconnected, as well as with each subsequent reboot.
At this point you have two options:
1) Hold down Light for 15 seconds to shut off the watch. When you turn it back on, it will start to reboot endlessly again
2) Clear user data. If you're very lucky, you can hold down Lap and use the normal UI to clear the user data before the device reboots.
If unlucky, you have to use Garmin's version of the "3-finger salute":
2a) Turn off device (hold Light for 15 seconds)
2b) Hold down Power, Run, and Lap.
2c) When the device turns on, let go of Power
2d) When the device beeps once, let go of Run
2e) When the device beeps again, let go of Lap.
(Or you can just hold down Power, Run and Lap while the device is endlessly rebooting, and skip to 2d)
The following possibly equivalent real-world scenario comes to mind, which doesn't even involve having more than one version of the app:
- Suppose a data field app has a dormant array out of bounds bug that is triggered by a certain condition, such as bad config which is not validated properly
- User installs data field with no problems
- One day the user accidentally sets the bad config which will likely cause the watch to reboot forever
- Now they probably have to lose all their data in order to recover. And they probably don't know the 3-finger salute.
o Any applicable additional information
None.
o A code sample that can reproduce the issue
Please replace <[ and ]> with parens in the following code.
Harmless Version
using Toybox.WatchUi as Ui;
class endlessRebootView extends Ui.SimpleDataField {
var x = [];
function initialize<[]> {
SimpleDataField.initialize<[]>;
label = "All good";
//var y = x[0];
}
function compute<[info]> {
return 0.0;
}
}
Bad Version
using Toybox.WatchUi as Ui;
class endlessRebootView extends Ui.SimpleDataField {
var x = [];
function initialize<[]> {
SimpleDataField.initialize<[]>;
label = "Reboot now";
var y = x[0];
}
function compute<[info]> {
return 0.0;
}
}