【发布时间】:2014-01-18 21:45:47
【问题描述】:
我正在学习 C 并阅读 Learn C The Hard Way (ISBN-10: 0-321-88492-2)。我被困在练习 17“如何打破它”上。
这是书中的问题:
由于strncpy不好,这个程序有一个bug 设计的。去阅读有关 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 更改为:
char name2[] = {
'a', 's', 't',
'r', 'i', 'n', 'g', '\0'
};
或者,在 strncpy 函数调用上方添加以下行
names2[sizeof(names2)-1] = '\0';
【问题讨论】:
-
这太笼统了。显示一些代码。
-
传入大量字节与传入少量字节相同,只是更大:)
-
我写过关于
strncpy()here的文章。 -
我会要求退款。在函数
Database_set:char *res = strncpy(...); // demonstrate the strncpy bug if(!res) die("Name copy failed");。strncpy从不返回 NULL,它总是返回目标指针。 -
我已经包含了我正在处理的函数。 @NigelHarper 所以我可以传入一个非常长的字符串,它会大于 512 字节吗?对不起,我非常靠近 C!
标签: c