C 添加未使用变量的随机行为
我真的不知道如何命名这个问题,问题是我在下面的代码中看到了一些严重的魔法 在这里,我放置了所有相关的代码片段及其输出C 添加未使用变量的随机行为,c,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);
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);
}
这个随机文件描述符的值丢失了,这是怎么回事?由于他随机将其值更改为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);
}
我希望有人能解释一下幕后发生的事情。因为对我来说,这似乎是一种相当黑暗的魔法,就在那里。我怀疑有什么可疑的'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;
}
}
void sha2hexf(无符号字符*extuf,无符号字符*hash){
int i;
对于(i=0;i<32;i++){
sprintf((char*)exputf,“%.2x”,散列[i]);
f+=2;
}
}
有什么真正的解释吗?您的函数
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).
sha2hexf正在跨越extuf的边界(也称为block_fname),因为sprintf在每个循环中都附加了“\0”(您可以通过增加extuf来处理它,但不是在最后一次循环运行中!)。
因此,您需要的缓冲区可以容纳65个字符。如果您的书写超出了您的边界,那么可能会出现奇怪而奇妙的行为。通过valgrind运行您的程序[并发布更多代码]非常感谢!监督这件事太愚蠢了。
void sha2hexf(unsigned char *outbuf, unsigned char *hash) {
int i;
for (i = 0; i < 32; i++) {
sprintf((char*)outbuf, "%.2x", hash[i]);
outbuf += 2;
}
}
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).