我正在学习 C 并阅读《Learn C The Hard Way》(ISBN-10:0-321-88492-2)。我被困在练习 17“如何打破它”上。
这是书上的问题:
由于 strncpy 性能不佳,该程序存在错误
设计的。去阅读有关 strncpy 的内容,然后尝试找出当
您提供的名称或地址大于 512 字节。通过以下方式修复此问题
只需将最后一个字符强制为 '\0',以便它始终设置为 no
不管怎样(这就是 strncpy 应该做的)。
我已经阅读了一些关于 strncpy 的文章,我知道它是不安全的,因为它不会在字符串末尾添加空字节。但是,我不知道如何向函数传递大量字节,也不知道如何解决空字节问题。
下面是使用 strncpy 的函数,MAX_DATA
设置为 512。
void Database_set(struct Connection *conn, int id, const char *name, const char *email)
{
struct Address *addr = &conn->db->rows[id];
if(addr->set) die("Already set, delete it first");
addr->set = 1;
// WARNING: bug, read the "How To Break It" and fix this
char *res = strncpy(addr->name, name, MAX_DATA);
// demonstrate the strncpy bug
if(!res) die("Name copy failed");
res = strncpy(addr->email, email, MAX_DATA);
if(!res) die("Email copy failed");
}
如何打破它 - 编辑
下面是如何破解 strncpy 的示例:
void Database_set(struct Connection *conn, int id, const char *name, const char *email)
{
struct Address *addr = &conn->db->rows[id];
if(addr->set) die("Already set, delete it first");
addr->set = 1;
// WARNING: bug, read the "How To Break It" and fix this
char name2[] = {
'a', 's', 't',
'r', 'i', 'n', 'g'
};
char *res = strncpy(addr->name, name2, MAX_DATA);
// demonstrate the strncpy bug
if(!res) die("Name copy failed");
res = strncpy(addr->email, email, MAX_DATA);
if(!res) die("Email copy failed");
}
要修复此问题,请在字符串末尾添加一个空字节。改变name2
to be:
char name2[] = {
'a', 's', 't',
'r', 'i', 'n', 'g', '\0'
};
或者,在 strncpy 函数调用上方添加以下行
names2[sizeof(names2)-1] = '\0';