非确定性的琐碎C程序

时间:2014-04-21 14:12:34

标签: c

如果我在main函数中写了一些东西,并且我真的不明白为什么......以下C程序有不同的输出。

如果我们评论myVariable声明,一切都很好,我们得到期望的结果(应用3次SHA256到0x12345678)。但是,如果我在main函数中写入任何内容,则输出会更改并且不会获取预期值。

声明一个新变量如何影响这个?

代码(precompute.c):

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include <openssl/sha.h>

unsigned char* sha256_3(int* input) {
    char *s = (char*)input;
    unsigned char *d = SHA256(s, strlen(s), 0);
    d = SHA256(d, strlen(d), 0);
    d = SHA256(d, strlen(d), 0);

    return d;
}

void print_hash(unsigned char* d) {
    int i;
    for (i = 0; i < SHA256_DIGEST_LENGTH; i++)
        printf("%02x", d[i]);
    putchar('\n');
}

int main(int argc, const char * argv[]) {
    int A = 0x12345678;
    unsigned char *B = sha256_3(&A);
    print_hash(B);

    // int myVariable = 3; // Uncomment this line and recompile to see the difference

    return EXIT_SUCCESS;
}

Makefile:

CC=gcc
CFLAGS=-c
LDFLAGS=-lssl -lcrypto
SOURCES=precompute.c
OBJECTS=$(SOURCES:.c=.o)
EXECUTABLE=hello

all: $(SOURCES) $(EXECUTABLE)

$(EXECUTABLE): $(OBJECTS) 
    $(CC) $(OBJECTS) -o $@ $(LDFLAGS)

.c .o:
    $(CC) $(CFLAGS) $< -o $@

clean:
    rm -rf *o hello

预期输出(myVariable的声明评论):

  

8f3d8f8c5eff23dc137762220cf24f140b7a1b804cc2044261742fd73286c169

意外输出(myvariable的声明未注释):

  

663e9571f713f83b19c913938e2947c8fc0a7072d1fc442385857c456c43295b

非常感谢!

1 个答案:

答案 0 :(得分:0)

通过分析此片段:

char *s = (char*)input;
unsigned char *d = SHA256(s, strlen(s), 0);

可以看到很少的错误。 input最初是指向int的指针(由int A行定义)。 int通常有4个字节。当你将指向它的指针转换为char *时,你的指针指向一个4字节的已分配内存。但是,string.h中的所有函数(包括strlen())都依赖于字符串末尾的NUL(&#39; \ 0&#39;)字符。基本上,strlen()计算NUL之前有多少个字符。因为你没有在int的4个字节之后有一个NUL字符,结果是基于在内存中可以找到的内容(某处可能是内存中的0,这是NUL字符的值,而strlen停止)。

现在,为了解决这个问题,你有两种可能的解决方案:从头开始用你需要的值创建一个字符串,或者在sha256_3函数中创建一个5字节的字符串,从提供的int中复制4个字符串参数并将NUL分配给最后一个。