Bug de l'an 2038

a marqué ce sujet comme résolu.

Bonsoir à tous ! :)

Je viens de tomber tout à fait par hasard sur une page Wikipedia, traitant du bug de l’an 2038.

Je vous laisse le lien : https://fr.wikipedia.org/wiki/Bug_de_l%27an_2038

Que pensez-vous de ce bug ? Est-ce possible ? Ou alors c’est une blague ?

Si c’est vrai, quelles pourraient être les conséquences ? :p

+0 -0

Ce bug existe et est problematique. Pour le coup ici on fait en sorte de baisser l’expiration de certificats en dessous de 2038 pour le moment.

1
gnutls_x509_crt_set_expiration_time(cert, now + (10 * 365 * 24 * 60 * 60)); // 10 years

Pour savoir plus sur les consequences possibles cherche integer overflow et tu auras des tonnes d’exemples. Pour les certificats dans mon exemple, c’est d’utiliser des certificats consideres comme expire, mais des dates invalides ca peut avoir des tonnes de consequences.

De mémoire, il existe des mécanismes pour contourner ce bug en 32 bits (les dates sont sur 2 octets, c’est-à-dire en 64 bits, ou un truc comme ça), d’ors et déjà implémenté dans le noyau linux, par exemple. C’est en particulier utile pour ARM, dont la version 32 bits devrait arriver prochainement, mais n’est pas encore sur le marché, ou pour des architectures exotiques (x32). Si je ne me trompes pas, ce n’est plus tout à fait mon domaine de compétence.

+0 -0

Mais est-ce un errement?

Sérieusement, énormément de vieux matériel n’avait tout simplement pas les moyens de gérer des listes de temps sur 64 bits.

Aujourd’hui, on peut. Si on y ajoute les lib de gestion de date bien plus complète (avec les fuseaux, avec l’internationalisation…) on peut se permettre d’être encore plus souple.

Plusieurs choses :

  • Ca va sûrement générer quelques pages de discussion. Ca peut avoir lieu ici ou dans un autre topic.

  • Je pousse un peu le trait et je sais bien que beaucoup de choix anciens étaient dictés par des contraintes techniques de l’époque. Cependant, ce que je considère comme un errement est de n’avoir jamais remis en cause / corrigé ces problèmes à partir du moment où on a pu.

Exemples en vrac:

  • le C. Révolution bienvenue à sa création, on aurait du le dépasser depuis. Mais on se farcit toujours des bases de code en C et les problèmes qui vont avec pour encore de nombreuses années....
  • La concurrence au sein d’un programme basé sur des threads manipulés explicitement. Bien que bordélique et sujet à erreur, ca reste le modèle prédominant.
  • la croissance organique des architectures x861: la rétro compatibilité avec l’ajout de fonctionnalités à fait des architectures actuelles des monstres de complexité. Je me demande sincèrement si on pourrait arriver aux mêmes performance avec une architecture pensée depuis 0 (true question).
  • Je suis sûr qu’on peut en trouver encore beaucoup d’autres…


  1. moins sûr de moi sur ce point là.  

+1 -0

Je pense que tu confonds deux choses :

  • des technos qui ont mal vieillies par rapport àc e qu’on sait faire aujourd’hui (exemple l’asynchrone à la JS ou à la go)
  • des choix douteux, même pour leur époque.

Savoir gérer des temps, de l’asynchrone, du thread, à l’époque des processeur monocoeur 16 voire 32bits, avec une mémoire limité, du swap à gogo, et des OS pas toujours au top, c’est pas la même chose que faire la même chose avec le matos, les os et les algorithmes d’aujourd’hui. L’informatique est une science jeune, c’est assez logique qu’on ait fait des découvertes "disruptives" en terme d’informatique théorique voire d’ingénieurie que récemment.

Le défi d’aujourd’hui c’est la disponibilité et la traçabilité. Et les logiciels qui tiennent ça à peu près bien n’ont pas plus de 5 ans.

