如何更安全地编写这个C 片段?

发布于 2024-07-20 21:26:46 字数 490 浏览 15 评论 0原文

我有以下 C 代码片段,必须识别错误并建议一种更安全的编写方法:

char somestring[] = "Send money!\n";
char *copy;

copy = (char *) malloc(strlen(somestring));

strcpy(copy, somestring);
printf(copy);

所以错误是 strlen 忽略了字符串的尾部 '\0' ,因此它是不会为副本分配足够的内存,但我不确定他们如何更安全地编写副本?

我认为我可以使用 malloc(strlen(somestring)+1)) 但我想一定有比这更好的方法吗?


编辑:好的,我已经接受了答案,我怀疑我们不会期望 strdup 解决方案,因为它不是 ANSI C 的一部分。这似乎是一个相当主观的问题,所以我不确定我所接受的是否真的是最好的。 无论如何,感谢所有的答案。

I have the following C code fragment and have to identify the error and suggest a way of writing it more safely:

char somestring[] = "Send money!\n";
char *copy;

copy = (char *) malloc(strlen(somestring));

strcpy(copy, somestring);
printf(copy);

So the error is that strlen ignores the trailing '\0' of a string and therefore it is not going to be allocated enough memory for the copy but I'm not sure what they're getting at about writing it more safely?

I could just use malloc(strlen(somestring)+1)) I assume but I'm thinking there must be a better way than that?


EDIT: OK, I've accepted an answer, I suspect that the strdup solution would not be expected from us as it's not part of ANSI C. It seems to be quite a subjective question so I'm not sure if what I've accepted is actually the best. Thanks anyway for all the answers.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

如梦初醒的夏天 2024-07-27 21:26:47

使代码更安全(并且更正确)的方法。

  1. 不要制作不必要的副本。 从该示例来看,没有明显的要求您实际上需要复制 somestring。 直接输出即可。
  2. 如果您必须复制字符串,请编写一个函数来完成它(或者使用 strdup,如果有的话)。 然后你只需在一处做对就可以了。
  3. 只要有可能,在声明时立即初始化指向副本的指针。
  4. 请记住为空终止符分配空间。
  5. 请记住检查 malloc 的返回值。
  6. 请记住释放malloc的内存。
  7. 不要使用不受信任的格式字符串调用 printf。 使用 printf("%s", copy)puts(copy)
  8. 使用具有字符串类的面向对象语言或任何具有内置字符串支持的语言可以避免大多数此类问题。

Ways to make the code safer (and more correct).

  1. Don't make an unnecessary copy. From the example, there's no apparent requirement that you actually need to copy somestring. You can output it directly.
  2. If you have to make a copy of a string, write a function to do it (or use strdup if you have it). Then you only have to get it right in one place.
  3. Whenever possible, initialize the pointer to the copy immediately when you declare it.
  4. Remember to allocate space for the null terminator.
  5. Remember to check the return value from malloc.
  6. Remember to free the malloc'ed memory.
  7. Don't call printf with an untrusted format string. Use printf("%s", copy) or puts(copy).
  8. Use an object-oriented language with a string class or any language with built-in string support to avoid most of these problems.
标点 2024-07-27 21:26:47

如果一个人真正对这样的事情感兴趣,那么更安全地编写它的最好方法就是用 Ada 编写它。

somestring : constant string := "Send money!";
declare
   copy : constant string := somestring;
begin
   put_line (somestring);
end;

结果一样,那么有什么区别呢?

  • 整个事情都是在堆栈上完成的
    (没有指针)。 解除分配是
    自动且安全。
  • 一切都会自动进行范围检查,因此
    不可能出现缓冲区溢出
    两个字符串都是
  • 常量,
    所以没有机会搞砸
    并修改它们。
  • 它可能比 C 快得多,不仅因为缺乏动态分配,而且因为不需要对 strlen() 所需的字符串进行额外的扫描。

请注意,在 Ada 中,“字符串”并不是某种特殊的动态构造。 它是内置的字符数组。 但是,Ada 数组可以在声明时根据您分配给它们的数组来调整大小。

The best way to write it more safely, if one were to be truly interested in such a thing, would be to write it in Ada.

somestring : constant string := "Send money!";
declare
   copy : constant string := somestring;
begin
   put_line (somestring);
end;

Same result, so what are the differences?

  • The whole thing is done on the stack
    (no pointers). Deallocation is
    automatic and safe.
  • Everything is automaticly range-checked so
    there's no chance of buffer-overflow
    exploits
  • Both strings are constants,
    so there's no chance of screwing up
    and modifying them.
  • It will probably be way faster than the C, not only because of the lack of dynamic allocation, but because there isn't that extra scan through the string required by strlen().

Note that in Ada "string" is not some special dynamic construct. It's the built-in array of characters. However, Ada arrays can be sized at declaration by the array you assign into them.

鲸落 2024-07-27 21:26:47

更安全的方法是使用 strncpy 而不是 strcpy。 该函数采用第三个参数:要复制的字符串的长度。 该解决方案不会超出 ANSI C,因此这将在所有环境下工作(而其他方法可能仅在符合 POSIX 标准的系统下工作)。

char somestring[] = "Send money!\n";
char *copy;

copy = (char *) malloc(strlen(somestring));

strncpy(copy, somestring, strlen(somestring));
printf(copy);

The safer way would be to use strncpy instead of strcpy. That function takes a third argument: the length of the string to copy. This solution doesn't stretch beyond ANSI C, so this will work under all environments (whereas other methods may only work under POSIX-compliant systems).

char somestring[] = "Send money!\n";
char *copy;

copy = (char *) malloc(strlen(somestring));

