slimxml 编码错误排查

编程难

共 1865字,需浏览 4分钟

 ·

2023-02-04 19:27

缘起

前一段时间,同事遇到一个配置文件读取错误问题,让我帮忙看看。最开始不相信这么基础的功能会有问题。排查完发现,确实是一个字符编码转换方面的 bug,而且只有特定字符会有问题。一起来看看吧。

简化问题

为了使问题简化,我把配置文件内容改成了下面这样,只有一条记录。

simple-xml-contain-special-char

尝试重现

网上找到 slimxml 源码,编译,运行。

说明: 这个 xml 库是非常古老的一个库了。不建议使用。

加载上面的 xml。查看结果,果然与预期的不一致。配置文件里的字符是 φ,用 utf8 编码存储的。对应的字节流是 cf 86


加载到内存中后,使用 unicode 存储的,对应的字节流是 cf 00


φutf16 编码下对应的字节流应该是 c6 03 (小端字节序)。


编码转换的bug?

配置文件里是使用 utf8 保存的,加载到内存中后变成了 unicode 的,加载过程中一定发生了编码转换。难道是转换过程中发生了错误?单步跟踪 slimxml 加载文件的过程。很快就找到了关键函数—— utf8toutf16()。简单跟踪后,发现下面的处理代码有些问题,

else if ((*u8 & 0xe0) == 0xc0)
{
  if (size < 2)
  {
    break;
  }
  *(u16++) = (*u8 & 0x1f) | ((*(u8+1) & 0x3f) << 5); // <-- something wrong
  u8 += 2;
  size -= 2;
  ++converted;
}

于是,网上找了一段 utf8utf16 的代码,替换上面的处理,替换后的代码如下:

else if ((*u8 & 0xe0) == 0xc0)
{
  if (size < 2)
  {
    break;
  }
  *u16 = (*u8 & 0x1F) << 6;
  *u16 |= (*(u8 + 1) & 0x3F);
  u16++;
  u8 += 2;
  size -= 2;
  ++converted;
}

再次运行,发现效果正常。

总结

本次排查非常顺利,一是因为目标比较明确,二是因为在整个排查过程中,我清楚的知道每一步的正确结果是什么。字符编码是每个程序员的基本功,一定要熟练掌握。本文的参考资料中包含了非常给力的在线编码转换工具,非常值得收藏。

参考资料

https://www.tamasoft.co.jp/en/general-info/unicode.html

https://code.google.com/archive/p/slimxml/downloads

https://onlineunicodetools.com/convert-unicode-to-utf8

https://onlineunicodetools.com/convert-unicode-to-utf16

https://www.browserling.com/tools/utf8-encode

https://www.browserling.com/tools/utf8-decode

https://gist.github.com/rechardchen/3321830

浏览 21
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报