Je pense que la distinction que tu fais importe peu, voire pas du tout. Les choix et design sont ce qu’ils sont, quelle qu’en soit la raison. La question étant comment se débarrasser de la dette technique qu’ils nous imposent. Et de ce que je vois, y’a pas de plan.

Le défi d’aujourd’hui c’est la disponibilité et la traçabilité.

Tu peux détailler un tout petit plus ? Je ne suis pas sûr de bien comprendre.

+1 -0

disponibilité :

ton service doit être disponible, tout le temps, partout et quel que soit la charge. C’est la principale raison pour laquelle tout le monde n’arrive pas à faire son twitter alors que le modèle de données de twitter semble simple a première vue.

traçabilité :

par quelle étape tu passes pour rendre ton service, s’assurer que chaque étape/microservice est disponible et efficace, et lorsqu’une erreur apparaît savoir où elle est apparu.

C’est la raison pour laquelle tout le monde n’est pas netflix : détecter une panne, la réparer et éviter qu’elle ne revienne dans une infrastucture aussi large et stressée que celle de netflix est un enfer.

C’est très web, ça. Dans d’autres domaines, les contraintes n’ont rien à voir. En industrie lourde, un gros problème actuel, c’est la rétrocompatibilité. Une gamme d’avion a une durée de vie de 60 ans en gros, ça veut dire que l’ensemble de la liasse numérique doit être lisible 60 ans après la première vente. Soit tu maintiens le logiciel pendant 60 ans et les machines qui vont avec, soit tu mets à jour le logiciel sur des architectures récentes, soit tu t’assures que toutes les données sont compatibles d’une version à l’autre. Les couts de migration pour une entreprise comme Dassault sont gigantesques (quelle que soit la solution choisie, et pire encore si on n’a pas fait gaffe).

Tous mauvais design de l’époque se pait aujourd’hui. Et cher. Tous mauvais design d’aujourd’hui se paiera demain. Et la facture sera salée. Cela continuera tant que les questions de durée de vie à long terme ne seront pas pris en compte correctement.

Je suis bien évidemment conscient que mon exemple est complètement différent de ta pratique, mais c’est un cas tout aussi réel que les tiens ; cette diversité des contraintes n’aide probablement pas à la réalisation d’un bon design globale.

+5 -0

C’est très web, ça.

oui et… non.

je travaille dans le mail, on utilise de l’intelligence artificielle, chaque modèle doit pouvoir être exposé sous forme micro service, le plus souvent REST mais parfois c’est du pur protocol milter (un truc de postfix entre autre).

La disponibilité des MX et des modèles est hyper importante. Savoir ce qui nous a fait rendre tel ou tel verdict est hyper important, de même que tracer les cas d’erreur.

Tous mauvais design de l’époque se pait aujourd’hui. Et cher

mais la question reste pertinente : étaient-ce des mauvais design… à l’époque?

Non parce que regarder avec nos technologie actuelles, nos connaissances actuels et nos moyens actuels en terme de connectique, de capteur, de modèle de communication, et dire "ah bah là c’est de la merde" c’est comme pester sur les programmes banquaires écrits en cobol quoi.

C’est pas que les développeurs qui ont fait du cobole ont fait des mauvais choix, c’est qu’aujourd’hui on doit payer plus cher ce choix qu’à l’époque.

Alors, oui, mes exemples sont web, mais globalement disponibilité et traçabilité c’est présent partout, je dirais même que l’autodiagnostique des équipements électroniques (industriels ou de voiture pour ce que j’ai pu apercevoir, je connais pas assez pour les avions) c’est le jour et la nuit par rapport à avant et on se rend bien compte que c’est pas encore assez. Les voitures qui tombent en panne sèche car personne nn’est capable de voir que le capteur de pression moteur envoie des mauvaises info et que du coup la jauge d’essence "autocorrige" sa mesure à la hausse même quand il n’y a plus d’essence justement (cas réel vécu) ça montre bien que trouver des algo et infra de traçabilité c’est encore un défi.

