随机行为添加未使用的变量

时间:2013-11-23 23:20:00

标签: c

我真的不知道如何标题,问题是我在下面的代码中看到了一些严肃的魔法。

这里我把所有相关的代码片段及其输出。

void persist_receipt(Receipt * receipt, char * path)
{
    int i, fd;
    unsigned char block_fname[64];

    fd = open( ".receipt", O_RDWR | O_CREAT, 0777);
    printf("1.fd=%i\n", fd);
    // Write receipt header
    write(fd, receipt->hash, 32);
    write(fd, receipt->name, 256);
    write(fd, &receipt->size, sizeof(int));

    printf("2.fd=%i\n", fd);

    for(i=0; i<receipt->size; i++)
    {
            printf("3.fd=%i\n", fd);
            sha2hexf(block_fname, receipt->blocks[i].hash);
            printf("4.fd=%i\n", fd);
            write(fd, block_fname, 64);
    }

    close(fd);
}

现在让我告诉你这段代码的输出:

1.fd=4
2.fd=4
3.fd=4
4.fd=0
85a2c67fe7f3dc586a0f231d0cc845e7094408769c8391da18d1ed35c7b1cb3c3.fd=0
4.fd=0
cbc6286fedb70a703f403e507e4daca7bb4a493cdd4d0f0c1787e56256afe5fd3.fd=0
4.fd=0
c364417c27bd887142e6c2de1f7a5b777d604c9df8bcd40bb1a20623b38de82b3.fd=0

这个随机文件描述符失去了它的价值是怎么回事?由于他随机将其值转换为0,它会向控制台输出散列值,但它不应该发生!

这是有趣的部分!如果我只声明一个新变量。假设我声明一个新的整数:

void persist_receipt(Receipt * receipt, char * path)
{
    int i, fd, p;
    unsigned char block_fname[64];

    fd = open( ".receipt", O_RDWR | O_CREAT, 0777);
    printf("1.fd=%i\n", fd);
    // Write receipt header
    write(fd, receipt->hash, 32);
    write(fd, receipt->name, 256);
    write(fd, &receipt->size, sizeof(int));

    printf("2.fd=%i\n", fd);

    for(i=0; i<receipt->size; i++)
    {
            printf("3.fd=%i\n", fd);
            sha2hexf(block_fname, receipt->blocks[i].hash);
            printf("4.fd=%i\n", fd);
            write(fd, block_fname, 64);
    }

    close(fd);
}

如你所见,现在我宣布了一个'p'变量,让我们再次编译并运行它,哦,男孩。

1.fd=4
2.fd=4
3.fd=4
4.fd=4
3.fd=4
4.fd=4
3.fd=4
4.fd=4
3.fd=4
4.fd=4
...

我希望有人能够解释幕后发生的事情。因为这对我来说似乎是一种非常黑暗的魔法,就在那里。我怀疑有一些可疑的'sha2hexf'功能,所以在这里我也放了代码,特别是可疑部分是内部的sprintf调用。

void sha2hexf(unsigned char *outbuf, unsigned char *hash) {
int i;
    for (i = 0; i < 32; i++) {
        sprintf((char*)outbuf, "%.2x", hash[i]);
        outbuf += 2;
    }
}

有真正的解释吗?

2 个答案:

答案 0 :(得分:1)

你的函数sha2hexf显然超出了你传入的缓冲区。它是空的 - 终止64字节的字符串(所以你需要缓冲区中至少65个字节)。

编译器经常反向布局堆栈,所以你会得到:

block_fname (64 bytes) | fd (4 bytes) | i (4 bytes)

                         ^ Overflow hits the first byte of 'fd', which zeros it
                           a little-endian architecture (if fd less than 256).

答案 1 :(得分:1)

sha2hexf正在写outbuf的边界(又名block_fname),因为sprintf在每个循环中附加“\ 0”(你通过递增outbuf来处理,但不是在最后一次循环运行!)。 所以你需要的缓冲区占65个字符。