0

I was attempting PSet 4's Recover but kept running into a segmentation fault. I tried using Valgrind to debug it but I have no idea of how to interpret the error message.

My code:

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


int main(int argc, char *argv[])
{
    int counter = 0;
    if(argc != 2)
    {
        printf("Usage: ./recover image\n");
    }
    typedef uint8_t BYTE;
    FILE *recover = fopen(argv[1], "r");
    printf("%p\n", recover);
    fseek(recover, 0L, SEEK_END);
    long long int size = ftell(recover);
    BYTE *CHUNK[size];
    for(int i = 0; i < size; i++)
    {
        CHUNK[i] = NULL;
    }
    while(!(feof(recover)))
    {
        fread(CHUNK, sizeof(BYTE), size, recover);      //Break recover into bytes
    }
    int j = 0;
    char *file = NULL;
    FILE *f = NULL;
    search:
    while(j < size)
    {
        if(*CHUNK[j] == 0xff && *CHUNK[j +1] == 0xd8 && *CHUNK[j + 2] == 0xff)                           //Check if byte is JPEG format 1st byte
        {
                    switch(*CHUNK[j + 3])               //Check if byte is JPEG format 1st byte
                    {
                        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:
                        {
                            write:
                            if(f != NULL)
                            {
                                f = NULL;
                            }
                            sprintf(file ,"%03d.jpg",counter);  //Create custom file of format xxx.jpg
                            f = fopen(file,"w");
                            for(int k = 0; k < 512; k++)
                            {
                                fwrite(CHUNK[j + k], 512, sizeof(BYTE), f);  //Copy 512 bytes from start of JPEG file as 512 bytes form one 'block'
                            }
                            j += 512; //Increment to check initial bytes of next 'block'
                            if(*CHUNK[j] == 0xff && *CHUNK[j + 1] == 0xd8 && *CHUNK[j + 2] == 0xff)  //Check if next block is JPEG
                            {
                                if(*CHUNK[j + 3] == 0xe0 ||*CHUNK[j + 3] == 0xe1 ||*CHUNK[j + 3] == 0xe2 ||*CHUNK[j + 3] == 0xe3 ||*CHUNK[j + 3] == 0xe4 ||*CHUNK[j + 3] == 0xe5 ||*CHUNK[j + 3] == 0xe6 ||*CHUNK[j + 3] == 0xe7 ||*CHUNK[j + 3] == 0xe8 ||*CHUNK[j + 3] == 0xe9 ||*CHUNK[j + 3] == 0xea ||*CHUNK[j + 3] == 0xeb ||*CHUNK[j + 3] == 0xec ||*CHUNK[j + 3] == 0xed ||*CHUNK[j + 3] == 0xee ||*CHUNK[j + 3] == 0xef)
                                {
                                    counter++;  //If next block has JPEG start open new file and write new JPEG
                                    goto search;
                                }
                                else{ fclose(f); goto write;}   //Else continue writing
                            }
                            else{ fclose(f); goto write;}   //Else continue writing
                        }
                    }
        }
        else { j++; continue;}  //Else continue searching
    }
    fclose(recover);
}

This is the Valgrind error message:

==2936== Memcheck, a memory error detector
==2936== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==2936== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==2936== Command: ./recover card.raw
==2936== 
0x5a07040
==2936== Warning: client switching stacks?  SP change: 0x1fff0004a0 --> 0x1ffd36e4a0
==2936==          to suppress, use: --max-stackframe=29958144 or greater
==2936== Invalid write of size 8
==2936==    at 0x4008C6: main (recover.c:22)
==2936==  Address 0x1ffd36e4a0 is on thread 1's stack
==2936== 
==2936== 
==2936== Process terminating with default action of signal 11 (SIGSEGV)
==2936==  Access not within mapped region at address 0x1FFD36E4A0
==2936==    at 0x4008C6: main (recover.c:22)
==2936==  If you believe this happened as a result of a stack
==2936==  overflow in your program's main thread (unlikely but
==2936==  possible), you can try to increase the size of the
==2936==  main thread stack using the --main-stacksize= flag.
==2936==  The main thread stack size used in this run was 8388608.
==2936== Invalid write of size 8
==2936==    at 0x4A2A650: _vgnU_freeres (in /usr/lib/valgrind/vgpreload_core-amd64-linux.so)
==2936==  Address 0x1ffd36e498 is on thread 1's stack
==2936== 
==2936== 
==2936== Process terminating with default action of signal 11 (SIGSEGV)
==2936==  Access not within mapped region at address 0x1FFD36E498
==2936==    at 0x4A2A650: _vgnU_freeres (in /usr/lib/valgrind/vgpreload_core-amd64-linux.so)
==2936==  If you believe this happened as a result of a stack
==2936==  overflow in your program's main thread (unlikely but
==2936==  possible), you can try to increase the size of the
==2936==  main thread stack using the --main-stacksize= flag.
==2936==  The main thread stack size used in this run was 8388608.
==2936== 
==2936== HEAP SUMMARY:
==2936==     in use at exit: 4,648 bytes in 2 blocks
==2936==   total heap usage: 2 allocs, 0 frees, 4,648 bytes allocated
==2936== 
==2936== 552 bytes in 1 blocks are still reachable in loss record 1 of 2
==2936==    at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==2936==    by 0x5694EB9: __fopen_internal (iofopen.c:65)
==2936==    by 0x5694EB9: fopen@@GLIBC_2.2.5 (iofopen.c:89)
==2936==    by 0x40083F: main (recover.c:15)
==2936== 
==2936== 4,096 bytes in 1 blocks are still reachable in loss record 2 of 2
==2936==    at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==2936==    by 0x56941FB: _IO_file_doallocate (filedoalloc.c:101)
==2936==    by 0x56A43E8: _IO_doallocbuf (genops.c:365)
==2936==    by 0x56A0D92: _IO_file_seekoff@@GLIBC_2.2.5 (fileops.c:960)
==2936==    by 0x569DD48: fseek (fseek.c:36)
==2936==    by 0x400870: main (recover.c:17)
==2936== 
==2936== LEAK SUMMARY:
==2936==    definitely lost: 0 bytes in 0 blocks
==2936==    indirectly lost: 0 bytes in 0 blocks
==2936==      possibly lost: 0 bytes in 0 blocks
==2936==    still reachable: 4,648 bytes in 2 blocks
==2936==         suppressed: 0 bytes in 0 blocks
==2936== 
==2936== For counts of detected and suppressed errors, rerun with: -v
==2936== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
Segmentation fault

I'd like to know why the segmentation fault occurs or atleast what Valgrind's error message means.

1

You must log in to answer this question.

Browse other questions tagged .