Maintenant, c’est vrai que je n’avais pas pensé à l’interopérabilité car cette dernière est assez développée dans le monde logiciel via des standard assez largement implémentés avec respect.

mais la question reste pertinente : étaient-ce des mauvais design… à l’époque?

Je n’ai pas forcément tous les détails (je ne bosse pas là-bas), mais le logiciel de l’époque ne tourne que sur des machines de calcul IBM de l’époque. Donc ils font durer autant que faire se peut ces machines. C’était probablement logique de privilégier ces machines à l’époque, mais se restreindre à celle-ci, étant donné la durée de vie, il commence à y avoir un problème (penser que le constructeur va continuer à commercialiser des machines compatibles pendant 50 ans, sans lui faire signer un contrat l’obligeant, c’est… optimiste). Ensuite, que la version N lise en gros 95 % des données de la version N-1, c’est un choix de l’époque (pas si vieux que ça, quelques années seulement) qui se paye très cher aujourd’hui. C’est beaucoup, 5 % d’un avion.

En vrai, le problème est la somme des deux : soit ton logiciel tourne sur des architectures variées, et tu peux toujours t’en servir au besoin, soit tu veux t’en débarrasser à terme, mais la compatibilité doit être excellente.

Peut-être que sur une partie, ils ont fait au mieux à l’époque, mais ils ont aussi fait le choix de limiter les dépenses (mono-architecture, rétro-compatiblité partielle…). Tout du moins, ils n’ont pas pensé à long terme. Le nouveau client est disponible uniquement sur Windows, mais 7 à 10 ; en espérant qu’ils gèrent mieux leur transition d’une version à l’autre.

+1 -0

Je trouve qu’il y a une assez grande confusion autour de ce bogue, son origine, si c’est normal ou pas et ses conséquences aujourd’hui ou demain.

Reprocher qu’à l’époque on utilise un entier signé sur 32 bits pour représenter le temps, c’est méconnaître grandement l’impact en performance d’un autre choix. Tout comme certains qui regrettent les nombres flottants par rapport au calcul multiprécision. Ne pas oublier que ce sont des données manipulées en permanence (de nombreux programmes font des appels systèmes liés à la date des milliers de fois par seconde). Il faut qu’on puisse le traiter vite et utiliser le type natif du processeur offrait un bon compromis performance / longévité. Et bien entendu cette donnée étant générée par le noyau de votre système d’exploitation, n’espérez pas un comportement de haut niveau avec des données très abstraites. Ne pas oublier également qu’UNIX (et la norme POSIX) ont une longévité record. Vous connaissez des API et des OS aussi vieux tout en étant largement utilisés ? En réalité, il n’y en a pas vraiment. Je doute très fortement que quiconque à l’époque aurait prédit un tel succès.

Ce n’est donc pas un mauvais design, comme tout en informatique, cela résulte d’un compromis qui a été longuement efficace. Et il était assez invraisemblable au moment de la définition que POSIX et l’architecture 32 bits pourraient coexister jusqu’à cette échelle de temps.

Corriger le problème pour des machines compatibles POSIX avec une architecture 32 bits sous-jacente n’est pas aisée si on s’inquiète de la stabilité de l’ABI, ce qui est le cas de Linux. À dire vrai il existe déjà des appels systèmes qui utilisent des entiers 64 bits pour de telles architecture mais cela demande du code spécifique et donc de recompiler les programmes concernés ce qui n’est pas toujours possible. Et cela est moins portable (non compatible POSIX de souvenir).

