JACK M JACK M - 1 month ago 8
C Question

find special cases while comparing files in reverse order

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BS 12

void reverse(char * buffer, int size)
{
char tmp;
int i;
for(i = 0; i < size / 2; i++)
{
tmp = (char)buffer[i];
buffer[i] = buffer[size - i - 1];
buffer[size - i - 1] = tmp;
}
}

int compare_bin(char * buffer, char * buffer2, int size)
{
// because strncmp is only for string without \x00, so there must be a customized compare function
int i;
for(i = 0; i < size; i++)
{
if(buffer[i] != buffer2[i])
return 0;
}
return 1;
}

int main (const int argc, const char** argv)
{
if(argc != 3)
exit(-1);

int equal = 1;
char * buffer = malloc(BS), * buffer2 = malloc(BS);
FILE * f1, * f2;
f1 = fopen(argv[1], "r");
f2 = fopen(argv[2], "r");

fseek(f1, 0, SEEK_END);
fseek(f2, 0, SEEK_END);

long i = ftell(f1), j = ftell(f2);
if(i != j)
{
equal = 0;
goto endp;
}

fseek(f2, 0, SEEK_SET);

int need = 0;
int count;
int f2_pos = 0;

do
{
i = i - BS;
if(i < 0)
{
need = BS - abs((int)i);
i = 0;
}
else
need = BS;

fseek(f1, i, SEEK_SET);
count = fread(buffer, need, 1, f1);

reverse(buffer, count * need);
// fwrite(buffer, count * need, 1, f2);
fread(buffer2, need * need, 1, f2);

// printf("compare...\n");
// for(int i = 0; i < need * count; i++)
// {
// printf("%02hhX", buffer[i]);
// }
// printf("\n");
// for (int i = 0; i < need * count; i++)
// {
// printf("%02hhX", buffer2[i]);
// }
// printf("\n");


if(compare_bin(buffer, buffer2, need * count) == 0)
{
equal = 0;
break;
}

f2_pos += need * count;
fseek(f2, f2_pos, SEEK_SET);

if(i == 0)
break;
}while(i > 0);

fclose(f1);
fclose(f2);
free(buffer);
free(buffer2);

endp:
if(equal)
return 0;
else
{
printf("2 files not equal is reversed order\n");
return 1;
}

return 0;
}


So I write a program to compare file content in reverse order. I have already considered
\x00
in binary file and
strncmp
isn't used. But there is still flaw. There is a test server to test this program. But I dont have access to it. This program always fails on that server. So there must be some special cases to make it fail. Any idea?

There are other ways around it. For instance, calculating MD5. But I want to fix this.

Answer

For the very first iteration where you read data you have

fread(buffer2, need * need, 1, f2);

The problem is that in that case need is 12, which is the size of the memory allocated for buffer2, but you ask to read 12 * 12 bytes.

If the second file is large enough, you will write out of bounds in the memory, leading to undefined behavior. If the file is not large enough then you won't read anything.

Also note that the order of the two middle arguments to fread matter. If you changed the order you would write out of bounds of the buffer both if the file is larger than need * need or not. You should really read count byte-sized object (the second argument should be 1 and the third should be count, which of course mean you need to change the order in the first call as well).

In short, your two fread calls should be

count = fread(buffer, 1, BS, f1);
fread(buffer2, 1, count, f2);

PS. Don't forget error checking.