五倍券官網當機亂碼為什麼「滚」出來? - 黑暗執行緒

文章推薦指數: 80 %
投票人數:10人

一樣是UTF8 誤判成BIG5,IE、Edge/Chrome(都是Chromium 核心)、Firefox 出現的亂碼不盡相同,也跟.NET 轉換結果不同。

IE 顯示為「甇斗? ? 瘜蝙?」(比. 前幾天的五倍券開搶,九點一到不意外地系統當機了。

話說,幾百萬人同時殺進來,系統撐不住很正常,完全沒事才叫意外,能很快復原就算設計者功力不差了。

依據事前事後的網路評論,感覺會設計高流量系統的鄉民路人真不少,不管有沒寫過程式都能說出一番道理,分流啦、動態擴充伺服器、預先做好壓測、不能用ASP.NET要用GO語言寫...以我對系統設計的淺薄了解,每項說法都有道理(除了ASP.NET不行得用GO之外,你知道工程師賴以維生的StackOverflow是用ASP.NET寫的嗎?就不是南拳北拳的問題呀),但絕對不是要做好某一項就能安全下莊,而是每個細節都得考慮周到,否則系統通常會在最脆弱的一環爆炸給你看,提醒你哪裡還沒做好。

設計高流量系統不是我的專業,但五倍券當機時噴出的亂碼卻引起我的好奇。

當時出現的錯誤訊息因中文編碼解析錯誤出現「甇斗?滚?嗵?⊥?蓥蝙?鍂??」,因其中夾雜「滚」字還意外引發討論成為話題(冏!五倍券無法綁定 亂碼藏字叫你「滾」),依經驗是多是套錯UTF8、BIG5編碼造成,之前研究過,例如:中文亂碼"蕞蕞蕞蕞"是怎麼來的?、中文亂碼「嚙踝蕭嚙踝蕭」是怎麼來的?,而依據報導,有網友切換編碼將BIG5改成UTF8即可看到原本的錯誤訊息是IIS過度忙碌時噴出的HTTP503訊息「此服務無法使用。

」,故推測狀況為系統回傳的是UTF8編碼,但瀏覽器誤判為BIG5變成亂碼,寫了程式驗證將「此服務無法使用。

」用UTF8轉成byte[]再用BIG5轉回String,原本預期會看到「甇斗?滚?嗵?⊥?蓥蝙?鍂??」秒結案,結果卻不然:是會變成亂碼,但我得到的是「甇斗??瘜蝙?具?」,根本不會出現「滚」,而跟「甇斗?滚?嗵?⊥?蓥蝙?鍂??」只有「甇斗蝙」三個字相同,開啟線上中文編碼解析進一步調查,「滚嗵蓥鍂」四個字根本不是BIG5編碼支援的字元,算是Unicode難字,在簡體中文GB2312編碼才有對映,這到底是怎麼一回事?註:擷圖之UTF16編碼有誤,已於2.0.1版修正,感謝讀者anthonywang指正。

為了驗證我寫了簡單網頁重現問題:

此服務無法使用。

檔案存成UTF8,但meta宣告故意寫成charset=Big5,分別用IE、Edge、Chrome、Firefox開啟,發現有趣的事:一樣是UTF8誤判成BIG5,IE、Edge/Chrome(都是Chromium核心)、Firefox出現的亂碼不盡相同,也跟.NET轉換結果不同。

IE顯示為「甇斗??瘜蝙?」(比.NET結果少了「具」),Edge/Chrome就如新聞所提是「甇斗?滚?嗵?⊥?蓥蝙?鍂??」,Firefox很有趣,沒有「滚」但集兩家之大成「甇斗??嗵?瘜蓥蝙?具??」比Edge/Chrome多了「瘜」跟「具」。

由此可知,各家瀏覽器將byte[]解讀成BIG5字元的實作存在一些差異。

但,Chrome/Edge中的「滚」是怎麼來的呢?為了查出真相,用線上中文編碼解析將「此服務無法使用。

」轉成UTF8BytesE6ADA4E69C8DE58B99E784A1E6B395E4BDBFE794A8E38082:再用以下ASP.NET程式測試不同byte[]在瀏覽器硬轉成BIG5的結果: voidPage_Load(objectsender,EventArgse) { varhex=Request["h"]??""; varbytes=newList(); foreach(Matchmin Regex.Matches(hex,"[0-9a-fA-F]{2}")) { bytes.Add(Convert.ToByte(m.Value,16)); } varbig5=System.Text.Encoding.GetEncoding("big5"); Response.BinaryWrite(big5.GetBytes("")); Response.BinaryWrite(bytes.ToArray()); Response.BinaryWrite(big5.GetBytes("")); Response.End(); } 我很快找出「滚」是8DE5變成的:依據BIG5編碼規則,8DE5落在0x8140-0xA0FE使用者自訂字元(造字區),理論上並不是一個通用的有效字元,那Chrome為什麼會判別它是「滚」字呢?我想到了Unicode補完計劃,並在香港的Unicode補完計劃字元表找到答案!8DE5是「滚」的HKSCS編碼,喚起我的記憶(延伸閱讀:Big5-HKSCS編碼初探(上)、Big5-HKSCS編碼初探(下)、Big5-HKSCS編碼補遺),結論:這次五倍券的錯訊息亂碼是UTF8編碼硬解成BIG5導致,IE跟.NET會依據標準BIG5(CodePage950)解析,而Chrome/Edge/Firefox則會自動切換Big5-HKSCS企圖解析出更多字元,這就是「滚」字冒出來的原因。

解開一個謎團,開心!FindtheChinesemessageiscurruptedduetousingBIG5todecodeUTF8content,butIfoundsomecharinEdge/Chromewhichcannotreproducewith.NETEncodingAPI.Itturnedoutnon-IEbrowserswilluseBig5-HKSCStodecodedata.ShareonFacebookShareonTwitterShareonGoogle+EmailComments#2021-09-2601:21PMbyanthonywang線上版的UTF-16編碼錯了!?怎麼跟UTF-8一樣?應該是2bytes是吧~#2021-09-2601:24PMbyAC最後一段BIG5打成BUG5😂#2021-09-2601:54PMbystudent看來這篇有Bug5問題#2021-09-2602:08PMbyJeffreytoanthonywang,真的耶,居然一直都沒被發現,查到是Vue的v-bind寫錯了,稍後會更新。

感謝指正。

toAC,student,身為程式人員,不自覺就會寫出BUG來:P,謝謝指正。

#2021-10-0503:55PMbyabb想到之前特斯拉導航map遇到罕見字直接亂碼螢幕直接重開機 被捅一刀中文字太奇妙了哈#2021-10-1612:27AMbyRita誠如你所言,若有興趣,我國中央政府機關官網或是信件,也有亂碼問題,可惜,還沒人搞懂怎麼處理唷!PostacommentCommentNameCaptcha97-44=黑暗執行緒黑暗後花園OrcsWeb:WindowsServerHosting2021-10-16Rita五倍券官網當機亂碼為什麼「滚」出來?誠如你所言,若有興趣,我國中央政府機關官網或是信件,也有亂碼問題,可惜,還沒人搞懂怎麼處理唷!2021-10-05abb五倍券官網當機亂碼為什麼「滚」出來?想到之前特斯拉導航map遇到罕見字直接亂碼螢幕直接重開機 被捅一刀中文字太奇妙了哈2021-09-26Jeffrey五倍券官網當機亂碼為什麼「滚」出來?toanthonywang,真的耶,居然一直都沒被發現,查到是Vue的v-bind寫錯了...2021-09-26student五倍券官網當機亂碼為什麼「滚」出來?看來這篇有Bug5問題2021-09-26AC五倍券官網當機亂碼為什麼「滚」出來?最後一段BIG5打成BUG5😂2021-09-26anthonywang五倍券官網當機亂碼為什麼「滚」出來?線上版的UTF-16編碼錯了!?怎麼跟UTF-8一樣?應該是2bytes是吧~


請為這篇文章評分?