Kādu saulainu rītu es sēdēju pie sava klēpjdatora, pārstrukturējot kādu C# kodu. Viss notiek labi, un tā būs produktīva diena. Tad es pievienoju pārāk daudz vienādības zīmju pastāvīgajai virknei burtiski, un lietas eksplodēja. Produktivitāte ir pazudusi. Svētdienas mierīgā rekonstrukcija ir aiz muguras. Pat saule nolēma paslēpties aiz mākoņiem.
Pēc 30 līdz 40 minūtēm, mēģinot saprast, ko es daru nepareizi, es sapratu, ka tas neesmu es. Tas ir Microsoft. Acīmredzot, es paklupu uz vecu kļūdu Base64 dekodēšanas funkcijā.Konvertēt.FromBase64StringŠī kļūda noteikti ir pastāvējusi kopš .NET 1.1 ieviešanas 2003. gadā. Wow! Tas ir vecs. Un to nav ļoti grūti reproducēt. Labs darbs:
Tehniski tas ir nelikumīgs Base64. Juridiskā versija ir "abc=". Ņemiet vērā tikai vienu aizpildīšanas rakstzīmi =. Base64 kodējums attēlo katrus 6 binārās ievades bitus vienā ASCII rakstzīmē. Tas nozīmē, ka katrās 4 rakstzīmes Base64 kodētajā virknē ir 3 baiti. Ja kodētie dati nav 3 baitu daudzkārtnis, Base64 kodētājs pievieno aizpildīšanas rakstzīmi, lai padarītu Base64 par 4 rakstzīmju daudzkārtni. Tādējādi tiks ģenerēta Base64 virkne, kas ir pareizi aizpildīta ar "abc=". Pievienojot vēl vienu =, tas tiks atzīts par nederīgu.
Base64 "abc=" tiek dekodēts kā divi baiti [105, 183]. Tas ir pareizi. Pievienojot vēl vienu polsterējuma rakstzīmi beigās, kodētā vērtība īsti nemainīsies. Tas ir tāpat kā atstarpes pievienošana teikuma beigās. Jā, tas ir, bet tas nemaina teikuma nozīmi. Bet .NET tā nedomā. "abc==" tiek dekodēts kā baits [109]. Tas ne tikai kļuva īsāks, kas bija dīvaini, jo mēs padarījām ievadi garāku. Tas ir arī kļuvis atšķirīgs. Pirmais baits iet no 105 līdz 109. Un tas arī nebija izņēmums. Pievienojiet vēl vienu = un jūs saņemsiet izņēmumu. Pārsteidzošs!
Kods:
Izvades:
'abc=' -> [105, 183] 'abc==' -> [109] Tas ir patiešām pārsteidzoši, ka neviens to nav pamanījis tik daudzus gadus. Vai arī tas tika atrasts, bet nav novērsts. Base64 ir ļoti svarīgs informācijas apmaiņā tīklā. To var redzēt visur. Tomēr .NET gadiem ilgi nav atbrīvojies no kļūdainā Base64 dekodētāja.
Sākumā es nevarēju tam noticēt un sāku izmeklēt. Es kādu laiku googlēju un neatradu daudz. Tad es ievietoju vietnē StackOverflow un arī nesaņēmu daudz veiksmes. Kad es sapratu, kas notiek, man pat bija jāatbild uz saviem jautājumiem. Pēc tam, kad kādu laiku meklēju GitHub, es paklupu uz labojumu, kas tika veikts .NET Core 2018. gada jūlijā. Tātad jaunākā .NET Core versija pareizi apstrādā šo problēmu un rada izņēmumu:
Neapstrādāts izņēmums: System.FormatException: ievade nav derīga Base-64 virkne, jo tajā ir 64 rakstzīme, kas nav bāze, vairāk nekā divas pildījuma rakstzīmes vai nelikumīga rakstzīme starp polsterējuma rakstzīmes. vietnē System.Convert.FromBase64CharPtr(Char* inputPtr, Int32 inputLength) vietnē System.Convert.FromBase64String(String s) pie Program.DecodeAndPrint(String base64) ./base64/Program.cs:13. rindā pie Program.Main() ./base64/Program.cs:line 8 Viņiem vajadzēja apmēram 15 gadus, lai atrastu un atrisinātu problēmu. Interesanti, ka neviens īsti nemēģināja to īpaši labot. Tas notika, kad viņi pārrakstīja kodu, lai padarītu to ātrāku:
Convert.FromBase64() ir smalka kļūda, kur otrā nelegāli polsterētā rakstzīme virknes beigās izraisa dekodēšanu "veiksmīgi", noņemot priekšpēdējo rakstzīmi.
Mēs esam . Šī kļūda tika nejauši novērsta, kad API tika optimizēta NetCore 2.1. Pievienojiet testus, lai reģistrētu kļūdas un pārliecinātos, ka mēs neejam atpakaļ. Tātad šī problēma ir novērsta .NET Core 2.2. Bet pašreizējā jaunākajā .NET Framework 4.7.2 versijā joprojām ir problēmas. Izskatās, ka tas ir salauzts arī Mono.
.NET 4.7.2 risinājums ir nepareizi aizpildītās virknes aizpildīšana ar kaut ko līdzīgu:
Sākotnējā:Hipersaites pieteikšanās ir redzama.
|