GHC 9.0.1下Haskell包异常Unicode输出问题排查问询
更新:已确认GHC 9.0.1相关bug为该问题的可能根源
我在使用GHC 9.0.1构建我的Haskell包crypto-enigma时,遇到了异常的Unicode行为。我知道排查该问题可能需要检查其他Haskell包的变更,本次咨询希望确认该异常输出是否对应已知的Unicode相关问题(Haskell领域或其他领域均可),方便我定位问题原因。
我原本预期的输出为:
β(或\946)γ(或\947)
实际输出却为:
β?KQHTLXOCBJSPDZRAMEWNIUYGVγ?EYJVCNIXWPBQMDRTAKZGFUHOS
该输出还有几个难以排查的特性:
- 希腊字符后的乱码字符在本地设备上固定,但在其他平台构建时结果不同,比如在Travis CI Focal环境下得到的输出为
β?SOVPZJAYQUIRHXLNFTGKDCMB - 可见内容和复制粘贴得到的内容不一致,通常首尾乱码字符会被截断,因此我推测
?实际是某个特殊字符
关键是,GHC 9之前的nightly解析器版本从未出现过该问题。
请问希腊字符后的异常字符序列是否对应已知问题,可辅助定位错误根源?GHC 9或最新Stackage nightly解析器中的包对Unicode的处理是否存在可能导致该问题的变更?
更新:经排查,依赖包未发生变更,使用相同nightly依赖在GHC 8.10版本下运行正常(仍在进一步验证中),问题似乎出现在使用Unicode字符作为键的场景。
我的相关代码如下:
type Name = String type Wiring = Mapping type Turnovers = String data Component = Component { name :: !Name, -- ^ 组件的名称 wiring :: !Wiring, -- ^ 组件的接线配置 turnovers :: !Turnovers -- ^ 组件的跳变配置 } -- 转子组件的定义,这些配置来自历史资料 rots_ :: M.Map Name Component rots_ = M.fromList $ (name &&& id) <$> [ -- 转子列表 Component "I" "EKMFLGDQVZNTOWYHXUSPAIBRCJ" "Q", Component "II" "AJDKSIRUXBLHWTMCQGZNPYFVOE" "E", Component "III" "BDFHJLCPRTXVZNYEIWGAKMUSQO" "V", Component "IV" "ESOVPZJAYQUIRHXLNFTGKDCMWB" "J", Component "V" "VZBRGITYUPSDNHLXAWMJQOFECK" "Z", Component "VI" "JPGVOUMFYQBENHZRDKASXLICTW" "ZM", Component "VII" "NZJHGRCXMYSWBOUFAIVLPEKQDT" "ZM", Component "VIII" "FKQHTLXOCBJSPDZRAMEWNIUYGV" "ZM", Component "β" "LEYJVCNIXWPBQMDRTAKZGFUHOS" "", Component "γ" "FSOKANUERHMBTIYCWLQPZXVGJD" ""]
另有代码:
rotors :: [Name] rotors = M.keys rots_
仅在GHC 9版本下,当Component的name为希腊字符时,keys返回值除了希腊字符外还会附带其他文本,附带文本随环境变化:本地设备上固定为rots_中前一个Component的wiring值,而在Travis CI环境中,β会附带IV的wiring值,γ仅会附带X。
我推测该问题与编译器存储Unicode的逻辑有关,导致调用M.keys时读取到了不属于name的邻近内存内容。
该问题超出了我的Haskell技术能力范围,恳请各位提供排查思路或解决方案,非常感谢。
复现步骤:
stack update stack unpack crypto-enigma-0.1.1.6 cd crypto-enigma-0.1.1.6 rm -f stack.yaml && stack init --resolver nightly stack build --resolver nightly --haddock --test --bench --no-run-benchmarks
内容的提问来源于stack exchange,提问作者orome

