0

My program is seg faulting so impressively that it managed to crash the appliance at one point, and after two days I still can't figure out what's happenning. Help will be massively appreciated at this point. My code:

/**
 * recover.c
 *
 * Computer Science 50
 * Problem Set 4
 *
 * Recovers JPEGs from a forensic image.
 */
 #include <stdio.h>
 #include <cs50.h>
 #include <stdlib.h>

int main(int argc, char* argv[])
{
//all the different data we'll need later
unsigned char jpg_beginning1[4] = {0xff, 0xd8, 0xff, 0xe0};
unsigned char jpg_beginning2[4] = {0xff, 0xd8, 0xff, 0xe1};
int jpg_count = 0;
char buffer[512];

// TODO
// make sure not too many arguments
if(argc != 1)
{
    printf("Usage: ./recover\n");
    return 1;
}

// open the card file
FILE* card = fopen("card.raw", "r");

// make sure file can actually open
if(card == NULL)
{
    fclose(card);
    printf("Could not open file.\n");
    return 1;
}

// initialise outfile
FILE* new_jpg = NULL;

while(!feof(card))
{   
    // read 512 bytes into a buffer
    fread(buffer, 1, 512, card);

    // check if the first 4 bytes correspond to a JPEG
    if(buffer[0] == jpg_beginning1[0] && buffer[1] == jpg_beginning1[1] && buffer[2] == jpg_beginning1[2] && (buffer[3] == jpg_beginning1[3] || buffer[3] == jpg_beginning2[3]))
    {
        // take care of all things filename
        jpg_count++;
        char filename[50];
        if(jpg_count < 10)
        {
            sprintf(filename, "00%d.jpg", jpg_count);
        }
        else
            sprintf(filename, "0%d.jpg", jpg_count);

        // close the outfile if already open
        fclose(new_jpg);

        // open the new file
        new_jpg = fopen(filename, "a");  
        fwrite(buffer, 1, 512, new_jpg);

    }   
    else
    {
        // if no JPEGs found yet
        if(jpg_count == 0)
        {
            continue;
        }
        // if we're still in the same file
        else
            fwrite(buffer, 1, 512, new_jpg);
    }
}
fclose(card);

}

I've run the program through with gdb and valgrind and the problem seems to be around line 41 (weird, because it's empty).

Valgrind returned this:

Use of uninitialised value of size 4
at 0x40F0687: fwrite (iofwrite.c:41)
by 0x80488E5: main (recover.c:73)

Use of uninitialised value of size 4
at 0x40F06C5: fwrite (iofwrite.c:42)
by 0x80488E5: main (recover.c:73)

Use of uninitialised value of size 4
at 0x40F06E9: fwrite (iofwrite.c:43)
by 0x80488E5: main (recover.c:73)

Invalid read of size 4
at 0x40F06FF: fwrite (iofwrite.c:43)
by 0x80488E5: main (recover.c:73)
Address 0x9483beda is not stack'd, malloc'd or (recently) free'd

There don't see to be any memory leaks per se though, and while the above tells me something, it's not enough to solve the problem. Any ideas what I'm doing wrong?

1 Answer 1

0

The issue is that you are attempting to write to a file that has not yet been opened.

Remember that the instructions tell you that the beginning of the file is trash data, not image data. You have to find the first signature before writing to output files. From that point on, all the data that remains are the image files that are to be recovered. What it doesn't mention is that there is a lot of trash data that has to be discarded first.

Now, with that in mind, look at what happens when you process the first block. You read it into buffer and check for a jpg signature. When it isn't found, you drop below the if statement's code block and immediately try to write to new_jpg, which has yet to be opened. Instant failure. I'll leave it to you to figure out how to fix this, but if you can't after giving it a good try, post a comment and I'll give some guidance.

Once you solve that problem, you have another waiting. As written, it will never produce more than one file because jpg_count is being initialized inside the while loop and will reinitialize on each pass. You need to initialize it before the start of the while loop.

This may not fix all your problems, but it will get you going again.

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

4
  • Thank you, the program's no longer seg faulting ;) I've got a different problem now though. When you run it through with gdb, buffer seems to be empty even after fread is executed, and I've not idea why that's happening. Any ideas? (It's weird, the first few times it iterated over fread in gdb there are some values in buffer[0], buffer[1] etc. but on nth iteration over the while loop buffer just fills with 0s.) Aug 30, 2015 at 12:11
  • First of all, the program has to go through over 33,000 blocks of data to get to the jpg files, so a lot of it is probably just zeros. A block of all zeros isn't no data, it's data that = 0! But, your bigger problem is that you're not detecting the jpeg signatures. That problem is in your comparison test. It's a subtle problem because you are comparing two different data types. Try changing your buffer from char to unsigned char. That should take care of it. Next, you'll have a file naming problem, but that one is simple to fix so I'll leave it to you to figure out. ;-)
    – Cliff B
    Aug 30, 2015 at 18:58
  • Wow, that's strange, because I've done that before and the program seg faulted again...But it's all sorted now, everything works fine, so thank you! What do you mean with the file naming problem? Everything seems to be fine, as in there are sixteen jpegs with names in the xxx.jpg format. Aug 30, 2015 at 19:13
  • Are they numbered from 0 to 15?
    – Cliff B
    Aug 30, 2015 at 19:21

You must log in to answer this question.

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