SHA_256 functions corrupting memory space - c

I've been trying to use the SHA_256 functions in sha256.h on a FreeBSD 9.1 system but it seems to be corrupting memory space of my program causing all kinds of manic behavior. I wrote up a quick program to just to play with those functions and still am having problems.
In the example below, int i is changed when I call SHA256_Init(), as shown by the output from the printf() statements surrounding it.
This is what I get running the code.
$ ./miner "hello world"
i = 0
i = 32
0000000032 9010a9cf81ce2c28a642fd03ddf6da5790c65c30cd4a148c4257d3fe488bacc7
Why is this value changing to 32? Am I missing something? The code is below...
#include <sha256.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#define DIFFICULTY 0
int main(int argc, const char **argv) {
uint nonce, i, j;
SHA256_CTX ctx;
size_t arglen;
unsigned char digest[32];
char * data;
if(argc < 1) exit(1);
arglen = strlen(argv[1]);
data = malloc(arglen + 1);
char digestStr[65];
i = 0;
do {
nonce = i;
strncpy(data, argv[1], arglen + 1);
printf("i = %i\n", i);
SHA256_Init(&ctx);
printf("i = %i\n", i);
SHA256_Update(&ctx, data, arglen);
SHA256_Update(&ctx, (unsigned char *) &nonce, sizeof(nonce));
SHA256_Final(digest, &ctx);
SHA256_End(&ctx, digestStr);
printf("%010i\t%s\n", i, digestStr);
j = 0;
while(j < 32 && digest[j] == '\0') {
j++;
}
i++;
} while(j < DIFFICULTY);
free(data);
return 0;
}

I just had this exact same problem and solved it.
The issue is that your are including a different header in your code than the SHA2 library you linked into your application is using.
In my case the SHA256_CTX struct was a different size in the openSSL library. The openSSL library's struct was 8 bytes bigger than the struct length in the file.
The function SHA256_Init(&ctx) does a memset on the SHA256_CTX struct which then corrupts 8 extra random bytes after the struct. I say random because it will do different things in a release vs debug build because the optimizing compiler will move your variables around.

Related

why malloc yields error after long argv arguments?

I have written a program where it reads some filenames and a word from command line arguments. The first argument will be a word and remaining will be filenames. It fills a structure that I have defined.
However for small arguments, the program works correctly but for large ones malloc gives corrupted top size error.
Below is just initial code of the program:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define FILENAME_LIM 256
#define WORD_LIM 256
struct data {
char filename[FILENAME_LIM];
char word[WORD_LIM];
};
int main(int argc, char *argv[]) {
if (argc < 3) {
printf("usage: ./a.out word filename1 filename2 filename3 filename4 filename5 ...\n");
exit(EXIT_FAILURE);
}
char word[WORD_LIM];
strcpy(word, argv[1]);
int files = argc - 2;
struct data *dataarray = (struct data *)malloc(sizeof(sizeof(struct data) * files));
if (!(dataarray)) {
perror("malloc");
exit(EXIT_FAILURE);
}
for (int i = 0; i < files; i++) {
strcpy(dataarray[i].filename, argv[i + 2]);
for (int ii = 0; ii < strlen(dataarray[i].filename) + 1; ii++) {
printf("filename[%d] = %c (%d), argv[%d] = %d\n",
i, dataarray[i].filename[ii], dataarray[i].filename[ii],
i, argv[i + 2][ii]);
}
}
return 0;
}
I tried everything, but when I give some large filename in argv such as "../../../C Programs/chess.c", malloc yields an error. I want to know what is making corrupted top size.
sizeof(struct data) * files
is a valid size. Any multiple of a size is a size.
sizeof(sizeof(struct data) * files)
is like saying sizeof(23422). I don't know what that means, and odds are the runtime isn't behaving properly either.
Restrict your use of sizeof(...) to processing type arguments.

C: sha256 hash function outputs in fields of structure array inducing crash when writing structure contents to disk

