gcc-8 Wstringop 截断

3 c gcc strncpy gcc8

我正在尝试修复一些 gcc-8 抱怨 Wstringop-truncation 的 C 代码(代码在这里

\n\n

当在我无法控制的服务器上编译该代码时,既不能添加编译指示语句,也不能禁用 Wstringop-truncation 诊断,我收到的警告是:

\n\n
gcc-8  -I"/home/hornik/tmp/R/include" -DNDEBUG -I./cqdb/include -I./crf/src -I./liblbfgs/include -I./include -I"/home/hornik/lib/R/Library/3.6/x86_64-linux-gnu/Rcpp/include" -I/usr/local/include   -fpic  -g -O2 -Wall -pedantic -mtune=native -c cqdb/src/cqdb.c -o cqdb/src/cqdb.o\ncqdb/src/cqdb.c: In function \xe2\x80\x98cqdb_writer_close\xe2\x80\x99:\ncqdb/src/cqdb.c:270:5: warning: \xe2\x80\x98strncpy\xe2\x80\x99 output truncated before terminating nul copying 4 bytes from a string of the same length [-Wstringop-truncation]\n     strncpy((char*)header.chunkid, CHUNKID, 4);\n     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\ncqdb/src/cqdb.c: In function \xe2\x80\x98cqdb_reader\xe2\x80\x99:\ncqdb/src/cqdb.c:469:9: warning: \xe2\x80\x98strncpy\xe2\x80\x99 specified bound 4 equals destination size [-Wstringop-truncation]\n         strncpy((char*)db->header.chunkid, (const char*)p, 4);\n         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n
Run Code Online (Sandbox Code Playgroud)\n\n

我想重写 strncpy 语句以删除这些警告。我是否正确,我需要替换以下几行

\n\n
strncpy((char*)header.chunkid, CHUNKID, 4);\nwith strncpy((char*)header.chunkid, CHUNKID, 5);\n\nand strncpy((char*)db->header.chunkid, (const char*)p, 4);\nwith strncpy((char*)db->header.chunkid, (const char*)p, 5);\n
Run Code Online (Sandbox Code Playgroud)\n\n

下面是cqdb.c中的相关代码。它主要检查文件是否属于“CQDB”类型。\n标记一下,虽然我真的很想能够访问,但我无权访问这台机器,因此我无法测试 C 代码的修复是否有效。

\n\n
#define CHUNKID             "CQDB"\n\ntypedef struct {\n    int8_t      chunkid[4]; /**< Chunk identifier, "CQDB". */\n    uint32_t    size;       /**< Chunk size including this header. */\n    uint32_t    flag;       /**< Global flags. */\n    uint32_t    byteorder;  /**< Byte-order indicator. */\n    uint32_t    bwd_size;   /**< Number of elements in the backward array. */\n    uint32_t    bwd_offset; /**< Offset to the backward array. */\n} header_t;\n\nint cqdb_writer_close(cqdb_writer_t* dbw)\n{\nheader_t header;\nstrncpy((char*)header.chunkid, CHUNKID, 4);\n...\n}\n\ncqdb_t* cqdb_reader(const void *buffer, size_t size)\n{\n    cqdb_t* db = NULL;\n    /* Check the file chunkid. */\n    if (memcmp(buffer, CHUNKID, 4) != 0) {\n        return NULL;\n    }\n    db = (cqdb_t*)calloc(1, sizeof(cqdb_t));\n    const uint8_t* p = NULL;\n    db->buffer = buffer;\n    p = db->buffer;\n    strncpy((char*)db->header.chunkid, (const char*)p, 4);\n...\n}\n
Run Code Online (Sandbox Code Playgroud)\n

M.M*_*M.M 7

问题中的用法strncpy实际上是正确的(左对齐缓冲区中的某些字符,右填充空字节),但警告是因为尝试复制空终止字符串的人经常滥用此函数。

对于问题中显示的代码,我会将调用替换strncpy为:

set_chunkid(&header);
Run Code Online (Sandbox Code Playgroud)

在其中添加新函数:

void set_chunkid(header_t *hdr)
{
    _Static_assert(sizeof CHUNKID == sizeof hdr->chunkid + 1, "chunk ID not 4 chars");

    memcpy(&hdr->chunkid, CHUNKID, sizeof hdr->chunkid);
}
Run Code Online (Sandbox Code Playgroud)

如果此功能未涵盖其他用例,请更新问题。