|
|
Publié sur 31/07/2023 18:36:01
|
|
|
|

Un matin ensoleillé, j’étais assis devant mon ordinateur portable en train de restructurer du code C#. Tout se passe bien et ce sera une journée productive. Ensuite, j’ai ajouté trop de signes égaux à la chaîne constante littéral, et tout a explosé. La productivité a disparu. La reconstruction calme de dimanche est derrière nous. Même le soleil décida de se cacher derrière les nuages.
Après avoir passé 30 à 40 minutes à essayer de comprendre ce que je faisais de mal, j’ai réalisé que ce n’était pas moi. C’est Microsoft. Apparemment, je suis tombé sur un vieux bug dans la fonction de décodage Base64.Convert.FromBase64StringCe bug existe clairement depuis l’introduction de .NET 1.1 en 2003. Pleurage! C’est vieux. Et ce n’est pas très difficile à reproduire. Bon travail:
Techniquement, c’est illégal Base64. La version légale est « abc= ». Notez qu’un seul caractère de remplissage =. L’encodage Base64 représente chaque 6 bits d’entrée binaire dans un caractère ASCII. Cela signifie que chaque 4 caractères dans une chaîne codée en Base64 représente 3 octets. Lorsque les données encodées ne sont pas un multiple de 3 octets, l’encodeur Base64 ajoute un caractère de remplissage pour faire de Base64 un multiple de 4 caractères. Cela générera une chaîne Base64 correctement remplie avec « abc= ». Ajouter un autre = l’invalidera.
Base64 « abc= » est décodé en deux octets [105, 183]. C’est juste. Ajouter un autre caractère de remplissage à la fin ne devrait pas vraiment changer la valeur encodée. C’est comme ajouter un espace à la fin d’une phrase. Oui, elle est là, mais elle ne change pas le sens de la phrase. Mais .NET ne le pense pas. « abc== » est décodé sous forme d’octet [109]. Non seulement elle est devenue plus courte, ce qui était étrange car nous avons rendu l’entrée plus longue. C’est aussi devenu différent. Le premier octet passe de 105 à 109. Et cela n’a pas non plus fait d’exception. Ajoutez un autre = et vous obtenez une exception. Stupéfiant!
Code:
Sortie:
'abc=' -> [105, 183] 'abc==' -> [109] C’est vraiment incroyable que personne n’ait remarqué cela depuis tant d’années. Ou alors il a été trouvé mais pas réparé. Base64 est très important dans l’échange d’informations sur le réseau. On peut la voir partout. Cependant, .NET n’a pas supprimé le décodeur Base64 défectueux depuis des années.
Au début, je n’y croyais pas et j’ai commencé à enquêter. J’ai cherché un moment sur Google et je n’ai pas trouvé grand-chose. Ensuite, j’ai posté sur StackOverflow et je n’ai pas eu beaucoup de chance non plus. Une fois que j’ai compris ce qui se passait, j’ai même dû répondre à mes propres questions. Après avoir cherché un moment sur GitHub, je suis tombé sur un correctif réalisé en .NET Core en juillet 2018. Ainsi, la dernière version de .NET Core gère correctement ce problème et fait une exception :
Exception non traitée : System.FormatException : L’entrée n’est pas une chaîne Base-64 valide car elle contient un caractère non-base 64, plus de deux caractères de remplissage, ou un caractère illégal parmi les Des personnages de remplissage. at System.Convert.FromBase64CharPtr(Char* inputPtr, Int32 inputLong) at System.Convert.FromBase64String(String s) sur Program.DecodeAndPrint(String base64) dans ./base64/Program.cs :line 13 sur Program.Main() dans ./base64/Program.cs :ligne 8 Il leur a fallu environ 15 ans pour trouver et résoudre le problème. Fait intéressant, personne n’a vraiment essayé de le réparer spécifiquement. Cela s’est produit lorsqu’ils ont réécrit le code pour le rendre plus rapide :
Convert.FromBase64() présente un bug subtil où le second caractère illégalement rempli à la fin de la chaîne fait que le décodage « réussit » en supprimant l’avant-dernier caractère.
Nous en sommes à . Ce bug a été corrigé par inadvertance lorsque l’API a été optimisée dans NetCore 2.1. Ajoutez des tests aux erreurs de journal et assurez-vous de ne pas revenir en arrière. Ce problème est donc corrigé dans .NET Core 2.2. Mais dans la dernière version actuelle du .NET Framework 4.7.2, il y a toujours des problèmes. Il semble aussi cassé en Mono.
La solution de contournement dans .NET 4.7.2 consiste à recharger la chaîne mal remplie avec quelque chose comme ceci :
Langue source:La connexion hyperlientérée est visible.
|
Précédent:Azure DevOps (viii) compile ASP.NET projets MVC en utilisant Pipelines BuildProchain:Un nouveau minuteur en .NET 6, PeriodicTimer, est utilisé
|