0

everyone!

I've been stuck with this one for a little while. Through debugging I found out that my problem is probably in the size parameter I'm trying to pass to fread() in line 33 (start of the while loop). However I have no idea what I'm doing wrong.

I thought every block was supposed to be 512 bytes and that sizeof(BYTE) would be enough to specify it. I also tried using sizeof(buffer) and telling the program to only read that size one time.

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

typedef uint8_t BYTE;

int main(int argc, char *argv[])
{
    // Ensures correct usage
    if (argc != 2)
    {
        printf("Usage: ./recover image\n");
    }


    // Opens file
    FILE *file = fopen(argv[1], "r");

    // Checks if file exist
    if (file == NULL)
    {
        printf("It wasn't possible to open the file\n");
        return 1;
    }


    char filename[7];
    int jpg_count = 0;
    BYTE buffer[512];
    FILE *img = NULL;

    // Repeats while fread() is able to read 512 bytes into buffer
    while (fread(buffer, sizeof(BYTE), 512, file) == 512)
    {
        // Checks if the first 4 bytes are the start of a jpg
        if ((buffer[0] == 0xff) && (buffer[1] == 0xd8) && (buffer[2] == 0xff) && ((buffer[3] & 0xf0) == 0xe0))
        {
            // If it's not the first jpg, close the last one
            if (jpg_count != 0)
            {
                fclose(img);
            }


            // Declares the name of the file
            sprintf(filename, "%03i.jpg", jpg_count);


            // Opens a new jpg
            img = fopen(filename, "w");

            // Checks if it was able to open file
            if (img == NULL)
            {
                printf("It wasn't possible to create a new jpg\n");
                return 1;
            }

            jpg_count++;
        }

        // If it's the first iteration, but isn't the start of jpg, you probably don't want to write what is there (you might get rick rolled =/)
        if (img != NULL)
        {
            // Writes block
            fwrite(buffer, sizeof(BYTE), 512, img);
        }
    }
}

The terminal is always as follows:

~/pset4/recover/ $ ./recover card.raw

Fatal error: glibc detected an invalid stdio handle

Aborted

2

At line 46, you write to the outside of filename declared at line 27. Here is the link that you can debug errors like this by yourself.

  Memory access error: writing to the outside of a memory space; abort execution.
  # Writing 1 bytes to 0xffe686b3 will clobber other memory-spaces.
  #
  # The memory-space-to-be-written (start:0xffe686ac, size:7 bytes) is bound to 'filename' at
  #    file:/recover.c::27, 10
  #
  #  0xffe686ac               0xffe686b2
  #  +------------------------------+
  #  |the memory-space-to-be-written|......
  #  +------------------------------+
  #                                  ^~~~~~~~~~
  #        the write starts at 0xffe686b3 that is right after the memory-space end.
  #
  # Stack trace (most recent call first) of the write.
  # [0]  file:/musl-1.1.10/src/stdio/vsnprintf.c::40, 9
  # [1]  file:/musl-1.1.10/src/stdio/vsprintf.c::6, 9
  # [2]  file:/musl-1.1.10/src/stdio/sprintf.c::19, 8
  # [3]  file:/recover.c::46, 13
  # [4]  [libc-start-main]
4
  • I'm not sure how to fix it. I thought that maybe I could assign filename to NULL after I finished using it, but that didn't work because it's not a pointer. May 25 '20 at 0:20
  • you can make filename larger by declaring it as char filename[16] and try it again. Your code might have other errors. Please accept my answer if it pointed out the cause.
    – stensal
    May 25 '20 at 0:22
  • Now it works perfectly! Thank you! Was that error occurring because I was forgetting about the "\0" in the end of the string or something else? May 25 '20 at 0:33
  • No, sprintf will automatically append '\0', your filename array is just too small.
    – stensal
    May 25 '20 at 0:38

You must log in to answer this question.

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