strncpy(copy, somestring, strlen(somestring));
printf(copy);
花辞树 2024-07-27 21:26:46

我无法对上面的回复发表评论,但除了检查
返回代码并使用 strncpy,你永远不应该这样做:

printf(string)

但使用:

printf("%s", string);

ref: http ://en.wikipedia.org/wiki/Format_string_attack

I can't comment on the responses above, but in addition to checking the
return code and using strncpy, you should never do:

printf(string)

But use:

printf("%s", string);

ref: http://en.wikipedia.org/wiki/Format_string_attack

月亮邮递员 2024-07-27 21:26:46
char somestring[] = "Send money!\n";
char *copy = strdup(something);

if (copy == NULL) {
    // error
}

或者只是将此逻辑放入单独的函数xstrdup中:

char * xstrdup(const char *src) 
{
    char *copy = strdup(src);

    if (copy == NULL) {
       abort();
    }

    return copy;
}
char somestring[] = "Send money!\n";
char *copy = strdup(something);

if (copy == NULL) {
    // error
}

or just put this logic in a separate function xstrdup:

char * xstrdup(const char *src) 
{
    char *copy = strdup(src);

    if (copy == NULL) {
       abort();
    }

    return copy;
}
一百个冬季 2024-07-27 21:26:46
char   somestring[] = "Send money!\n";
char   *copy;
size_t copysize;

copysize = strlen(somestring)+1;
copy = (char *) malloc(copysize);
if (copy == NULL)
    bail("Oh noes!\n");

strncpy(copy, somestring, copysize);
printf("%s", copy);

注意上面的差异:

  • 必须检查 malloc() 的结果!
  • 计算并存储内存大小!
  • 使用 strncpy() 因为 strcpy() 很顽皮。 在这个人为的例子中,它不会造成伤害,但不要养成使用它的习惯。

编辑:

对于那些认为我应该使用strdup()的人...只有当您对问题采取最狭隘的看法时才有效。 这不仅愚蠢,而且忽视了一个更好的答案:

char somestring[] = "Send money!\n";
char *copy = somestring;
printf(copy);

如果你要变得迟钝,至少要擅长它。

char   somestring[] = "Send money!\n";
char   *copy;
size_t copysize;

copysize = strlen(somestring)+1;
copy = (char *) malloc(copysize);
if (copy == NULL)
    bail("Oh noes!\n");

strncpy(copy, somestring, copysize);
printf("%s", copy);

Noted differences above:

  • Result of malloc() must be checked!
  • Compute and store the memory size!
  • Use strncpy() because strcpy() is naughty. In this contrived example it won't hurt, but don't get into the habit of using it.

EDIT:

To those thinking I should be using strdup()... that only works if you take the very narrowest view of the question. That's not only silly, it's overlooking an even better answer:

char somestring[] = "Send money!\n";
char *copy = somestring;
printf(copy);

If you're going to be obtuse, at least be good at it.

眉目亦如画i 2024-07-27 21:26:46
  1. strlen + 1,对于\0终止符
  2. malloc可能会失败; 总是检查 malloc 返回值
  1. strlen + 1, for the \0 terminator
  2. malloc may fail; always check malloc return value
π浅易 2024-07-27 21:26:46

哎呀...像其他人所说的那样使用 strdup() 并在必要时自己编写。 既然您现在有时间考虑这个问题...请查看 25 Mitre 上最危险的编程错误,然后考虑为什么短语 printf(copy) 不应该永远出现在代码中。 就彻底的糟糕性而言,这与 malloc(strlen(str)) 不相上下,更不用说当复制类似于 "%s 时,追踪为什么它会引起很多悲伤的头痛。 %n"...

Ick... use strdup() like everyone else said and write it yourself if you have to. Since you have time to think about this now... check out the 25 Most Dangerous Programming Errors at Mitre, then consider why the phrase printf(copy) should never appear in code. That is right up there with malloc(strlen(str)) in terms of utter badness not to mention the headache of tracking down why it causes lots of grief when copy is something like "%s%n"...

梦归所梦 2024-07-27 21:26:46

我会对以前的解决方案发表评论,但我没有足够的代表。
在这里使用 strncpy 与使用 strcpy 一样错误(因为绝对没有溢出风险)。 中有一个名为memcpy的函数 string.h > 正是为此而设计的。 它不仅速度明显更快,而且是用于复制标准 C 中已知长度字符串的正确函数。

从已接受的答案来看:

char   somestring[] = "Send money!\n";
char   *copy;
size_t copysize;

copysize = strlen(somestring)+1;
copy = (char *) malloc(copysize);
if (copy == NULL)
    bail("Oh noes!\n");

memcpy(copy, somestring, copysize); /* You don't use str* functions for this! */
printf("%s", copy);

I would comment to previous solutions but I do not have enough rep.
Using strncpy here is as wrong as using strcpy(As there is absolutely no risk of overflow). There is a function called memcpy in < string.h > and it is meant exactly for this. It is not only significantly faster, but also the correct function to use to copy strings of known length in standard C.

From the accepted answer:

char   somestring[] = "Send money!\n";
char   *copy;
size_t copysize;

copysize = strlen(somestring)+1;
copy = (char *) malloc(copysize);
if (copy == NULL)
    bail("Oh noes!\n");

memcpy(copy, somestring, copysize); /* You don't use str* functions for this! */
printf("%s", copy);
土豪我们做朋友吧 2024-07-27 21:26:46

为了添加更多 Adrian McCarthy 的方法来制作更安全的代码,

请使用静态代码分析器,他们非常擅长发现此类错误

to add more to Adrian McCarthy's ways to make safer code,

Use a static code analyzer, they are very good at finding this kind of errors

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文