I am attempting to write a program which will store credential information in an array of structures and then print that information out into a file (this is for learning purposes only, don't worry). To do this, I create an array of structures and then raster through that array to assign the pertinent information to each field. This proceeds without issue. I then attempt to raster through the array again to write each structure's fields to a file whereupon the program crashes after the first write (ie only one structure's worth of content is successfully written to the output file).
I created the following simplified / stripped down variant of my program which reproduces the error. I believe the problem lies within the set_hash_entry function as the error only manifested after that function was re-introduced into my stripped down code in place of a hard coded test value.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "openssl/sha.h"
#include <time.h>
#include <math.h>
struct password_struct {
char password[17];
char hash[65];
float entropy;
};
struct password_struct* allocate_heap_memory(int num_passwords);
void orchestrate_value_setting(int num_passwords, struct password_struct* user_password_structs);
void orchestrate_file_output(int num_passwords, struct password_struct* user_password_structs);
void write_results_to_disk(char file_name[], struct password_struct* user_password_structs);
void set_hash_entry(struct password_struct* user_password_structs);
int main(void) {
int num_passwords = 2;
struct password_struct* user_password_structs = allocate_heap_memory(num_passwords);
struct password_struct* allocated_memory_start_ptr = user_password_structs;
orchestrate_value_setting(num_passwords, user_password_structs);
user_password_structs = allocated_memory_start_ptr; // Resetting pointer to allow cycling back through all structures for appending data to output file
orchestrate_file_output(num_passwords, user_password_structs);
free(allocated_memory_start_ptr);
}
struct password_struct* allocate_heap_memory(int num_passwords) {
struct password_struct* user_password_structs = malloc(num_passwords * sizeof(struct password_struct));
if (!user_password_structs) {
printf("Malloc failed, exiting\n");
exit(0);
}
return user_password_structs;
}
void set_hash_entry(struct password_struct* user_password_structs){
int pass_entry_length = strlen(user_password_structs->password);
SHA256_CTX context;
unsigned char generated_hash[65]; //sha256 standard digest length + 1;
SHA256_Init(&context);
SHA256_Update(&context, (unsigned char *)user_password_structs->password, pass_entry_length);
SHA256_Final(generated_hash, &context);
char* hash_ptr = &user_password_structs->hash[0];
int i;
for (i=0; i < (64); i++) {
snprintf(&hash_ptr[i*2], (64), "%02x", generated_hash[i]); // Need to convert from hex to char representation
}
user_password_structs->hash[64] = '\0';
printf("%s\n", user_password_structs->hash);
}
void orchestrate_value_setting(int num_passwords, struct password_struct* user_password_structs) {
char pw1[10] = "test";
char pw2[10] = "test2";
float entropy1 = 5.0;
float entropy2 = 10.0;
strcpy(user_password_structs->password, pw1);
set_hash_entry(user_password_structs);
user_password_structs->entropy = entropy1;
user_password_structs++;
strcpy(user_password_structs->password, pw2);
set_hash_entry(user_password_structs);
user_password_structs->entropy = entropy2;
user_password_structs++;
}
void orchestrate_file_output(int num_passwords, struct password_struct* user_password_structs) {
printf("Writing data to disk...\n");
char file_name[20] = "name";
int i;
for (i = 0; i < num_passwords; i++) {
write_results_to_disk(file_name, user_password_structs);
user_password_structs++;
}
}
void write_results_to_disk(char file_name[], struct password_struct* user_password_structs) {
FILE *file_pointer = fopen(file_name, "a");
if (file_pointer == NULL) {
printf("Error: Failed to open file\n");
exit(1);
}
fprintf(file_pointer, "%s:%s:%f\n", user_password_structs->password, user_password_structs->hash, user_password_structs->entropy);
fclose(file_pointer);
}
After running this program, the following output is produced:
9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08
60303ae22b998861bce3b28f33eec1be758a213c86c93c076dbe9f558c11c752
Writing data to disk...
*** Error in `./diagnostic': free(): invalid next size (normal): 0x0804b0c0 ***
Aborted (core dumped)
I naively assumed this was an overflow issue related to my
snprintf(&hash_ptr[i*2], (64), "%02x", generated_hash[i]);
operation, but increasing the size of the hash buffer in the struct does not seem to help. Any help would be greatly appreciated!
I compiled as follows: gcc -o diagnostic -g diagnostic.c -lcrypto -lm
char hash[65];
Okay, hash has room for 65 characters.
char* hash_ptr = &user_password_structs->hash[0];
So, hash_ptr points to hash, so it points to room for 65 characters.
for (i=0; i < (64); i++) {
snprintf(&hash_ptr[i*2], (64), "%02x", generated_hash[i]); // Need to convert from hex to char representation
}
When i is 60, i*2 is 120. So you're trying to write to the 120th position of a buffer with room for 65 characters.
Change that (64) to 32 in the loop or change hash[65] to a bigger buffer.
Using valgrind found this immediately. You should learn to use some too that detects buffer overflows, use after free, double frees, and similar problems.

Getting seg fault when assigning random float value in a loop from rand()

I cannot figure out why my code works only one way and it is driving me crazy because it just should work.Whole code so far:
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <stdlib.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <time.h>
#define MAGIC_CONSTANT 73.
int Check_Parameters(int argc, char **argv){
int i=0;
if(argc > 3){
printf("You have entered more than 2 arguments!\n");
}
do{
if(isdigit(argv[2][i]) == 0){
printf("Second argument should be number!\n");
return 0;
}
i++;
}while(argv[2][i] != 0);
return 1;
}
int Write_Sequence(char **argv,int Handle){
char *length;
float *values,help;
unsigned int i,j,index;
index = atoi(argv[2]);
for(i=0; i<index; i++){
*length = (char)(rand()%11+10);
if(write(Handle,length,1) == -1){
printf("Something went wrong during Index writing\n%s\n",strerror(errno));
return 0;
}
printf("Value is: %u\n",*(unsigned int *)length);
values = malloc(*length*sizeof(float));
if(values == NULL){
printf("Memory allocation for values failed\n");
return 0;
};
for(j=0; j<*length; j++){
help = (rand()%200)/MAGIC_CONSTANT;
values[j] = (float)(rand()%200)/MAGIC_CONSTANT;
printf("%lf\n",values[j]);
}
if(write(Handle,(char*)values,sizeof(float)*(*length)) == -1){
printf("Something went wrong during value writing\n%s\n",strerror(errno));
return 0;
};
free(values);
}
return 1;
}
int main(int argc, char **argv){
int Handle;
char *citaj;
srand(time(NULL));
Check_Parameters(argc,argv);
Handle = open(argv[1], O_RDWR | O_CREAT);
Write_Sequence(argv,Handle);
close(Handle);
return 0;
}
I want to fill my allocated memory with floats. The thing is that this code does not work:
for(j=0; j<*length; j++){
values[j] = (rand()%200)/MAGIC_CONSTANT;
}
But this one does without any problem:
for(j=0; j<*length; j++){
help = (rand()%200)/MAGIC_CONSTANT;
values[j] = help;
}
MAGIC_CONSTANT = 73.
The thing is it only works when I first assign it to my help variable and then to the memory and whenever I assign it right away it gives me segmentation fault. What is wrong with that rand() function?
Thanks!
You declare length as a char *, but you never give it a value. You then try to dereference the pointer by assigning to *length. That invokes undefined behavior. In your case, this manifests as a segfault in your code without help but appears to work when you do use help.
In this code, you don't need length to be a pointer. Instead, declare it as a char and assign to it directly. Then when calling write, take its address.
int Write_Sequence(char **argv,int Handle){
// declare as char
char length;
float *values,help;
unsigned int i,j,index;
index = atoi(argv[2]);
for(i=0; i<index; i++){
// assign directly to length
length = (char)(rand()%11+10);
// pass address of length to write
if(write(Handle,&length,1) == -1){
printf("Something went wrong during Index writing\n%s\n",strerror(errno));
return 0;
}
...
The statement:
*length = (char)(rand()%11+10);
You are attempting to assign the type-casted output of rand() into an uninitialized pointer. I am not sure what you intended to use this for, but if your compiler is set properly, this should throw warnings. (uninitialized pointer)
Other things to consider, 1) for how its used, length does not need to be a pointer. 2) when using rand(), it is recommended that srand() be called first to seed the pseudo randomizer rand(). Once you do these few things, your code at least starts to work. There are other things you can do to optimize, but a code segment with these changes is below.
#define MAGIC_CONSTANT 73
int main(void)
{
char length = 0;
float *values,help;
unsigned int i,j;
srand(clock());
length = (char)(rand()%11+10);
values = malloc(length*sizeof(float));
for(j=0; j<length; j++)
{
values[j] = (rand()%200)/MAGIC_CONSTANT;
}
return 0;
}

sprintf with struct array field - gets segmentation fault

This idea is to format text info messages bellowing to a structure within a module.
It works like a charm when trying to define the message with (cf module.c):
/*this works*/
module_text3.info_text[0] = "toto[0]";
module_text3.info_text[1] = "toto[1]";
But when using sprintf, I got segmentation fault (cf module.c):
/*this gives segmentation fault*/
for(cpt=0; cpt < 2; cpt++)
{
sprintf(module_text3.info_text[cpt], "info[%u]", cpt);
}
3 different files: main.c, module.h and module.c
/*main.c*/
/*gcc -o test main.c module.c*/
#include <stdio.h>
#include "module.h"
int main(int argc, char **argv)
{
int i;
struct message3 *ptext3 = moduleFcn3();
for (i= 0; i < ptext3->info_nb; i++)
{
printf("ptext3->info_text[%u]: %s\n", i, ptext3->info_text[i]);
}
printf("ptext3->error_text: %s\n", ptext3->error_text);
printf("ptext3->id: %u\n", ptext3->id);
printf("ptext3->info_nb: %u\n", ptext3->info_nb);
printf("ptext3->info_nb_max: %u\n", ptext3->info_nb_max);
return 0;
}
/*------------------------------------------------------*/
/*module.h*/
#define NB_LINE_MAX 10
struct message3
{
char *info_text[NB_LINE_MAX]; /*a few info lines.*/
char *error_text; /*only one line for error.*/
int id;
int info_nb_max;
int info_nb;
};
extern struct message3* moduleFcn3(void);
/*------------------------------------------------------*/
/*module.c*/
#include <stdio.h>
#include "module.h"
/*static is in "Stack".*/
static struct message3 module_text3;
struct message3* moduleFcn3(void)
{
int cpt = 0;
struct message3 *ptext;
/*this gives segmentation fault*/
for(cpt=0; cpt < 2; cpt++)
{
sprintf(module_text3.info_text[cpt], "info[%u]", cpt);
}
/*this works*/
// module_text3.info_text[0] = "toto[0]";
// module_text3.info_text[1] = "toto[1]";
// cpt = 2;
module_text3.error_text = "This is error";
module_text3.id = 4;
module_text3.info_nb_max = NB_LINE_MAX;
module_text3.info_nb = cpt;
ptext = &module_text3;
return ptext;
}
I would appreciate any advises on how to format my information messages (with our without using sprintf).
Thank you,
You have not allocated space for the strings in the info_text field. The simplest thing to do would be to change the struct:
/*module.h*/
#define NB_LINE_MAX 10
#define INFO_MAX 25
struct message3
{
char info_text[NB_LINE_MAX][INFO_MAX]; /*a few info lines.*/
char *error_text; /*only one line for error.*/
int id;
int info_nb_max;
int info_nb;
};
extern struct message3* moduleFcn3(void);
You did not allocate any memory for the info_text strings. You either have to use malloc() first, or if your C library supports it (the GNU one does), use asprintf() instead of sprintf() to have it allocate enough memory to hold the whole output string for you:
for(cpt = 0; cpt < 2; cpt++)
asprintf(&module_text3.info[cpt], "info[%u]", cpt);
Don't forget that you also have to free the memory again at some point.
The reason that the following line works:
module_text3.info_text[0] = "toto[0]";
Is that the compiler ensures the string "toto[0]" is stored in memory somewhere, and you just make the pointer module_text3.info_text[0] point to that string.

How to write exact 1MB array in C?

I want to initialize an array of size 1MB. So my goal is finally write that 1MB to a file.
I am curious every time i use this formula it is giving less than 1mb.
int len = (1048576)/sizeof(int);
data = (int *) malloc(len);
What is correct way ?
Thank you
Edit - As per the comments I have changed the code .
#include <stdio.h>
#include <stdlib.h>
#include <mpi.h>
#include <string.h>
int main(int argc, char *argv[]) {
int *data;
int bytes = (1024*1024);
data = (int *) malloc(bytes);
for(int i=0;i<bytes;i++){
data[i] = (int)rand();
printf("%d",data[i]);
}
return 0;
}
After compiling it and I tried dumping the data like below
mpicc -o a mpiFileSize.c
./a > dump.dat
Now I see the file size of dump.dat. Why its 2.5MB ?
Try this
#include <stdio.h>
#include <stdlib.h>
#include <mpi.h>
#include <string.h>
int main(int argc, char *argv[]) {
char *data;
int bytes = (1024*1024);
data = (char *) malloc(bytes);
for(int i=0;i<bytes;i++){
data[i] = (char) rand();
printf("%c",data[i]);
}
return 0;
}
You shoul use character instead of integer.
Although it was already properly answered.
Just a plus to the answer, if one wants to choose the amount of MBs to allocate would make something like:
#include <malloc.h>
#define Mebabyte (1024 * 1024)
int main(int argc, char** argv)
{
void* data = malloc(2 * Megabyte);
// Do your work here...
free(data);
return 0;
}
If you wanted to allocate more than 2 MBs just change the 2.
As already stated before do not use integers as it's going to have more than 1 byte of size. Instead use char or unsigned char. And as stated by another post, there's no need to cast the result of malloc since void* can be turned to a pointer to any type (and in fact it's done implicitly by the compiler).
see: Why does this code segfault on 64-bit architecture but work fine on 32-bit?

Resources