Adonai
Adonai

Reputation: 129

unexpected seg fault caused by lstat function

i'm making na assignment for programming class.
The program is supposed to:

  1. receive a string from command line.
  2. open the current directory and cycle through its entries,
    and analyse the entries only if their name starts with the string that i passed from CMD.
  3. if these entries are regular files,
    i need to count all characters except spaces,
    and count the number of words that start with a/A.

Here's the code.

int main(int argc,char* argv[])
{
    if(argc!=2) //ensures at least an argument is passed.
    {
        puts("enter one argument.");
        exit(EXIT_FAILURE);
    }

    DIR* folder; //folder abstraction
    struct dirent* entry; //entry abstraction
    struct stat info; //file's i node info

    FILE* file;
    int total=0,first=0;
    char temp[100];

    int res;

    folder=opendir("."); //i open the directory

    while((entry=readdir(folder))!=NULL) //i cicle through every entry
    {

        res=strncmp(entry->d_name,argv[1],strlen(argv[1]));
        if(res==0) //if entry name begins with string i continue
        {

            lstat(entry->d_name,&info); //i take file info
            if(S_ISREG(info.st_mode)) //i check if it's a regular file
            {
                file=fopen(entry->d_name,"r"); //i open it
                //printf("%s\n",entry->d_name);
                while((fscanf(file,"%s",temp))!=EOF) //i parse it
                {
                    if(temp[0]=='a'|| temp[0]=='A')
                    {
                        first++;
                    }
                    total+=strlen(temp);
                }
                //now i close the file and print all info
                fclose(file);
                printf("%s\nthe number words that start with a/A: %i\n",entry->d_name,first);
                printf("the amount of characters except spaces is %i\n",total);
                total=0;
                first=0;
            }

        }
        //now the process will be repeated for the remaining entries
    }
    return 0;
}

the problem is, the program gets the first entry that starts with the pattern that i passed from CMD, evaluates it correctly, but then
when the stat is called on the second entry, it causes seg fault 11.

if i comment out the lstat, all the entries that match the criteria are recognized, even if no calculation i can't test if it's regular file without lstat...
what is causing the issue, i've been trying stuff for the past two hours, please help me, thanks!

EDIT:

I found the problem, basically the directory I'm working in has binary files of executables.

It turns out that binary files are considered regular files, so when the program opened it to parse it, it parsed one long string that caused buffer overflow on the temp variable. I thought those files were binary and separated from regular.

Upvotes: 1

Views: 351

Answers (1)

chux
chux

Reputation: 153517

unexpected seg fault caused by lstat function

With undefined behavior in other parts of code, we do not know the seg fault is caused by lstat. Inclusion of lstat did reveal a problem, yet the true cause may lie elsewhere.


Code has troubles yet it lacks error checking in various places. @Weather Vane

Check function return values

folder=opendir(".");
if (folder == NULL) {
  perror("opendir failed);
  exit (EXIT_FAILURE);
}


// lstat(entry->d_name,&info);
if (lstat(entry->d_name,&info)) {
  perror("lstat failed);
  exit (EXIT_FAILURE);
}

file=fopen(entry->d_name,"r");
if (file == NULL) {
  fprintf(stderr, "Unable to open <%s> for reading\n", entry->d_name);
  exit (EXIT_FAILURE);
}

Limit width

// while((fscanf(file,"%s",temp))!=EOF)
while(fscanf(file,"%99s",temp) == 1) {
  if (strlen(temp) == 99) {
    fprintf(stderr, "Maximum length word read, longer ones might exist\n");
    exit (EXIT_FAILURE);
  }

Of course instead of exiting, code cab handle the error in some other way.

Minor: I'd used width types for counting characters.

Upvotes: 1

Related Questions