使用多字符常量的危险

图片1

在代码分析期间,PVS-Studio将分析数据流并对变量值进行操作。 值是从常量中提取的,还是从条件表达式中推断出来的。 我们称它们为虚拟价值。 最近,我们改进了它们以使用多字符常量,这就是创建新诊断规则的原因。

引言


多字符文字是实现定义的 ,因此不同的编译器可以用不同的方式对这些文字进行编码。 例如,GCC和Clang根据文字中字符的顺序设置一个值,而MSVC根据字符类型(常规或转义)移动它们。

例如,文字“ T \ x65s \ x74”将以不同的方式编码,具体取决于编译器。 必须向分析仪添加类似的逻辑。 结果,我们创建了一个新的诊断规则V1039来识别代码中的此类文字。 在使用多个编译器进行组装的跨平台项目中,此类文字很危险。

诊断V1039


考虑一个例子。 下面的代码由各种编译器编译,其行为将有所不同:

#include <stdio.h> void foo(int c) { if (c == 'T\x65s\x74') // <= V1039 { printf("Compiled with GCC or Clang.\n"); } else { printf("It's another compiler (for example, MSVC).\n"); } } int main(int argc, char** argv) { foo('Test'); return 0; } 

由不同的编译器编译的程序将在屏幕上打印不同的消息。

对于使用特定编译器的项目,这不会引起注意,但是移植可能会引起问题,因此您应使用简单的数字常量替换此类文字,例如,将“测试”更改为0x54657374。

为了演示编译器之间的区别,我们编写了一个小实用程序,其中使用3个字符和4个字符的序列,例如'GHIJ'和'GHI',并显示它们在编译后在内存中的表示形式。

实用代码:

 #include <stdio.h> typedef int char_t; void PrintBytes(const char* format, char_t lit) { printf("%20s : ", format); const unsigned char *ptr = (const unsigned char*)&lit; for (int i = sizeof(lit); i--;) { printf("%c", *ptr++); } putchar('\n'); } int main(int argc, char** argv) { printf("Hex codes are: G(%02X) H(%02X) I(%02X) J(%02X)\n",'G','H','I','J'); PrintBytes("'GHIJ'", 'GHIJ'); PrintBytes("'\\x47\\x48\\x49\\x4A'", '\x47\x48\x49\x4A'); PrintBytes("'G\\x48\\x49\\x4A'", 'G\x48\x49\x4A'); PrintBytes("'GH\\x49\\x4A'", 'GH\x49\x4A'); PrintBytes("'G\\x48I\\x4A'", 'G\x48I\x4A'); PrintBytes("'GHI\\x4A'", 'GHI\x4A'); PrintBytes("'GHI'", 'GHI'); PrintBytes("'\\x47\\x48\\x49'", '\x47\x48\x49'); PrintBytes("'GH\\x49'", 'GH\x49'); PrintBytes("'\\x47H\\x49'", '\x47H\x49'); PrintBytes("'\\x47HI'", '\x47HI'); return 0; } 

由Visual C ++编译的实用程序的输出:

 Hex codes are: G(47) H(48) I(49) J(4A) 'GHIJ' : JIHG '\x47\x48\x49\x4A' : GHIJ 'G\x48\x49\x4A' : HGIJ 'GH\x49\x4A' : JIHG 'G\x48I\x4A' : JIHG 'GHI\x4A' : JIHG 'GHI' : IHG '\x47\x48\x49' : GHI 'GH\x49' : IHG '\x47H\x49' : HGI '\x47HI' : IHG 

由GCC或Clang编译的实用程序的输出:

 Hex codes are: G(47) H(48) I(49) J(4A) 'GHIJ' : JIHG '\x47\x48\x49\x4A' : JIHG 'G\x48\x49\x4A' : JIHG 'GH\x49\x4A' : JIHG 'G\x48I\x4A' : JIHG 'GHI\x4A' : JIHG 'GHI' : IHG '\x47\x48\x49' : IHG 'GH\x49' : IHG '\x47H\x49' : IHG '\x47HI' : IHG 

结论


V1039诊断已添加到最近发布的PVS-Studio分析仪7.03版中。 您可以在下载页面下载最新版本的分析仪。



如果您想与说英语的读者分享这篇文章,请使用以下链接:Svyatoslav Razmyslov。 使用多字符常量的危险

Source: https://habr.com/ru/post/zh-CN457696/


All Articles