0

I have run my program and it works (at least looks like). My code recovered all the 000.jpg to 049.jpg. The 50 jpgs show in the "jpg folder, and I can see all the 50 faces of the teaching team.

However, the check code says the code recovers the 000.jpg correctly but fails to recover the middle and the last jpg.

I tried GDB, GDB shows the process exits normally. But if I set a breakpoint to main and run step by step, it seems to be trapped in the first loop.(I don't get why it can exits normally while trapped in a loop)

So I desperately don't have any other resort.

Here's my questions:

  1. I do not define how long is my BLOCK, how could the code know and read and write the 50 images?

2.How could the code successfully recovers the 000.jpg but fails at the middle and the last? (and yet the images all look fine, clear and viewable)

Thanks

Here's my code:

/**
 * recover.c
 *
 * Computer Science 50
 * Problem Set 4
 *
 * Recovers JPEGs from a forensic image.
 */

 #include <stdio.h>
 #include <stdlib.h>
 #include <stdint.h>

 typedef uint8_t  BYTE;

 typedef struct
{
BYTE  byte_1;
BYTE  byte_2;
BYTE  byte_3;
BYTE  byte_4;
BYTE* body[];
} __attribute__((__packed__))
BLOCK;

int main(void)
{

// open the input file
FILE* file = fopen("card.raw", "r");
if (file == NULL)
{
    printf("Could not open card.raw\n");
    return 1;
}

BLOCK block;

do
{
    fread(&block, sizeof(BLOCK), 1, file);
}
while (block.byte_1 != 0xff || block.byte_2 != 0xd8 || block.byte_3 != 0xff || (block.byte_4  < 0xe0 || block.byte_4 > 0xef));


//open new file
char* tittle = malloc(7 * sizeof(BYTE));
int photo_recovered = 0;
sprintf(tittle, "%03d.jpg", photo_recovered);
FILE* img = fopen(tittle, "w");

fwrite(&block, sizeof(BLOCK), 1, img);


while (fread(&block, sizeof(BLOCK), 1, file) == 1) //read a block and check the condition
{

    //when the next ID is detected
    if (block.byte_1 == 0xff && block.byte_2 == 0xd8 && block.byte_3 == 0xff && 0xe0 <= block.byte_4  && block.byte_4  <= 0xef)
    {
        fclose(img);
        photo_recovered = photo_recovered + 1;
        sprintf(tittle, "%03d.jpg", photo_recovered);
        img = fopen(tittle, "w");
        fwrite(&block, sizeof(BLOCK), 1, img);
    }

    //if no ID detected
    else
    {
        fwrite(&block, sizeof(BLOCK), 1, img);
    }
}


free(tittle);
fclose(file);
fclose(img);
return 0;
}
2

If you put the following in your code before the big while loops, you should understand the problem:

printf("sizeof(BLOCK) = %lu\n", sizeof(BLOCK));

The code is processing 4 bytes at a time, not 512 bytes. This causes several problems. First, the program is taking 128 times longer to run. Second, it is getting caught by some data that was deliberately planted in the test file to catch this exact condition. (It is possible for random image data to match a signature, so only the first 4 bytes of a 512 byte block should be checked.) BTW, check50 uses a different input file than is provided, with a different number of image files. Surprise!

Minor issue: when the code allocates memory for the file name, it allocates 7 bytes. File names are 7 bytes. Where is the end of string marker, \0, being put?

Finally, you have created a structure for the buffer, with 4 individual bytes for the first 4 bytes, plus a pointer to an array. That pointer doesn't specify any size. When you start reading 512 bytes at a time, this last part is going to produce a seg fault. You could modify the struct to work, but a struct complicates matters. Why not keep it simple and create a simple buffer array of an unsigned one byte type with a size of 512 and just check array elements 0 through 4 for the signature, but write 512 bytes at a time?

If this answers your question, please click on the check mark to accept. Let's keep up on forum maintenance. ;-)

3
  • Your answer is very helpful. But I still have some questions.
    – user13479
    Aug 25 '16 at 7:04
  • 1. BYTE* body[] in the struct didn't specify any size, so it's just there, not doing anything? So the code processed 4 bytes. BUT my code wasn't caught by any random signatures. The code still recovered all the 50 images. Was it just a coincidence? 2. I only allocated 7 bytes for the file names, but it didn't seem to cause any problems. Why was it? 3. Yes, I figured out that just a simple array can do.
    – user13479
    Aug 25 '16 at 7:10
  • 1. As written, yes. But when you change it from 4 to 512 bytes, it's going to hold the last 508. If not explicitly allocated, it's going to hit a seg fault for trying to store data well past the undefined length body[]. The random sig isn't in your data file, but it is in the one used by chek50. They're sneaky like that. ;-) 2. you were lucky. sometimes it works, sometimes not. It depends on what is stored in physical memory immediately after. More often than not, that will cause a problem with check50 because that's a far more active system where memory is extensively used and reused.
    – Cliff B
    Aug 25 '16 at 7:16

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .