c - 这段代码是否是整数溢出

标签 c

我在某处看到这段代码,这不是整数溢出和未定义行为吗?

假设0 < str[i] < 127

char *msl_decrypt(char *str) {
    char *decrypted;
    unsigned int i;
    int key = 0xFACA;

    for (i = 0; i < strlen(str); ++i) {
        str[i] = str[i] + key; // referring to this line, is it UB?
    }
    ...

最佳答案

很遗憾您没有指定目标参数。所以对于以下我假设:

  • CHAR_BIT == 8
  • sizeof(int) >= 2
  • 不是填充位
  • str 指向有效且已初始化的内存,该内存正确地以 nul 结尾且不大于 INT_MAX(或者使用 size_t 索引 - 感谢@chux)。
  • 可能还有其他我们倾向于视为理所当然的先决条件。

这些对于大多数现代实现来说都是典型的。

对于 sizeof(int) == 2,初始化器是实现定义的行为,因为您使用 unsigned int 常量作为初始化器。对于更宽的 int 这没问题。如果 (int)(0xFACA) + CHAR_MAX > INT_MAX(在算术上,也仅与 2 字节 int 相关),事情也会变得更加复杂。

其余部分以更复杂的方式依赖于实现定义的行为:

1)加法str[i] + key:这里先将str[i]转为int,加法完成作为 int 并产生 int 结果。

2) 赋值str[i] = ...:这里将加法的int结果转换为char。为此,我们有两种变体,具体取决于 char 的符号性(实现定义):

  • unsigned:结果以标准定义的方式转换为 unsigned char
  • signed:结果以实现定义的方式“向下”转换为“更小的”signed char

因此:没有 未定义的行为,但这(和评论)表明在 C 中使用有符号整数时必须牢记多少。


但是:

涉及太多实现定义的行为,并且需要很多先决条件(尽管这很常见)。最好在整个代码中使用 unsigned charunsigned int。这将使代码符合标准并表现良好。即使对于 CHAR_BIT 值以外的值。如果您依赖 8 位值,请使用 stdint.h 中的 uint8_t

关于c - 这段代码是否是整数溢出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35350045/

相关文章:

更改 GtkLabel 前景色

c - 在 Swift 中读取二进制 (.hgt) 文件(将代码从 C++ 迁移到 swift)

在二进制文件中找不到 .dtors 和 .ctors

c - 为什么 arr[1] 打印的内容看起来像是 arr[0] ?

c - 这行代码在 Kilobot 示例中起什么作用?

c - 检索函数中的指针

c - 从串行端口读取总是返回写入的内容

c - 为什么这个程序会产生运行时错误?

c - C 中使用指针的 for 循环声明

C 编程循环不会因 scanf!=0 而停止