0

My recover program creates 50 files, but they do not open (it says "Invalid or Unsupported Image Format"). I opened some of the JPEGs with a hexadecimal editor and found out that they start with 00 d8 ff e, instead of ff d8 ff e. What is the problem with my solution? Thank you in advance.

/**
 * Recovers JPEGs from a forensic image.
 * CS50x 2018 Problem Set 4
 * Author: Leonidius20
 **/

#include <stdio.h>

#define BLOCKSIZE 512

typedef unsigned char byte;

int main(int argc, char *argv[])
{
    // Ensure proper usage
    if (argc != 2)
    {
        fprintf(stderr, "Usage: ./recover <forensic image>\n");
        return 1;
    }

    // Open an image
    char *imageName = argv[1];
    FILE *image = fopen(imageName, "r");
    if (image == NULL)
    {
        fprintf(stderr, "Cannot open an image.\n");
        return 2;
    }

    int fileNumber = -1;
    FILE *currentFile = NULL;

    // Temporary storage
    byte buffer[BLOCKSIZE];

    // Iterate over blocks in the image
    while (fread(&buffer, BLOCKSIZE, 1, image) == 1)
    {
        // Check if there is a JPEG header in i'th block
        if (buffer[0] == 0xff &&
            buffer[1] == 0xd8 &&
            buffer[2] == 0xff &&
            (buffer[3] & 0xf0) == 0xe0)
        {
            // Closing the current file
            if (currentFile != NULL)
            {
                fclose(currentFile);
            }

            // Opening a new file
            fileNumber++;
            char fileName[7];
            sprintf(fileName, "%03i.jpg", fileNumber);
            currentFile = fopen(fileName, "w");
            if (currentFile == NULL)
            {
                fprintf(stderr, "Cannot create a file %s.\n", fileName);
                return 3;
            }

            // Writing the block to the file
            fwrite(buffer, BLOCKSIZE, 1, currentFile);
        }  
        // If there is no header in the block...
        else
        {
            // ...just write it to the file
            if (currentFile != NULL)
            {
                fwrite(buffer, BLOCKSIZE, 1, currentFile);
            }
        }
    }

    // Closing the image
    fclose(image);

    // Closing the current file
    if (currentFile != NULL)
    {
        fclose(currentFile);
    }

    // Success
    return 0;
 }
2

The whole problem is given by the following statement:

char fileName[7];

The file name is given by seven characters, but you must bear in mind that it is a string, so we need an additional character (end of string \ 0), note that this simple fact causes an indefinite behavior throughout the program because the program does not know where the string ends. The solution is simple:

char fileName[8];
4
  • Well, the cause is correct, but the result is perfectly predictable. The sprintf will write the \0 at the end of the string. Unfortunately, since the array is only 7 chars, the \0 is written into the very next memory location, no matter what it was allocated for. In this pset, its usually the buffer, so every file ends up with \0 as the first byte. ;-) – Cliff B May 1 '18 at 18:51
  • it may be a lot to suppose that the buffer is overwritten, but in any case it is a more accurate explanation – MARS May 1 '18 at 19:23
  • Obviously, it would be unreasonable to simply assume the buffer is overwritten, but because this has happened so many times in the past, and the first byte of each file is being overwritten, well, it's a safe bet. ;-) The buffer usually gets allocated right after the output filename string. It's a result of the distribution code. But you're right. In general, when the space isn't allocated for the \0, then something is going to be corrupted! – Cliff B May 1 '18 at 19:27
  • Thank you! Everything works now. – Leonidius May 2 '18 at 16:36

You must log in to answer this question.

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