-
Structure Clobering
I am writing a file integrity program. I first scans through all of the directories, gathering file names. The problem I am having is in storing the file name and directory names. File names seem to bleed into the directory tree. The first 0a-9a directories are correct ,but once I hit the bottom of the fuction the files have bleed through. Attached is the entire source code, if you feel the the code sections I have posted are not enough.
Code:
D:\tmp\0a\
D:\tmp\1a\
D:\tmp\2a\
D:\tmp\3a\
D:\tmp\4a\
D:\tmp\5a\
D:\tmp\6a\
D:\tmp\7a\
D:\tmp\8a\
D:\tmp\9a\
D:\tmp\u.txt
D:\tmp\v.txt
D:\tmp\w.txt
D:\tmp\x.txt
D:\tmp\y.txt
D:\tmp\z.txt
D:\tmp\6a\
D:\tmp\7a\
D:\tmp\8a\
D:\tmp\9a\
Code:
struct File {
int i_files;
int a_files;
char **files;
};
struct Directory {
int i_dirs;
int a_dirs;
char **dirs;
};
The following code add directories to a Directory structure and files to a File structure. It does not show the initialization of the structures.
Code:
while ((file = readdir(dir_in)) != NULL) {
if (!((dir_in->dd_dta).attrib == _A_SUBDIR)) {
if (wfiles->i_files >= wfiles->a_files) {
wfiles->files =
realloc(wfiles->files,
wfiles->a_files + MIN_FILE_ALLOC);
if (wfiles->files == NULL) {
fprintf(stderr,
"Something really bad just happend. We lost the file list in realloc.\n");
return NULL;
}
wfiles->a_files += MIN_FILE_ALLOC;
}
wfiles->files[wfiles->i_files] =
calloc(MAX_FILE_NAME, sizeof(char));
if (wfiles->files[wfiles->i_files] == NULL) {
fprintf(stderr, "File name too long.\n");
return NULL;
}
strncpy(wfiles->files[wfiles->i_files], directory,
DIR_IN_LEN);
strncpy(wfiles->files[wfiles->i_files] + DIR_IN_LEN,
"\\", 1);
strncpy(wfiles->files[wfiles->i_files] + DIR_IN_LEN + 1,
file->d_name, file->d_namlen);
wfiles->i_files++;
} else {
if (wdirs->i_dirs >= wdirs->a_dirs) {
wdirs->dirs =
realloc(wdirs->dirs,
wdirs->a_dirs + MIN_FILE_ALLOC);
if (wdirs->dirs == NULL) {
fprintf(stderr,
"Something really bad just happend. We lost the directory list in realloc.\n");
return NULL;
}
wdirs->a_dirs += MIN_FILE_ALLOC;
printf("%i\t%i\n", wdirs->a_dirs,
wdirs->i_dirs);
}
if (strcmp(file->d_name, ".") != 0
&& strcmp(file->d_name, "..") != 0) {
wdirs->dirs[wdirs->i_dirs] =
malloc(MAX_FILE_NAME * sizeof(char));
if (wdirs->dirs[wdirs->i_dirs] == NULL) {
fprintf(stderr,
"Unable to malloc(MAX_FILE_NAME * sizeof( char )).\n");
return NULL;
}
if (memset
(wdirs->dirs[wdirs->i_dirs], '\0',
MAX_FILE_NAME) == NULL) {
fprintf(stderr,
"We had some problem with memset.\n");
return NULL;
}
strncpy(wdirs->dirs[wdirs->i_dirs], directory,
DIR_IN_LEN);
strncpy(wdirs->dirs[wdirs->i_dirs] + DIR_IN_LEN,
"\\", 1);
strncpy(wdirs->dirs[wdirs->i_dirs] +
DIR_IN_LEN + 1, file->d_name,
file->d_namlen);
strncpy(wdirs->dirs[wdirs->i_dirs] +
DIR_IN_LEN + file->d_namlen + 1, "\\",
1);
printf("%s\n", wdirs->dirs[wdirs->i_dirs]);
wdirs->i_dirs++;
}
}
}
-
You are experiencing the unpredictable results of a buffer overrun.
Code:
wfiles->files = realloc(wfiles->files, wfiles->a_files + MIN_FILE_ALLOC);
should be:
Code:
wfiles->files = realloc(wfiles->files, (wfiles->a_files + MIN_FILE_ALLOC) * sizeof(*wfiles->files));
The same for other places where you allocate memory.
Welcome to the forums!
-
Also, using realloc in the following manner is not a good thing to do.
Code:
ptr = realloc(ptr, elements * sizeof *ptr);
It is better to use another temporary pointer.
Code:
temp = realloc(ptr, elements * sizeof *ptr);
if ( temp != NULL )
{
ptr = temp;
}
else
{
free(ptr);
/* etc. */
}
Then if the realloc call failed, you don't leak the memory you started with.
-
Dave_Sinkula:
Thanks for the reminder. It slipped my mind completly. 8^)
anonytmouse:
I added you suggestion and it did not change anything. I do need to add a sizeof but for char, as the wfiles->a_files variable holds how many chars have been allocated. Thanks for the help.
-
>> I do need to add a sizeof but for char, as the wfiles->a_files variable holds how many chars have been allocated. <<
No, wfiles->files holds an array of character pointers. Therefore, you have to multiply the desired number of entries by sizeof(char *). Multiplying by sizeof(char) will give you one quarter of the memory that you need(char being one byte while char * is 4 bytes on Win32). This same error is made in your calls to calloc.
These are all wrong:
Code:
wfiles->files = calloc(MIN_FILE_ALLOC, sizeof(char));
wdirs->dirs = calloc(MIN_FILE_ALLOC, sizeof(char));
char **test = calloc(MIN_FILE_ALLOC, sizeof(char));
for (int a = 0; a < MIN_FILE_ALLOC; a++) {
test[a] = calloc(MAX_FILE_NAME, sizeof(char));
}
Check all your calls to calloc(), malloc() and realloc().
-
I feel soooo very slow some times. 8^) Thanks for pointing that out. I will go through the code and see if that fixes it.
[edit] Now I feel really slow as that seems to have fixed it. Thanks for all the help.[/edit]
jInuQ