|
|
Δημοσιεύτηκε στις 31/7/2023 6:36:01 μ.μ.
|
|
|
|

Ένα ηλιόλουστο πρωινό, καθόμουν μπροστά από το φορητό υπολογιστή μου και αναδιάρθρωνα κάποιο κώδικα C#. Όλα πάνε καλά και θα είναι μια παραγωγική μέρα. Στη συνέχεια, πρόσθεσα πάρα πολλά σύμβολα ίσον στη σταθερή κυριολεκτική συμβολοσειρά και τα πράγματα εξερράγησαν. Η παραγωγικότητα έχει φύγει. Η ήρεμη ανοικοδόμηση της Κυριακής είναι πίσω μας. Ακόμα και ο ήλιος αποφάσισε να κρυφτεί πίσω από τα σύννεφα.
Αφού πέρασα 30 με 40 λεπτά προσπαθώντας να καταλάβω τι έκανα λάθος, συνειδητοποίησα ότι δεν ήμουν εγώ. Είναι η Microsoft. Προφανώς, έπεσα πάνω σε ένα παλιό σφάλμα στη λειτουργία αποκωδικοποίησης Base64.Μετατροπή.FromBase64StringΑυτό το σφάλμα υπάρχει σίγουρα από τότε που εισήχθη το .NET 1.1 το 2003. Πω πω! Αυτό είναι παλιό. Και δεν είναι πολύ δύσκολο να αναπαραχθεί. Μπράβο:
Τεχνικά, αυτό είναι παράνομο Base64. Η νομική έκδοση είναι "abc=". Σημειώστε μόνο έναν χαρακτήρα πλήρωσης =. Η κωδικοποίηση Base64 αντιπροσωπεύει κάθε 6 bit δυαδικής εισόδου σε έναν χαρακτήρα ASCII. Αυτό σημαίνει ότι κάθε 4 χαρακτήρες σε μια κωδικοποιημένη συμβολοσειρά Base64 αντιπροσωπεύουν 3 byte. Όταν τα κωδικοποιημένα δεδομένα δεν είναι πολλαπλάσιο των 3 byte, ο κωδικοποιητής Base64 προσθέτει έναν χαρακτήρα πλήρωσης για να κάνει το Base64 πολλαπλάσιο των 4 χαρακτήρων. Αυτό θα δημιουργήσει μια συμβολοσειρά Base64 που έχει συμπληρωθεί σωστά με "abc=". Η προσθήκη ενός άλλου = θα το ακυρώσει.
Το Base64 "abc=" αποκωδικοποιείται ως δύο byte [105, 183]. Σωστά. Η προσθήκη ενός άλλου χαρακτήρα συμπλήρωσης στο τέλος δεν θα πρέπει να αλλάξει πραγματικά την κωδικοποιημένη τιμή. Είναι σαν να προσθέτεις ένα κενό στο τέλος μιας πρότασης. Ναι, υπάρχει, αλλά δεν αλλάζει το νόημα της πρότασης. Αλλά το .NET δεν το πιστεύει. Το "abc==" αποκωδικοποιείται ως byte [109]. Όχι μόνο έγινε πιο σύντομο, κάτι που ήταν περίεργο γιατί κάναμε την είσοδο μεγαλύτερη. Έχει γίνει επίσης διαφορετικό. Το πρώτο byte πηγαίνει από το 105 στο 109. Και δεν έκανε ούτε εξαίρεση. Προσθέστε ένα άλλο = και θα έχετε μια εξαίρεση. Καταπληκτικός!
Κώδικας:
Απόδοση:
'abc=' -> [105, 183] 'abc==' -> [109] Είναι πραγματικά εκπληκτικό που κανείς δεν το έχει προσέξει αυτό τόσα χρόνια. Ή βρέθηκε αλλά δεν διορθώθηκε. Το Base64 είναι πολύ σημαντικό για την ανταλλαγή πληροφοριών στο δίκτυο. Φαίνεται παντού. Ωστόσο, το .NET δεν έχει απαλλαγεί από τον ελαττωματικό αποκωδικοποιητή Base64 εδώ και χρόνια.
Στην αρχή δεν μπορούσα να το πιστέψω και άρχισα να ερευνώ. Έψαξα στο google για λίγο και δεν βρήκα πολλά. Μετά δημοσίευσα στο StackOverflow και δεν είχα και πολλή τύχη. Μόλις κατάλαβα τι συνέβαινε, έπρεπε να απαντήσω ακόμη και στις δικές μου ερωτήσεις. Αφού έψαξα στο GitHub για λίγο, έπεσα πάνω σε μια επιδιόρθωση που έγινε στο .NET Core τον Ιούλιο του 2018. Έτσι, η τελευταία έκδοση .NET Core χειρίζεται σωστά αυτό το ζήτημα και κάνει μια εξαίρεση:
Unhandled Exception: System.FormatException: Η είσοδος δεν είναι έγκυρη συμβολοσειρά Base-64, καθώς περιέχει έναν χαρακτήρα που δεν είναι base 64, περισσότερους από δύο χαρακτήρες padding ή έναν μη έγκυρο χαρακτήρα μεταξύ των αναπλήρωση χαρακτήρων. στο System.Convert.FromBase64CharPtr(Char* inputPtr, Int32 inputLength) στο System.Convert.FromBase64String(String s) στο Program.DecodeAndPrint(String base64) στο ./base64/Program.cs:line 13 στο Program.Main() στο ./base64/Program.cs:line 8 Τους πήρε περίπου 15 χρόνια για να βρουν και να διορθώσουν το πρόβλημα. Είναι ενδιαφέρον ότι κανείς δεν προσπάθησε πραγματικά να το διορθώσει συγκεκριμένα. Αυτό συνέβη όταν ξαναέγραψαν τον κώδικα για να τον κάνουν πιο γρήγορο:
Το Convert.FromBase64() έχει ένα λεπτό σφάλμα όπου ο δεύτερος χαρακτήρας με παράνομη επένδυση στο τέλος της συμβολοσειράς προκαλεί την "επιτυχία" της αποκωδικοποίησης αφαιρώντας τον προτελευταίο χαρακτήρα.
Είμαστε στο . Αυτό το σφάλμα διορθώθηκε κατά λάθος όταν το API βελτιστοποιήθηκε στο NetCore 2.1. Προσθέστε δοκιμές για να καταγράψετε σφάλματα και βεβαιωθείτε ότι δεν θα πάμε πίσω. Επομένως, αυτό το ζήτημα διορθώνεται στο .NET Core 2.2. Αλλά στην τρέχουσα τελευταία έκδοση του .NET Framework 4.7.2 εξακολουθεί να έχει προβλήματα. Φαίνεται σαν να έχει σπάσει και στο Mono.
Η λύση στο .NET 4.7.2 είναι να ξαναγεμίσετε την εσφαλμένα συμπληρωμένη συμβολοσειρά με κάτι σαν αυτό:
Αρχικός:Η σύνδεση με υπερσύνδεσμο είναι ορατή.
|
Προηγούμενος:Azure DevOps (viii) Μεταγλωττίζει ASP.NET έργα MVC χρησιμοποιώντας τη Δημιουργία διοχέτευσηςΕπόμενος:Χρησιμοποιείται ένα νέο χρονόμετρο στο .NET 6, το PeriodicTimer
|