GCC 9.4 编译 specified bound 255 equals destination size [-Werror=stringop-truncation]

前提

最近项目需要使用最新的 Ubuntu 20.04.4,查看下 编译器版本居然是 9.4.0,自然项目迁移过程中会有很多编译问题需要解决,毕竟之前的 gcc 版本都是 4.8.5的,差距很大。

环境

lm@lm:~$ cat /etc/os-release
NAME="Ubuntu"
VERSION="20.04.4 LTS (Focal Fossa)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 20.04.4 LTS"
VERSION_ID="20.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=focal
UBUNTU_CODENAME=focal



lm@lm:~$ gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/9/lto-wrapper
OFFLOAD_TARGET_NAMES=nvptx-none:hsa
OFFLOAD_TARGET_DEFAULT=1
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 9.4.0-1ubuntu1~20.04.1' --with-bugurl=file:///usr/share/doc/gcc-9/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++,gm2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-9 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-9-Av3uEd/gcc-9-9.4.0/debian/tmp-nvptx/usr,hsa --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 9.4.0 (Ubuntu 9.4.0-1ubuntu1~20.04.1)

编译问题

In function ‘char* strncpy(char*, const char*, size_t)’,
    inlined from ‘Agent::queryLocalData(std::string&, ResponseDataT&)’ at ./Agent/Agent.cc:715:14:
/usr/include/x86_64-linux-gnu/bits/string_fortified.h:106:34: error: ‘char* __builtin_strncpy(char*, const char*, long unsigned int)’ specified bound 255 equals destination size [-Werror=stringop-truncation]
  106 |   return __builtin___strncpy_chk (__dest, __src, __len, __bos (__dest));
      |          ~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cc1plus: all warnings being treated as errors

关键源码

部分关键源码如下:

710 const unsigned int NAME_LENGTH = 255;
712 char logicName[NAME_LENGTH];
713 std::string localFileData;
714 ......
715 strncpy(logicName, localFileData.c_str(), NAME_LENGTH);
716 ......

从编译错误可以很清晰的看出就是 strncpy() 这一行有问题。可以原来的 gcc 4.8.3 没有问题啊,而且貌似在 gcc 8.3 也没报错。都是这么使用的。

查看/usr/include/x86_64-linux-gnu/bits/string_fortified.h 文件对应的内容如下:

102 __fortify_function char *
103 __NTH (strncpy (char *__restrict __dest, const char *__restrict __src,
104 		size_t __len))
105 {
106   return __builtin___strncpy_chk (__dest, __src, __len, __bos (__dest));
107 }

寻找问题

查看gcc官网的编译选项:3 GCC Command Options

在其中的 3.1 Option Summary 中可以搜索到 -Wno-stringop-truncation 编译选项。顺藤摸瓜,进一步我们可以在 3.8 Options to Request or Suppress Warnings 查看到下面的描述:

-Wno-stringop-truncation

Do not warn for calls to bounded string manipulation functions such
as strncat, strncpy, and stpncpy that may either truncate the copied
string or leave the destination unchanged.

In the following example, the call to strncpy specifies the size of
the destination buffer as the bound. If the length of the source
string is equal to or greater than this size the result of the copy
will not be NUL-terminated. Therefore, the call is also diagnosed. To
avoid the warning, specify sizeof buf - 1 as the bound and set the
last element of the buffer to NUL.

下面是其中举的例子

void copy (const char *s)
{
  char buf[80];
  strncpy (buf, s, sizeof buf);}

其中关键字我这里已经做了加粗处理。即我们需要将最后一个字节做处理,手动给它赋值’\0’。

解决问题

通过编译选项我们知道了问题所在,那么接下来解决起来就很简单了。从上面的描述我们可以有下面两种解决办法:

方案一

我们通过将 strncpy 中长度改为小于目标缓冲区边界值,即将 lenght 调整为 sizeof(buf) -1 。修改后代码如下:

710 const unsigned int NAME_LENGTH = 255;
712 char logicName[NAME_LENGTH];
713 std::string localFileData;
714 ......
715 strncpy(logicName, localFileData.c_str(), sizeof(logicName)-1);
716 ......

方案二

我们不改变原来的代码,而是直接再添加一行代码,即,将缓冲区的最后一个元素设置为 NUL。修改后代码如下:

710 const unsigned int NAME_LENGTH = 255;
712 char logicName[NAME_LENGTH];
713 std::string localFileData;
714 ......
715 strncpy(logicName, localFileData.c_str(), NAME_LENGTH);
716 logicName[sizeof(logicName)-1] = '\0';
717 ......

通过验证,上面两种办法都是可以的,任选一种即可。

方案三

也可以通过忽略编译告警的方式,即通过在编译选项中添加 -Wno-error=stringop-truncation
具体方式为:

  1. 找到引起告警的产品代码源文件所在的makefile文件(或者cmake);
  2. 查看编译选项(一般是makefile文件)xx_xx_CPPFLAGS(x_xx是最终会生成的 lib 库)
  3. 添加或者追加编译选项 xx_xx_CPPFLAGS := -Wno-error=stringop-truncation
  4. 重新编译产品代码

当然,使用此种方案,会在编译的 log 中看到下面的提示信息:

In function ‘char* strncpy(char*, const char*, size_t)’,
    inlined from ‘Agent::queryLocalData(std::string&, ResponseDataT&)’ at ./Agent/Agent.cc:715:14:
/usr/include/x86_64-linux-gnu/bits/string_fortified.h:106:34: warning: ‘char* __builtin_strncpy(char*, const char*, long unsigned int)’ specified bound 255 equals destination size [-Wstringop-truncation]
  106 |   return __builtin___strncpy_chk (__dest, __src, __len, __bos (__dest));
      |          ~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

综上几种解决方案,建议优先考虑方案一和方案二。最后考虑方案三。

  • 9
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 8
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值