3

我最近完成了 C 的大学课程。因此,我当然缺乏经验。

一些大学倾向于教他们的学生安全编程,或者至少教一些元素。甚至还有一段视频(取自这里)。

在 C 语言中,复制字符串需要 - 据我所知 - strcpy 或 string.h 函数。您如何在日常编程中安全地使用它?你有一些函数来处理分配以防止缓冲区溢出吗?有C 的 CERT 安全编码标准。它提供了示例和合规的解决方案:

int main(int argc, char *argv[]) {
  /* ... */
  char prog_name[128];
  strcpy(prog_name, argv[0]);
  /* ... */
}

他们的替代方案是:

int main(int argc, char *argv[]) {
  /* ... */
  char *prog_name = (char *)malloc(strlen(argv[0])+1);
  if (prog_name != NULL) {
    strcpy(prog_name, argv[0]);
  }
  else {
    /* Couldn't get the memory - recover */
  }
  /* ... */
}

取自这里,第二个例子

但据我所知,这只是更具挑战性、更多代码、更多工作。为什么没有人改变图书馆本身?或者至少为什么没有人提供安全的替代库或函数,以正确的方式处理这个问题?

感谢阅读,祝

4

7 回答 7

9

用于此的 Posix 函数(几乎在每个系统上都可用)是strdup(). strcpy()如果您不想分配新内存并且已经有一个要使用的缓冲区,则使用它,但是您会更好地知道该缓冲区有多大以及字符串是否适合它。如果您不知道字符串是否合适,那么strncpy()它只是复制给定数量的字符。因此,您可以将复制的数量限制为缓冲区大小。

除此之外,还有许多以不同方式管理字符串大小的 sting 库。

并且由于您将其标记为 C++:它std::string为您完成了所有的内存管理,并且不会给您带来这些问题。

于 2009-01-27T11:25:55.243 回答
2

使用strncpy

#define BUFSIZE 127
int main(int argc, char *argv[]) {
  /* ... */
  char prog_name[BUFSIZE + 1];
  strncpy(prog_name, argv[0], BUFSIZE);
  progname[BUFSIZE]= '\0';
  /* ... */
}

大多数功能都有*n*版本。str*

于 2009-01-27T11:27:24.320 回答
2

OpenBSD中的l (strlcpy, strlcat) 函数通常比n函数更好,它们更快更容易安全使用,但它们是非标准的。但是,它们是 BSD 许可的,因此您可以在任何程序中包含已知的良好实现,这样您就可以跨平台和安全。

对于 Windows,如果不关心可移植性,可以使用 *_s 函数。

于 2009-01-27T13:27:22.237 回答
1

如果我理解正确,你真正的问题是为什么 API 函数没有变得更安全。

原因之一是 C 库是遗留的(现在更改它为时已晚)。

然而,主要原因是该库被设计为极简主义,因此它只做最低限度的工作,并且用户有责任确保正确调用它。如果它进行了任何过多的检查,那么每次调用它都会付出代价,即使用户可以出于其他原因保证不会发生任何问题。这在许多 API 中非常常见。

话虽如此,有足够多的库可以提供更安全的替代方案,它们只是不是标准库的一部分。此外,许多从事更高级别工作的人使用 C++,其中有许多用于这些事情的标准类库。

于 2009-01-29T00:02:09.397 回答
0

实际上,Microsoft 确实提供了 CRT 功能的安全替代方案。我认识的每个人都讨厌它们,并禁用了你不应该使用旧功能的警告。如果你想要一些安全的东西,也许你应该使用 C++。然后是 STL 字符串或类似 Qt 的东西。

好吧,或者您使用 .NET 或 Java 之类的平台,它们通常不会遇到这些问题(您的应用程序可能会崩溃,但无法通过缓冲区溢出将代码注入您的应用程序)。

编辑:启用数据执行保护/NX(Vista 和 .NET 的默认设置),这对于传统平台也不应该是问题。

于 2009-01-27T11:19:32.010 回答
0
int main
(
    int argc, 
    char *argV[]
) 
{
   char prog_name[128];
   if (strlen(argV[0]) < sizeof(prog_name))
   {
       strcpy(prog_name, argV[0]);
   }
   else
   {
       printf("%s is too large for the internal buffer\n", argV[0]);
   }

   return 0;
}
于 2009-01-27T15:09:45.510 回答
0

也许你会找到这个问题的有用阅读答案

于 2009-01-28T23:45:54.283 回答