使用多字符常量的危险

27 篇文章 0 订阅
1 篇文章 0 订阅

在代码分析期间,PVS-Studio分析数据流并操作变量值。值取自常量或从条件表达式派生。我们称之为虚拟价值观。最近,我们对它们进行了改进,以便使用多字符常量,这已成为创建新诊断规则的原因。

图片1

介绍

多字符文字是实现定义的,因此不同的编译器可以以不同的方式对它们进行编码。例如,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/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值