在代码分析期间,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;
}
由不同编译器编译的程序将在屏幕上打印不同的消息。
对于使用特定编译器的项目,它不会引人注意。但是在移植时,可能会出现问题,因此应该用简单的数字常量替换这些文字,例如“Test”将用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;
}
由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
作者:Svyatoslav Razmyslov
原文链接:https://www.viva64.com/en/b/0634/