|
|
Julkaistu 31.7.2023 18.36.01
|
|
|
|

Eräänä aurinkoisena aamuna istuin läppärini edessä uudelleenjärjestelyssä C#-koodia. Kaikki sujuu hyvin ja päivä tulee olemaan tuottelias. Sitten lisäsin liian monta yhtäsuuruusmerkkiä vakiomerkkijonoon, ja asiat räjähtivät. Tuottavuus on poissa. Sunnuntain rauhallinen jälleenrakennus on takanapäin. Jopa aurinko päätti piiloutua pilvien taakse.
Käytettyäni 30–40 minuuttia yrittäessäni selvittää, mitä tein väärin, tajusin, ettei vika ollut minussa. Se on Microsoft. Ilmeisesti törmäsin vanhaan bugiin Base64:n dekoodausfunktiossa.Muunna. FromBase64StringTämä bugi on ollut olemassa siitä lähtien, kun .NET 1.1 esiteltiin vuonna 2003. Vau! Se on vanhaa. Eikä sen toistaminen ole kovin vaikeaa. Hyvää työtä:
Teknisesti ottaen tämä on laitonta Base64:ää. Oikeudellinen versio on "abc=". Huomaa vain yksi täytemerkki =. Base64-koodaus edustaa jokaista 6 binäärisyötteen bittiä yhdellä ASCII-merkillä. Tämä tarkoittaa, että jokainen 4 merkkiä Base64-koodatussa merkkijonossa edustaa 3 tavua. Kun koodattu data ei ole kolmen tavun monikertainen, Base64-kooderi lisää täytemerkin, jolloin Base64 on neljän merkin monikertainen. Tämä tuottaa Base64-merkkijonon, joka on asianmukaisesti täytetty "abc=". Toisen = lisääminen mitätöi sen.
Base64 "abc=" dekoodataan kahdella tavulla [105, 183]. Niin juuri. Toisen täytemerkin lisääminen loppuun ei oikeastaan pitäisi muuttaa koodattua arvoa. Se on kuin lisäisi välilyöntiä lauseen loppuun. Kyllä, se on siellä, mutta se ei muuta lauseen merkitystä. Mutta .NET ei usko niin. "abc==" puretaan tavuna [109]. Se ei vain lyhentynyt, mikä oli outoa, koska teimme syötteestä pidemmän. Se on myös muuttunut. Ensimmäinen tavu menee 105:stä 109:ään. Eikä se tehnyt poikkeusta. Lisää vielä = ja saat poikkeuksen. Hämmästyttävä!
Koodi:
Tuotos:
'abc=' -> [105, 183] 'abc==' -> [109] On todella hämmästyttävää, ettei kukaan ole huomannut tätä niin moneen vuoteen. Tai se löydettiin, mutta ei korjattu. Base64 on erittäin tärkeä verkon tiedonvaihdossa. Se näkyy kaikkialla. Kuitenkin .NET ei ole poistanut viallista Base64-dekooderia vuosiin.
Aluksi en voinut uskoa sitä ja aloin tutkia asiaa. Googlasin hetken, mutta en löytänyt paljoa. Sitten postasin StackOverflow'hun, enkä saanut juuri onnea. Kun ymmärsin, mitä oli meneillään, minun piti jopa vastata omiin kysymyksiini. Etsittyäni hetken GitHubista törmäsin heinäkuussa 2018 tehtyyn .NET Corella tehtyyn korjaukseen. Uusin .NET Core -versio käsittelee tämän ongelman oikein ja heittää poikkeuksen:
Käsittelemätön poikkeus: System.FormatException: Syöte ei ole kelvollinen Base-64-merkkijono, koska se sisältää ei-base 64 -merkin, enemmän kuin kaksi täytemerkkiä tai laittoman merkin joukossa Täyttävät hahmot. at System.Convert.FromBase64CharPtr(Char* inputPtr, Int32 inputLength) osoitteessa System.Convert.FromBase64String(String s) osoitteessa Program.DecodeAndPrint (String base64) tiedostossa ./base64/Program.cs:rivi 13 osoitteessa Program.main() muodossa ./base64/Program.cs:rivi 8 Heiltä kesti noin 15 vuotta löytää ja korjata ongelma. Mielenkiintoista kyllä, kukaan ei oikeastaan yrittänyt korjata sitä erityisesti. Tämä tapahtui, kun koodi kirjoitettiin uudelleen nopeammaksi:
Convert.FromBase64():ssa on hienovarainen bugi, jossa toinen laittomasti täytetty merkki merkkijonon lopussa saa dekoodauksen "onnistumaan" poistamalla toiseksi viimeisen merkin.
Olemme . Tämä bugi korjattiin vahingossa, kun API optimoitiin NetCore 2.1:ssä. Lisää testejä virheiden lokimiseen ja varmista, ettemme mene taaksepäin. Tämä ongelma on siis korjattu .NET Core 2.2:ssa. Mutta nykyisessä uusimmassa .NET Framework 4.7.2 -versiossa ongelmia on edelleen. Näyttää siltä, että se on rikki myös Monossa.
Kiertotie .NET 4.7.2:ssa on täyttää väärin täytetty merkkijono tällaisella:
Alkuperäinen:Hyperlinkin kirjautuminen on näkyvissä.
|
Edellinen:Azure DevOps (viii) Compiles ASP.NET MVC-projekteja käyttäen Pipelines BuildSeuraava:.NET 6:ssa käytetään uutta ajastinta, PeriodicTimer,
|