strncpy 被替换为 __strncpy_chk 并失败

strncpy is replaced by __strncpy_chk and fails

我有一个说法

strncpy(&data->m_bin->data,versionStr,data->m_bin->sizeData);

在我的应用程序中,它本身很好并且运行良好。这里的 data->m_bin->data 是一个字符,调用应用程序确保它后面跟着一个数据块,该数据块足够大以保存 strncpy() 传递的所有数据。

但是当我使用 GCC/Linux 将其构建为发行版时,此函数在 __strncpy_chk() 中崩溃。所以我的 strncpy() 似乎被 __strncpy_chk() 替换了,参数 s1 的长度错误。

那么如何确保 __strncpy_chk() 被调用时 s1 的长度正确?

谢谢!

strncpy(&data->m_bin->data,versionStr,data->m_bin->sizeData);

address of 操作员在我看来很可疑。我希望是这样的:

strncpy(data->m_bin->data,versionStr,data->m_bin->sizeData);

或者也许:

strncpy(&data->m_bin->data[0],versionStr,data->m_bin->sizeData);

how can I ensure __strncpy_chk() is called with the correct length for s1?

嗯,你不能本身。这是 FORTIFY_SOURCE 和对象大小检查的一部分,目标缓冲区大小在编译器可以推断出来时使用。

假设 data 是一个大小为 sizeData.

的数组,您可以执行如下操作
/* avoid undefined behavior */
ASSERT(data->m_bin->data != NULL);
ASSERT(versionStr != NULL);
ASSERT(data->m_bin->sizeData > 0);

size_t l1 = data->m_bin->sizeData;
size_t l2 = strlen(versionStr);

/* min function */
size_t len = l1 < l2 ? l1 : l2;

/* if versionStr is shorter than len, then data will be backfilled */
strncpy(data->m_bin->data, versionStr, len);

/* NULL terminate, even if it truncates */
data->m_bin->data[data->m_bin->sizeData-1] = '[=12=]';

您可能应该使用 -Wall 打开警告。我怀疑你应该得到一个使用 address of 运算符的。

Here data->m_bin->data is a char where the calling application ensures it is followed by a datablock which is large enough to keep all the data handed over by strncpy().

这导致有效的 C 程序是不寻常的。指针出处规则通常意味着这会导致未定义的行为。

如果 char 位于结构的末尾,则可以使用灵活的数组成员,使编译器更清楚其意图。

如果您不想更改源代码,可以使用-U_FORTIFY_SOURCE-D_FORTIFY_SOURCE=0 进行编译。这将禁止用强化版本替换 strncpy