0

On checking with valgrind, I get

main (recover.c:89) ==14182== Address 0x55022c8 is 0 bytes after a block of size 8 alloc'd

There are 2 more problems with malloc again, while doing sprintf and opening img(output file).

Here is my code

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

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

typedef uint8_t  BYTE;

int main(int argc, char* argv[])
{
// ensure proper usage
if (argc != 1)
{
    printf("Usage: ./recover\n");
    return 1;
}

// remember filenames
char* infile = "card.raw";

// open input file 
FILE* inptr = fopen(infile, "r");
if (inptr == NULL)
{
    printf("Could not open %s.\n", infile);
    return 2;
}

// initialize some flags and counters
int flag = 1;
int isfirstjpg = 1;
int isjpg = 0;
int count = 0;
FILE* img = NULL;
char* title = malloc(8 * sizeof(char));
BYTE bloc[512]={0};

// read the card 512 bytes at a time
do
{
    // if fread reaches end of file
    if (fread(bloc,sizeof(BYTE),512,inptr) == 1)
    {
        flag = 0;
    }
    else
    {
        // look for jpeg signature
        if (bloc[0] == 0xff && bloc[1] == 0xd8 && bloc[2] == 0xff)
        {
            switch (bloc[3])
            {
                case 0xe0: 
                case 0xe1: 
                case 0xe2: 
                case 0xe3: 
                case 0xe4: 
                case 0xe5: 
                case 0xe6:
                case 0xe7: 
                case 0xe8: 
                case 0xe9: 
                case 0xea: 
                case 0xeb: 
                case 0xec: 
                case 0xed: 
                case 0xee: 
                case 0xef:
                    isjpg = 1;
                    break;
                default: isjpg = 0;
            }
        }

        // if fread contains a jpg signature
        if (isjpg == 1)
        {
            // if this is the first jpg encountered
            if (isfirstjpg == 1)
            {
                // open a new file and write to  it
                sprintf(title, "%03d.jpg", count++);
                img = fopen(title, "w");

                fwrite(bloc,sizeof(BYTE),512,img);
            }
            // if this is not the first jpg encountered
            else
            {
                // close earlier file, open a new file and write to it 
                fclose(img);

                sprintf(title, "%03d.jpg", count++);
                img = fopen(title, "w");

                fwrite(bloc,sizeof(BYTE),512,img);
            }
        }
        // if fread encounters empty block (i.e. not a part of any jpg)
        else if (img == NULL && isjpg == 0) // file pointer points to null and it is not a bloc with jpg signature
        {
            continue;
        }
        // if fread encounters a block which is part of a jpg, but does not contain a signature
        else
        {
                // just write to file
                fwrite(bloc,sizeof(BYTE),512,img);
        }
    }
}while (flag == 1);
}

EDIT-
Now the program is working correctly. I moved the if - else which tested for the jpg being being first or not inside the if statement which tested for signature bytes. Also, I changed the fread() condition. The output of fread() should now be != 0. Now, isjpg and isfirstjpg are zeroed after the signature is detected. Thus the condition for isjpg == 0 has been removed form the else if statement.

2 Answers 2

1

You have a misunderstaning of the return value from the fread() call. It will return the number of elements read - the third parameter. If it works correctly, the third parameter is returned. If it reads less, it will return the number of elements actually read. At EOF, it actually returns 0. In practice, given the size of the data, it will never return 1.

The structure is also a serious problem. You have set up the read as the test condition of the if statement. It will attempt a read on every pass through the while loop. Because of the design, it will either set the flag to 0 or will test for the signature. Since it never returns 1, it will always test for the signature. This also means that it is an infinite loop because the while loop condition is always true.

The code needs to read a block, test for signature to determine whether to open a new file, AND to write out the block if a file is open - not either/or. There may be more issues, but this needs to be repaired first.

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

1
  • I did have a terrible misunderstanding of fread(). I now fixed the if - else conditions and also the variables isjpg and isfirstjpg. They both now are equated to 0 at appropriate places. The program is a lot better now but there still remain some bugs to be worked out. Thanks! Jul 7, 2016 at 19:23
1

I'm working on the same pset but it seems like you have an infinite loop. Are you sure your first if statement is working correctly and ending when it reaches the EOF? Otherwise you'll just keep creating jpgs until you run out of memory.

3
  • Yeah there is some some problem with the first if statement. On running with GDB, the loop just ends after entering the first if. Jul 7, 2016 at 16:58
  • So, I interchanged the if and else condition as well as code. The problem now is that fread is not moving beyond the first block with jpg signature bytes. Thus, it is now in an infinite loop. Jul 7, 2016 at 17:03
  • In the section videos, they mentioned not using fread code, but instead using this structure: while (fgets(output, sizeof(output), filepointer) != NULL) { // read file output } Maybe try that?
    – borker
    Jul 7, 2016 at 17:18

You must log in to answer this question.

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