C++ 自定义编写的 strncpy 没有将所有字符填充为 null 是否安全?

C++ custom-written strncpy without padding all characters to null is it safe?

#include <iostream>
using namespace std;

struct Packet {
    int a;
    char b[17];
    int c;
};

// char* dest has form char dest[n], src has length <= n and is null-terminated
// After the function, dest should satisfy:
// - If strlen(src)==n, dest is not null terminated
// - If strlen(src) < n, dest[n-1] = dest[strlen(src)] = '[=10=]'
static void strncpy_faster(char* dest, const char* src, size_t n) {
    size_t i;
    for (i = 0; i < n; i++) {
      dest[i] = src[i];
      if (src[i] == '[=10=]')
        break;
    }
    //while (i < n) {dest[i] = '[=10=]'; i++;} // C standard strncpy do this
    if (i < n)
      dest[n - 1] = '[=10=]';
 }
 
 string charArrayToString(const char* a, size_t n) {
    size_t len = 0;
    while (len < n && a[len]!='[=10=]') len++;
    return std::string(a, a+len);
 }

int main()
{
    string s = "12341234123412345";
    Packet packet;
    
    strncpy_faster(packet.b, s.c_str(), 17);
    cout << charArrayToString(packet.b, sizeof(packet.b)) << "\n";
    
    s = "12345";
    strncpy_faster(packet.b, s.c_str(), 17);
    cout << charArrayToString(packet.b, sizeof(packet.b));
    return 0;
}

我正在处理具有固定大小 char 数组的结构。假设我真的非常想保持结构的大小(或者我需要通过网络发送它们),所以 std::string 没有在我的结构中使用(它花费 32 个字节,而我有多个大小为4-20).我有 2 个关于 strncpy 的问题:

所以,我的strncpy_faster最多只给'\0'分配了2个位置:数组的最后一个元素,以及strlen(src)的位置。由于 std::string() 需要一个以 null 结尾的字符数组 (NTCA),我使用 charArrayToString() 将非 NTCA 转换为字符串。

strncpy 这个版本安全吗?是否有任何 C/C++ 函数需要 strncpy'[=15=]' 填充所有剩余字节,或者它们只需要一个空终止符?我不知道为什么标准要求 strncpy 将剩余字节清零。

Is this version of strncpy safe?

是的。

它和 strncpy 一样安全。所以....不安全。

Are there any C/C++ functions that requires strncpy to fill all leftover bytes with '[=14=]', or do they only need a null terminator?

没有函数需要它。

来自 Linux 手册页的注释 man strcpy:

NOTES

Some programmers consider strncpy() to be inefficient and error prone. If the programmer knows (i.e., includes code to test!) that the size of dest is greater than the length of src, then strcpy() can be used.

One valid (and intended) use of strncpy() is to copy a C string to a fixed-length buffer while ensuring both that the buffer is not overflowed and that unused bytes in the destination buffer are zeroed out (perhaps to prevent information leaks if the buffer is to be written to media or transmitted to another process via an interprocess communication technique).

考虑使用(and/or 实施)strlcpy。记得关于 first rule of optimization.