L’idée est d’essayer de mettre des wrappers dans le noyau et la glibc pour contourner plus ou moins le soucis. En tout cas ce n’est pas simple et malgré des années de travaux nous sommes encore loin d’une solution parfaite (de nombreuses structures fournies par le noyau, dont via les ioctl utilisent le fameux type time_t source de tous les maux.

Travaillant dans l’embarqué, on débute des projets dont la durée de vie est de 10-15 ans avec de l’ARM 32 bits, on commence donc à toucher l’horizon des temps du fameux bogue. Et bien entendu dans l’aérospatial, militaire, automobile, ferroviaire ou aéronautique cela est probablement déjà atteint ce qui n’est pas sans poser de soucis à terme.

Allons tester nos applications ! Je serais curieux de connaitre les vrais effets problématiques de ce bug dans la pratique.

Bah exemple tout con, mon projet actuel est un collecteur de capteurs qui assigne donc à chaque mesure une date précise en temps réel. Et pour des raisons de performances, ARM 32 bits tout ça, time_t est un 32 bits signé. Si jamais la date du bogue 2038 est atteinte, bah j’aurais une date fausse et le serveur en face aura bien du mal à m’afficher la donnée à la date attendue.

Et je passe outre certains codes (un peu sale), où il font de la différence de temps pour calculer des timeout. Le temps d’attente risque d’être bien long une fois ce seuil franchi…

Dans ma tête c’était un INT UNSIGNED, je n’avais jamais vu qu’on pouvait utiliser un nombre négatif pour aller avant 1970.

De souvenir POSIX ne définie pas vraiment le type de time_t. C’est au choix du compilateur / système. Mais autoriser un nombre négatif n’est pas forcément idiot, soit pour permettre en effet un espace de temps plus large que celui proposé par défaut dans le passé. Ou pour faire passer des erreurs. Ou pour faire des comparaisons de temps (une différence de temps qui retourne une valeur négative).

Dans POSIX c’est de toute façon assez rare l’usage des unsigned int, le type entier est très souvent préféré pour des raisons de souplesses et de performances.

+0 -0

Question bête, mais au lieux de stocker la date dans une variable qui augmente de 1 toutes les secondes, pourquoi ils n’ont pas stocker la date sous forme "YYYYMMDDHHMMSS" ?

Ca donnerais pas exemple : 20180613012045. Là aussi il faut augmenter de 1 toutes les secondes, mais avant d’atteindre la limite, il y en à pour un moment…

Après, je dit sûrement une grosse bêtise, mais ne connaissant pas vraiment comment ça fonctionne, ça me paraît une bonne solution. :p

+0 -0

Car dans ce cas tu manipules un entier non continu ce qui est bien sûr source de bogues (20190229012045 n’existe pas), complexifie sa manipulation, ne gère pas tous les cas (tu t’occupes comment des secondes intercalaires qui sont une plaie par définition ? Les fuseaux horaires ?), les différences de calendriers (avec un timestamp comme aujourd’hui, passer du calendrier grégorien au julien, ou même au calendrier perse ou chinois est possible assez facilement).

Puis étant donnée la gueule de l’entier résultant, tu outrepasses largement la représentation 32 bits aussi. Et le timestamp traditionnel ne pose aucun soucis en 64 bits en terme de représentation (ou alors il faudrait s’inquiéter si une telle compatibilité était maintenue si longtemps !).

Comme la durée élémentaire de base est la seconde (selon la SI), utiliser un compteur en seconde depuis une date fixe dans le temps est loin d’être idiot. Cela est même plutôt efficient pour s’affranchir des soucis de représentations culturels (les calendriers) et tenir compte des difficultés intrinsèques liées au temps (seconde intercalaire, fuseaux horaires). Cela offre une meilleure souplesse tout en étant plus rapide en terme de calculs.

Ne pas oublier que le temps est peut être la mesure la plus complexe à représenter. Entre autre car nous basons tout notre système sur des temps ronds (journée de 24h, années de 365 jours de base) alors que la réalité est plus complexe que cela.

+1 -0

En fait selon ton application, ce n’est pas un problème à prendre en compte dans le futur mais qui a été pris en compte dans le passé.

Typiquement les applications bancaires : j’ai un prêt qui court sur 20 ans, qui se termine donc après ce fameux bug. Si la date de fin est enregistrée ou seulement traitée quelque part avec un timestamp, le cas a dû être géré. En fait, il a dû être géré il y a au moins 5 ans car on trouve des prêts sur 25 ans.

Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte