Fichier créé le 29 janvier 1999.

Un Sun 3 est arrivé sur mon bureau le 4 Janvier 1988, et il a aussitôt manifesté le bug que j'ai localisé et corrigé dans la soirée, pour autant que je me souvienne, car les fichiers que je garde de cette époque eux sont datés du 7 Janvier, sans doute suite à une recopie. Tout était prévu pour traiter le cas des années bissextiles, mais il y avait un bug dans le code. En cette circonstance Sun a été victime de l'anthropomorphisme des fabricants de chips. Leur système, comme tous les Unix, utilisait des dates en secondes depuis 1970 et les traditionnelles fonctions de conversion en notations humaine asctime, ctime et localtime qui tenaient parfaitement compte des années bissextiles ainsi que des fuseaux horaires et des heures d'été (américaines seulement à cette epoque).

Leur problème est venu de ce que pour conserver l'heure pendant que la machine est hors tension, ils utilisaient un chip du commerce avec une pile incorporée qui lui comptait en heures, minutes, secondes, mois, jours, année. Il leur fallait donc dans le noyau du système d'exploitation une fonction de conversion pour mettre à jour le chip chaque fois qu'on change l'heure de la machine. Ils en ont donc réécrit une, dans laquelle ils ont mis un superbe bug, une vieille erreur classique d'effet de bord sur une macro dans le langage de programmation C. Pour leur conversion, ils avaient besoin de savoir combien de secondes il y a dans chaque mois. C'est facile d'obtenir ça par consultation d'une table initialisée, qu'ils avaient appelée monthsec[], mais il y a le problème de février en années bissextiles, d'où la macro MONTHSEC, qui dit que ce qu'on veut c'est ce que donne la table sauf si l'année est bissextile et le mois février, cas auquel c'est 29*24*3600 :

#define MONTHSEC(mon, year) ((year%4 == 0) && mon == 2) ? \
                (29*24*60*60) : monthsec[mon-1]
jusque là tout va bien.

Là où ça bugge, c'est à la sortie d'une boucle où il est écrit:

        t += MONTHSEC(--mon, year);

Il se produit alors un effet de bord dans la macro MONTHSEC, dû à la décrémentation de mon dans les arguments de la macro, (--mon), et comme mon figure 2 fois dans cette macro il y est décrémenté 2 fois ... non pas toujours, parce que la première occurrence de mon, la comparaison ((mon) == 2) n'est évaluée que si l'année est bissextile, donc le code avait donné l'illusion d'être correct jusque-là. À noter qu'il aurait à nouveau donné cette illusion durant le mois de février de cette même année, car dans ce cas c'est la deuxième occurence de mon qui n'est pas évaluée !

À noter que personne ne se serait jamais aperçu de rien tant qu'on n'essayait pas de mettre la machine à l'heure. Mais il se trouve qu'on tournait à cette epoque à l'INRIA et dans beaucoup d'autres endroits un protocole de synchronisation entre machines qui n'arrêtait pas de les mettre à l'heure, de pas grand chose d'ailleurs, mais avec le bug ça suffisait pour faire faire n'importe quoi à leur heure.