|
|
Postitatud 31.07.2023 18:36:01
|
|
|
|

Ühel päikeselisel hommikul istusin oma sülearvuti ees ja ümber korraldasin C# koodi. Kõik läheb hästi ja see saab olema produktiivne päev. Siis lisasin liiga palju võrdsusmärke konstantse stringi literaalile ja asjad plahvatasid. Tootlikkus on kadunud. Pühapäevane rahulik taastamine on möödas. Isegi päike otsustas pilvede taha peitu pugeda.
Pärast 30–40 minutit püüdes aru saada, mida ma valesti teen, sain aru, et see polnud mina. See on Microsoft. Ilmselt sattusin vana vea peale Base64 dekodeerimisfunktsioonis.Konverteeri.FromBase64StringSee viga on kindlasti olnud olemas alates .NET 1.1 tutvustamisest 2003. aastal. Vau! See on vana. Ja seda pole väga raske paljundada. Tubli töö:
Tehniliselt on see ebaseaduslik Base64. Juriidiline versioon on "abc=". Pane tähele, et ainult üks täitetähe =. Base64 kodeerimine esindab iga 6 bitti binaarset sisendit ühes ASCII märgis. See tähendab, et iga 4 tähemärki Base64 kodeeritud stringis esindab 3 baiti. Kui kodeeritud andmed ei ole 3 baidi kordne, lisab Base64 kodeerija täitemärgi, muutes Base64 nelja märgi kordseks. See genereerib Base64 stringi, mis on korrektselt täidetud "abc="-ga. Teise = lisamine tühistab selle.
Base64 "abc=" dekodeeritakse kahe baidina [105, 183]. Just nii. Teise täitemärgi lisamine lõppu ei tohiks kodeeritud väärtust tegelikult muuta. See on nagu lause lõppu tühiku lisamine. Jah, see on olemas, aga see ei muuda lause tähendust. Aga .NET ei arva nii. "abc==" dekodeeritakse baidina [109]. See mitte ainult ei muutunud lühemaks, mis oli imelik, sest me tegime sisendi pikemaks. See on muutunud ka teistsuguseks. Esimene bait liigub 105-lt 109-le. Ja see ei teinud erandit. Lisa veel = ja saad erandi. Hämmastav!
Kood:
Väljund:
'abc=' -> [105, 183] 'abc==' -> [109] On tõesti hämmastav, et keegi pole seda nii paljude aastate jooksul märganud. Või leiti see üles, aga ei parandatud. Base64 on võrgus info vahetamisel väga oluline. Seda on näha kõikjal. Kuid .NET pole vigasest Base64 dekoodrist juba aastaid lahti saanud.
Alguses ei suutnud ma seda uskuda ja hakkasin uurima. Googeldasin mõnda aega, aga ei leidnud eriti midagi. Siis postitasin StackOverflow'sse ja mul ei õnnestunud ka eriti hästi. Kui ma aru sain, mis toimub, pidin isegi oma küsimustele vastama. Pärast mõnda aega GitHubis otsimist sattusin juulis 2018 .NET Core'is tehtud parandusele. Seega lahendab viimane .NET Core versioon selle probleemi õigesti ja viskab erandi:
Käsitlemata erand: System.FormatException: Sisend ei ole kehtiv Base-64 string, kuna see sisaldab mitte-base 64 märki, rohkem kui kahte täitemärki või ebaseaduslikku märki Täitsid tegelasi. at System.Convert.FromBase64CharPtr(Char* inputPtr, Int32 inputLength) aadressil System.Convert.FromBase64String(string s) aadressil Program.DecodeAndPrint (string base64) kujul ./base64/Program.cs:line 13 aadressil Program.Main() in ./base64/Program.cs:read 8 Neil kulus umbes 15 aastat, et probleem üles leida ja lahendada. Huvitaval kombel ei püüdnud keegi seda konkreetselt parandada. See juhtus siis, kui nad kirjutasid koodi ümber, et seda kiiremaks teha:
Convert.FromBase64()-l on peen viga, kus teine ebaseaduslikult täidetud märk stringi lõpus põhjustab dekodeerimise "õnnestumise", eemaldades eelviimase tähemärgi.
Me oleme . See viga parandati kogemata, kui API optimeeriti NetCore 2.1-s. Lisa testid vigade logimiseks ja veendu, et me ei läheks tagasi. See probleem on lahendatud .NET Core 2.2-s. Kuid praeguses viimases .NET Framework 4.7.2 versioonis esineb endiselt probleeme. Tundub, et see on ka Monos katki.
Lahendus .NET 4.7.2-s on täita valesti täidetud string millegi sarnasega:
Originaal:Hüperlingi sisselogimine on nähtav.
|
Eelmine:Azure DevOps (viii) Compiles ASP.NET MVC projektid Pipelines Buildi abilJärgmine:.NET 6-s kasutatakse uut taimerit, PeriodicTimer,
|