2
votes

I am fairly new to C so I've been honing my skills by working on this program which recovers passwords by searching two text files for matching hashes. When I attempt to compile this program, I get the following error.

Segmentation fault (core dumped)

As such, I attempted to debug my program using valgrind. As I'm rather new to C I do not quite understand the errors in my program. The errors are as follows.

Error 1: Possible memory leaks.

552 bytes in 1 blocks are still reachable in loss record 1 of 2
 at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-
 linux.so)
by 0x4EA7CDC: __fopen_internal (iofopen.c:69)
by 0x4008E7: matchfile (in /home/st2411/test)
by 0x400873: main (in /home/st2411/test)

Error 2: Invalid read of size 1. I find this error rather difficult to understand as it does not indicate which line the error occurred

Invalid read of size 1
at 0x4EE4070: __strstr_sse2_unaligned (strstr-sse2-unaligned.S:22)
by 0x4009DA: matchfile (in /home/st2411/test)
by 0x400873: main (in /home/st2411/test)
Address 0x0 is not stack'd, malloc'd or (recently) free'd

My Code Is as follows :

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define MAXCHAR 1000
//Declaring Functions to match word in file
int matchfile(char *shadowfilename, char 
*hashtablefilename);//shadowfilename for shadow.txt hashtablefilename for hash table

void UsageInfo(char *shadowfile, char * hashtablefile );//Display usage info on arguements for program

void UsageInfo(char *shadowfile, char * hashtablefile) {
    printf("Usage: %s %s <shadowfile> <hashtable>\n", shadowfile, hashtablefile);

}

//main function.
int main(int argc, char *argv[]) {
    int result;
        int errcode;
//Display format for user to enter arguements and
//End program if user does not enter exactly 3 arguements
    if(argc < 3 || argc > 3) {
        UsageInfo(argv[1],argv[2]);
        exit(1);
    }


    system("cls");
//Pass command line arguements into searchstringinfile
    result = matchfile(argv[1], argv[2]);

//Display error message
    if(result == -1) {
        perror("Error");
        printf("Error number = %d\n", errcode);
        exit(1);
    }
    return(0);
}
//Declaring Functions to match word in file


int matchfile(char *shadowfilename, char *hashtablefilename){
    //Declare file containing user account and hashed password
    FILE *shadowfile;
    //Declare file containing list of words and corresponding hash values

    FILE *hashtable;
    //char variables to extract text from files

    char strshadow[MAXCHAR];

    char strhash[MAXCHAR];

//read from file containing user account and hashed password

shadowfile = fopen(shadowfilename, "r");

//error message if file does not exist

if (shadowfile == NULL){
    printf("Could not open file %s",shadowfilename);
    return 1;
}

//read from file containing list of words and corresponding hash values

hashtable = fopen(hashtablefilename, "r");

//error message if file does not exist

if (hashtable == NULL){
    printf("Could not open file %s",hashtablefilename);
    return 1;
}

const char ch = '$';
//char variables to extract hash values

//char *strshadowvalues for shadow file;

//char *strhashvalues for hash table file;
//Valgrind detected an error here
char *strshadowvalues;
char *strhashvalues;

    //variable to check line number for matched
int linenumber = 1;
    //Variable to count match results
int search_result = 0;
while (fgets(strshadow, MAXCHAR, shadowfile) != NULL && fgets(strhash, MAXCHAR, hashtable) != NULL){


    strshadowvalues = strchr(strshadow, ch);
    strhashvalues = strchr(strhash, ch);
            //Matching hashes line-by-line

    if((strstr(strshadowvalues,strhashvalues)) != NULL) {
        //Display lines in which matched hash is found

        printf("A match found on line: %d\n", linenumber);
        //Display matching hash in shadow file

                    printf("Shadow:\n%s\n", strshadow);
                    //Display matching hash in shadow file

        printf("Hash: \n%s\n", strhash);


        search_result++;
    }//Display message if no match

    if((strstr(strshadowvalues,strhashvalues)) == NULL|| strshadowvalues==NULL || strhashvalues==NULL) {
                printf("No password found ");
            }
    linenumber++;
}

//close file
fclose(shadowfile);
return 0;
}

If someone could explain to me where I've gone wrong and guide me on how to fix them, I would be very grateful.

1
Compile your code with -g will give you more information.. Like line number ;).Stargateur
"Invalid read of size 1" => look like you are overextend of one char ? Useful information.Stargateur
"Address 0x0" => NULL pointer ?Stargateur
Man of strstr => "These functions return a pointer to the beginning of the substring, or NULL if the substring is not found.".Stargateur
You fopen() two files, but fclose() only one of them. That's where your memory leak comes from.M Oehm

1 Answers

2
votes

Think about what happens here:

strshadowvalues = strchr(strshadow, ch);
strhashvalues = strchr(strhash, ch);
        //Matching hashes line-by-line

if((strstr(strshadowvalues,strhashvalues)) != NULL) {
    //Display lines in which matched hash is found

when there is no $ found in the line or when one of the two strings (or both, for that matter) are empty. The answer is, strstr() will return a null pointer. When you try to print that with a %s format string, you end up in the realm of undefined behavior and a segmentation fault.

I'll leave it to you to find the memory leak that Valgrind mentions, but this is why it is telling you that Address 0x0 is not stack'd, malloc'd or (recently) free'd