CS50 pset04 - handles lack of forensic image - segmentation fault - c

Problem
The program is supposed to recover images from a memory chunk with the following requirements:
each JPEG file start with a distinct header
all first 3 bytes in JPEG files are the same : 0xff - 0xd8 - 0xff
the fourth byte : 0xe0, 0xe1, 0xe2, ...., or 0xef
the JPEG files are stored back to back in the memory car
each block is 512 bytes
It's compiled and runs smoothly on my local machine. But fail when I use check50. Anybody has an idea why? Please help
:( handles lack of forensic image // failed to execute program due to segmentation fault
Code
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#define FAT 512
typedef unsigned char BYTE;
int main(int argc, char *argv[])
{
// program must accept only one argument
if (argc > 2)
{
printf("Usage: ./recover [image disk]\n");
return 1;
}
// open forentic file
FILE *input = fopen(argv[1], "r");
if (input == NULL)
{
fclose(input);
printf("Could not open %s.\n", argv[1]);
return 2;
}
// create a buffer
BYTE buffer[FAT];
int fcount = -1;
char pic_name[8];
FILE *output;
while (fread(buffer, FAT, 1, input))
{
// check if the buffer started with the 04 signed digits of jpeg
if (buffer[0] == 0xff &&
buffer[1] == 0xd8 &&
buffer[2] == 0xff &&
(buffer[3] & 0xe0) == 0xe0)
{
// if it's not the first picture, we need to close the connection
// to create a new image.
if (fcount > -1)
{
fclose(output);
}
fcount++;
sprintf(pic_name, "%03i.jpg", fcount);
output = fopen(pic_name, "w");
if (output == NULL)
{
fclose(input);
printf("Could not create %s.\n", pic_name);
return 3;
}
}
if (fcount > -1)
{
fwrite(buffer, FAT, 1, output);
}
}
fclose(input);
fclose(output);
return 0;
}

Related

CS50 pset4 recover > program is free of memory errors

I finished writing the program that recovers photos from a memory card and it's working properly
But there is an error closing the "output"file.
I just want to know where to write another "fclose"
This is the error:
:( program is free of memory errors
Cause
valgrind tests failed; see log for more information.
Log
running valgrind --show-leak-kinds=all --xml=yes --xml-file=/tmp/tmpie2_4mb5 -- ./recover card.raw...
checking that program exited with status 0...
checking for valgrind errors...
23,128 bytes in 49 blocks are still reachable in loss record 1 of 1: (file: recover.c, line: 35)
the problem in " output = fopen(fileName, "w"); "
`
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#define BLOCK_SIZE 512
int main(int argc, char *argv[])
{
// Check command-line arguments
if (argc != 2)
{
printf("Usage: ./recover IMAGE\n");
return 1;
}
// Open files and determine scaling factor
FILE* input = fopen(argv[1], "r");
if (input == NULL)
{
printf("Could not open file.\n");
return 1;
}
FILE* output = NULL; //output_file
typedef uint8_t BYTE;
BYTE buffer[BLOCK_SIZE]; //buffer = 512
char fileName[8]; // =malloc
int count = 0; //count image
while (fread(buffer, BLOCK_SIZE, sizeof(BYTE), input))
{
if (buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff && (buffer [3] & 0xf0) == 0xe0)
{
sprintf(fileName, "%03i.jpg", count);
output = fopen(fileName, "w");
count++;
}
if (output != NULL)
{
fwrite(buffer, BLOCK_SIZE, sizeof(BYTE), output);
}
}
fclose(input);
fclose(output);
return 0;
}
`

Recover functions recovers only 4 images instead of 50

I wrote this code to recover 50 images from cs50 pset4 recover. The code can only retrieve 4 images all of which are not the right ones. It is compiling fine. When i use printf to debug it seems like the if(found) piece of code runs many times when name_count == 0 more than it is supposed to.
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
typedef uint8_t BYTE;
const int BLOCK_SIZE = 152;
bool is_a_jpeg(BYTE *buffer);
int main(int argc, char *argv[])
{
//Check if there are exactly two commandline arguments
if (argc != 2)
{
printf("usage: ./IMAGE\n");
return 1;
}
//Open a storage device and chack if it has data
FILE *input = fopen(argv[1], "r");
if (input == NULL)
{
fclose(input);
printf("Could not open file.\n");
return 2;
}
//Create a file to write into and clear it
FILE *img = NULL;
//Declar an interger of counting images
int name_count = 0;
// create buffer
BYTE buffer[BLOCK_SIZE];
//Declare space for saving the filename
char filename[8];
//Declare a bolean variable used to check for already found images
bool found = false;
//A function for reading through the device looking for images
while (fread(buffer, BLOCK_SIZE, 1, input))
{
//If a jpeg image is found notify the program(set found = true)
//and start writing the data to a new file
if (is_a_jpeg(buffer))
{
found = true;
//If we are not writing the first image, close the previous one
if (name_count > 0)
{
fclose(img);
}
//Create incrementing filenames for each new picture i.e 000.jpg, 001.jpg etc.
sprintf(filename, "%03d.jpg", name_count);
//Open an initially created empty file and start writing to it
img = fopen (filename, "w");
name_count++;
fwrite(buffer, BLOCK_SIZE, 1, img);
}
//Continue writing to a file as soon as it is found until another JPEG image is found
if(found)
{
fwrite(buffer, BLOCK_SIZE, 1, img);
}
}
//Close all the files
fclose(input);
fclose(img);
return 0;
}
//Function to check for a JPEG Image
bool is_a_jpeg(BYTE *buffer)
{
return buffer[0] == 0xff &&
buffer[1] == 0xd8 &&
buffer[2] == 0xff &&
(buffer[3] & 0xf0) == 0xe0;
}
cs50 results for check50
printing dot everytime if(found) code runs. The code unnecessarily spends a lot of time on the first image before closing it
There are some problems in the posted code:
the block size should be 512 bytes, not 152.
you should not fclose(file) if fopen failed. This has undefined behavior.
you unconditionally close img at the end, which may have undefined behavior if no JPG file was found or if the last JPG file could not be open.
both the disk image file and the jpg destination files must be open in binary mode. This may explain unexpected behavior if you are working on Windows.
Here is a modified version:
#include <errno.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
typedef uint8_t BYTE;
const int BLOCK_SIZE = 512;
bool is_a_jpeg(const BYTE *buffer);
int main(int argc, char *argv[]) {
//Check if there are exactly two commandline arguments
if (argc != 2) {
printf("usage: ./IMAGE\n");
return 1;
}
//Open a storage device and check if it has data
FILE *input = fopen(argv[1], "rb");
if (input == NULL) {
fprintf(stderr, "Could not open file %s: %s.\n", argv[1], strerror(errno));
return 2;
}
//Create a file to write into and clear it
FILE *img = NULL;
//Declare an integer of counting images
int name_count = 0;
// create buffer
BYTE buffer[BLOCK_SIZE];
//Declare space for saving the filename
char filename[16];
//A function for reading through the device looking for images
while (fread(buffer, BLOCK_SIZE, 1, input)) {
//If a jpeg image is found notify the program(set found = true)
//and start writing the data to a new file
if (is_a_jpeg(buffer)) {
//close the current image file if any
if (img) {
fclose(img);
img = NULL;
}
//Create incrementing filenames for each new picture i.e 000.jpg, 001.jpg etc.
sprintf(filename, "%03d.jpg", name_count);
name_count++;
//Create an empty file and start writing to it
img = fopen(filename, "wb");
if (img == NULL) {
fprintf(stderr, "Could not open output file %s: %s.\n", filename, strerror(errno));
}
}
//Continue writing to a file as soon as it is found until another JPEG image is found
if (img) {
if (!fwrite(buffer, BLOCK_SIZE, 1, img)) {
fprintf(stderr, "Error writing to %s: %s.\n", filename, strerror(errno));
fclose(img);
img = NULL;
}
}
}
//Close all the files
fclose(input);
if (img)
fclose(img);
return 0;
}
//Function to check for a JPEG Image
bool is_a_jpeg(const BYTE *buffer) {
return buffer[0] == 0xff &&
buffer[1] == 0xd8 &&
buffer[2] == 0xff &&
(buffer[3] & 0xf0) == 0xe0;
}

RECOVER code returns 51 jpegs and are incorrect i need some cues

So I'm trying CS50 Recover exercise (where you need to search for jpg files in a memory card and whenever you find one- you open a new file and write the jpg found to the new file). My code compiles and returns 51 jpegs instead of only 50 and all of them are incorrect. Please, I need some cues on what to focus at and fix/replace.
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
typedef uint8_t BYTE;
int main(int argc, char *argv[])
{
// Check for valid usage
if ( argc != 2)
{
printf("Usage: ./recover IMAGE\n");
return 1;
}
// Check for valid image
FILE *image = fopen(argv[1], "r");
if (image == NULL)
{
return 1;
}
BYTE buffer[512];
int i = 0;
char new_image[8];
FILE *output;
FILE *output1;
while (fread (buffer, 1, 512, image) == 512)
{
// IF Start of a JPEG
if (buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff && ((buffer[3] & 0xf0) == 0xe0))
{
sprintf(new_image, "%03i.jpg", i);
//if first JPEG
if ( i == 0)
{
output = fopen(new_image, "w");
fwrite(buffer, 512, 1, output);
i++;
}
// if not first JPEG
else
{
fclose(output);
sprintf(new_image, "%03i.jpg", i);
output1 = fopen(new_image, "w");
fwrite(buffer, 1, 512, output1);
fclose(output1);
i++;
}
}
// if not start of a JPEG
else
{
output = output1 = fopen(new_image, "w");
fwrite(buffer, 1, 512, output);
}
}
fclose(image);
}

How could count number of data blocks that have a file?

I have to make a program that extract images from a RAW file. It's specified that the system file is fat32 and blocks of data are 512 bytes. The below program works, at least with the file that is provided for testing, but when i try to use RAW files that I found on the internet, not works and yields a segmentation fault error. Valgrind report some bytes still reachable.
I think I'm reading less or more bytes that the block size for data in the file, so:
How could I know the size of each block data inside the file?
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
typedef uint8_t BYTE;
int main(int argc, char *argv[])
{
// Check for two arguments
if (argc != 2)
{
printf("Usage: ./recover image\n");
return 1;
}
// Open the forensic image
FILE *file = fopen(argv[1], "r");
if (file == NULL)
{
fprintf(stderr, "It's not possible open the file :(\n");
return 2;
}
// Initialize values
int count = 0;
BYTE buffer[512];
char filename[8];
FILE *out = NULL;
// Read blocks of data from forensic image
while (fread(&buffer, sizeof(BYTE), sizeof(buffer), file))
{
// Check if there is a JPG signature
if (buffer[0] == 0xff && buffer[1] == 0xd8
&& buffer[2] == 0xff && (buffer[3] & 0xf0) == 0xe0)
{
// If isn't first loop, close previous output file
if (count != 0)
{
fclose(out);
}
// Save name for current output file
sprintf(filename, "%03i.jpg", count++);
// Open output file
out = fopen(filename, "w");
// Check if file is right
if (out == NULL)
{
fprintf(stderr, "File could not open :(\n");
return 3;
}
// Write data to output file
fwrite(&buffer, sizeof(BYTE), sizeof(buffer), out);
}
// If isn't first loop, write data
else if (count != 0)
{
fwrite(&buffer, sizeof(BYTE), sizeof(buffer), out);
}
}
fclose(out);
fclose(file);
}

Invalid or Unsupported Image Format Recover CS50

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
int main(int argc, char *argv[])
{
// open memory card
if(argc > 2 )
{
printf("Usage: ./recover image");
return 1;
}
FILE *file = fopen(argv[1], "r");
FILE *img;
// repeat until end
int i = 0;
// 512 bytes into buffer
uint8_t buffer[2048];
char *filename = malloc(8);
// if start of new jpeg
while(fread(&buffer, 512, 4, file)) // read card
{
if(buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff && (buffer[3] & 0xf0) == 0xe0) // if start new jpeg
{
// if first
i++;
sprintf(filename, "%03i.jpg", i);
img = fopen(filename, "w");
fwrite(&buffer, sizeof(uint8_t), 1, img); // fixed
}
//else
else
{
// if still reading jpeg
if(img != NULL)
{
fwrite(&buffer, sizeof(uint8_t), 1, img);
}
}
}
//close
free(filename);
fclose(file);
return 0;
}
I think my code is pretty close to being done but the images returned are invalid or unsupported image format. It compiles fine and it returns 12 images. I do not want to look at a solution to fix this. Where did my code mess up?

Resources