Баг що призвів до зависання Zune 30

Zune 30 – перше покоління MP3-плеєрів від Microsoft. Випускалися пристрої з 2006 року, а у 2011 випуск усієї лінійки припинився. Усього було 4 покоління: 1) Zune 30, 2) Zune 4, 8, 80, 3) Zune 16, 120, 4) Zune HD.

Баг про який йде мова був лише в коді Zune 30.

Сам код:

year = ORIGINYEAR; /* = 1980 */

while (days > 365)
{
    if (IsLeapYear(year))
    {
        if (days > 366)
        {
            days -= 366;
            year += 1;
        }
    }
    else
    {
        days -= 365;
        year += 1;
    }
}

Цей код як бачите вираховує рік на основі лічильника днів (лічильник починається з 1/1/1980).

Тепер слідкуємо за руками.

Уявимо що у нас останній день 2008-го року:

  1. У рядку 3 код перевіряє кількість днів, умова виконується (366 > 365)
  2. У рядку 5 функція IsLeapYear() повертає true бо 2008 високосний рік
  3. Умова у рядку 7 не виконується (366 > 366)
  4. Переходимо до рядка 3

Ну от ми і в нескінченному циклі!

Таким чином усі пристрої у першу секунду 2009-го року перетворилися на тикви, тобто перестали реагувати на будь-що.

Справедливості заради треба сказати що це був код не Microsoft, а Freescale – драйвер для їхнього годинника. Були і інші пристрої що зловили точно таку ж проблему, наприклад медіа-плеєр від Toshiba. Інші моделі Zune мали інший чіп і там цієї проблеми не виникло.

Офіційно рекомендованим способом вирішити проблему було розрядити остаточно батарею і поставити пристрій на зарядку (таким чином 1 січня 2009-го було б 367-мим днем якщо рахувати від 1/1/2008).