非确定性平凡C程序

非确定性平凡C程序,c,C,如果我在主函数中写了一些东西,下面的C程序会有不同的输出,我真的不明白为什么 如果我们对myVariable声明进行注释,则一切正常,并获得预期结果(将SHA256应用3次到0x12345678)。但是,如果我在main函数中写入任何内容,那么输出会发生变化,并且不会采用预期的值 声明一个新变量如何可能影响这一点 代码(precompute.c): #include <stdlib.h> #include <stdio.h> #include <string.h&g

如果我在主函数中写了一些东西,下面的C程序会有不同的输出,我真的不明白为什么

如果我们对myVariable声明进行注释,则一切正常,并获得预期结果(将SHA256应用3次到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;
}
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
#包括
#包括
#包括
#包括
无符号字符*sha256_3(整数*输入){
char*s=(char*)输入;
无符号字符*d=SHA256(s,strlen,0);
d=SHA256(d,strlen(d),0);
d=SHA256(d,strlen(d),0);
返回d;
}
无效打印散列(未签名字符*d){
int i;
对于(i=0;i
生成文件:

#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;
}
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
CC=gcc
CFLAGS=-c
LDFLAGS=-lssl-lcrypto
SOURCES=precompute.c
对象=$(源:.c=.o)
可执行文件=你好
全部:$(源)$(可执行)
$(可执行文件):$(对象)
$(CC)$(对象)-o$@$(LDFLAGS)
.c.o:
$(CC)$(CFLAGS)$<-o$@
清洁:
rm-rf*o你好
预期输出(myVariable的声明已注释):

8F3D8F8C5EFF23C137762220CF24F140B7A1B804CC2044261742FD73286C169

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

663E9571F713F83B19C913938E2947C8FC0A7072D1FC44385857C456C43295B


多谢各位

通过分析此片段:

char *s = (char*)input;
unsigned char *d = SHA256(s, strlen(s), 0);
几乎看不出有什么错误
input
最初是指向int的指针(由
inta
行定义)。int通常有4个字节。当您将指向它的指针强制转换为char*时,很好,您的指针指向一个4字节的分配内存。但是,string.h中的所有函数,包括strlen(),都依赖于字符串末尾是否存在NUL('\0')字符。基本上,strlen()计算NUL之前的字符数。由于int中的4个字节后没有NUL字符,因此结果基于内存中可以找到的内容(内存中可能有0,这是NUL字符的值,strlen停止)


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

您从未分配过任何空间。您只是在向随机内存(UB)写入数据,而且C中的这些行几乎没有任何意义。在同一个内存中读写,像原语一样反复向指针写入。这看起来不可赎回,只需重新开始。C字符串的长度由终止的空字符决定,因此
strlen(s)
是UB,因为
s
只是指向某个内存块