|
|
Geplaatst op 31-07-2023 18:36:01
|
|
|
|

Op een zonnige ochtend zat ik voor mijn laptop wat C#-code te herstructureren. Alles gaat goed en het wordt een productieve dag. Toen voegde ik te veel gelijke tekens toe aan de constante string letterlijk, en het ging uit elkaar. De productiviteit is weg. De rustige wederopbouw van zondag ligt achter ons. Zelfs de zon besloot zich achter de wolken te verbergen.
Na 30 tot 40 minuten te hebben geprobeerd te begrijpen wat ik verkeerd deed, realiseerde ik me dat het niet aan mij lag. Het is Microsoft. Blijkbaar kwam ik een oude bug tegen in de Base64-decodeerfunctie.Convert.FromBase64StringDeze bug bestaat zeker al sinds de introductie van .NET 1.1 in 2003. Wauw! Dat is oud. En het is niet erg moeilijk om het te reproduceren. Goed gedaan:
Technisch gezien is dit illegale Base64. De juridische versie is "abc=". Let op: slechts één vulpersonage =. Base64-codering vertegenwoordigt elke 6 bits binaire invoer in één ASCII-teken. Dit betekent dat elke 4 tekens in een Base64-gecodeerde string 3 bytes vertegenwoordigt. Wanneer de gecodeerde data geen veelvoud van 3 bytes is, voegt de Base64-encoder een vulteken toe om Base64 een veelvoud van 4 tekens te maken. Dit genereert een Base64-string die correct is ingevuld met "abc=". Het toevoegen van een andere = maakt het ongeldig.
Base64 "abc=" wordt gedecodeerd als twee bytes [105, 183]. Dat klopt. Het toevoegen van een extra opvulteken aan het einde zou de gecodeerde waarde eigenlijk niet moeten veranderen. Het is alsof je een spatie aan het einde van een zin toevoegt. Ja, het is er, maar het verandert de betekenis van de zin niet. Maar .NET denkt van niet. "abc==" wordt gedecodeerd als een byte [109]. Niet alleen werd het korter, wat vreemd was omdat we de invoer zo lang maakten. Het is ook anders geworden. De eerste byte gaat van 105 naar 109. En het gooide ook geen uitzondering. Voeg er nog een = toe en je krijgt een uitzondering. Verbazingwekkend!
Code:
Uitvoer:
'abc=' -> [105, 183] 'abc==' -> [109] Het is echt verbazingwekkend dat niemand dit al zoveel jaren heeft opgemerkt. Of het is gevonden maar niet gerepareerd. Base64 is erg belangrijk bij de uitwisseling van informatie op het netwerk. Het is overal te zien. Echter, .NET heeft de gebrekkige Base64-decoder al jaren niet meer verwijderd.
In het begin kon ik het niet geloven en begon ik te onderzoeken. Ik heb een tijdje gegoogeld en vond niet veel. Daarna plaatste ik iets op StackOverflow en had ook niet veel geluk. Toen ik eenmaal doorhad wat er aan de hand was, moest ik zelfs mijn eigen vragen beantwoorden. Na een tijdje zoeken op GitHub stuitte ik in juli 2018 op een fix die in .NET Core was gemaakt. Dus de nieuwste .NET Core-versie lost dit probleem correct op en geeft een uitzondering:
Onbeheerde Uitzondering: System.FormatException: De invoer is geen geldige Base-64-string omdat deze een niet-basis 64-teken, meer dan twee opvultekens of een illegaal teken bevat tussen de Onderdrukken personages. bij System.Convert.FromBase64CharPtr(Char* inputPtr, Int32 inputLength) op System.Convert.FromBase64String(String s) op Program.DecodeAndPrint (String base64) in ./base64/Program.cs:regel 13 op Program.Main() in ./base64/Program.cs:regel 8 Het duurde ongeveer 15 jaar voordat ze het probleem vonden en oplossen. Interessant genoeg heeft niemand echt geprobeerd het specifiek te repareren. Dit gebeurde toen ze de code herschreven om het sneller te maken:
Convert.FromBase64() heeft een subtiele bug waarbij het tweede illegaal opgevulde teken aan het einde van de string ervoor zorgt dat de decodering "slaagt" door het voorlaatste teken te verwijderen.
We zijn op . Deze bug werd per ongeluk opgelost toen de API werd geoptimaliseerd in NetCore 2.1. Voeg tests toe om fouten te loggen en zorg dat we niet teruggaan. Dit probleem is opgelost in .NET Core 2.2. Maar in de huidige nieuwste versie van .NET Framework 4.7.2 zijn er nog steeds problemen. Het lijkt erop dat het ook kapot is in Mono.
De oplossing in .NET 4.7.2 is om de verkeerd ingevulde string te vullen met iets als dit:
Origineel:De hyperlink-login is zichtbaar.
|
Vorig:Azure DevOps (viii) Compileert ASP.NET MVC-projecten met behulp van Pipelines BuildVolgend:Er wordt een nieuwe timer in .NET 6 gebruikt, PeriodicTimer,
|