Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Error when comparing array elements to constant C

Tags:

c

I'm making a program in C that tries to recover any deleted JPGs.

My overall approach is to load a block size (on FAT 512 bytes) of the file into memory to see if the JPG signature is present in the first four bytes (it's guaranteed to be in those bytes).

If the signature is present, I'll onward write chunks of 512 bytes to the file until I see another JPG etc.

Here's my code so far:

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

#include "jpg.h" /*set uint8_t to  BYTE */  

int main(int argc, char* argv[])
{
    // Opens the rFile
    FILE* rFile = fopen("card.raw", "r");

    // Checks for errors in opening rFile and terminates program
    if (rFile == NULL)
    {
        printf("Error opening rFile");
        return 0;
    }

    // Sets the blocksize (depends on the filesystem)
    int blockSize = 512;

    // allocates space for buffer on heap
    char* buf = malloc(blockSize);

    // image counter
    int icount = 0;

    // write file
    FILE* wFile = NULL; 

    // iterates through content of rFile in size buf
    while (fread(&buf, blockSize, 1, rFile))
    {

        // Check if the first four bytes are JPG signature
        if (buf[0] == 0xff && buf[1] == 0xd8 && buf[2] == 0xff
            && (buf[3] == 0xe0 || buf[3] == 0xe1))
        {
            // Close the file, if opened
            if (wFile != NULL)
                fclose(wFile);

            // Determine name of new file
            char filename[8];
            sprintf(filename, "%03d.jpg", icount);

            // Open new JPG for Writing
            wFile = fopen(filename, "w");

            // Iterates the filename icount
            icount++; 
        }

        // Write blocksize to file
        if (wFile != NULL)
            fwrite(buf, blockSize, 1, wFile);
    }

    // Close the current file if exists 
    if (wFile != NULL)
        fclose(wFile);

    // Frees buffer on heap
    free(buf);

    // Close read file
    fclose (rFile);

}

However when compiling, the compiler says it can't compare the buf[0-3] to the constants which are the signature bytes of JPGs

if (buf[0] == 0xff && buf[1] == 0xd8 && buf[2] == 0xff && (buf[3] == 0xe0 || buf[3] == 0xe1))
{
    doStuff();
{

The error I get is:

clang -ggdb3 -O0 -std=c11 -Wall -Werror -Wshadow    recover.c  -lcs50 -lm -o recover
recover.c:44:20: error: comparison of constant 255 with expression of type 'char' is always false [-Werror,-Wtautological-constant-out-of-range-compare]
        if (buf[0] == 0xff && buf[1] == 0xd8 && buf[2] == 0xff
            ~~~~~~ ^  ~~~~
recover.c:44:38: error: comparison of constant 216 with expression of type 'char' is always false [-Werror,-Wtautological-constant-out-of-range-compare]
        if (buf[0] == 0xff && buf[1] == 0xd8 && buf[2] == 0xff
                              ~~~~~~ ^  ~~~~
recover.c:44:56: error: comparison of constant 255 with expression of type 'char' is always false [-Werror,-Wtautological-constant-out-of-range-compare]
        if (buf[0] == 0xff && buf[1] == 0xd8 && buf[2] == 0xff
                                                ~~~~~~ ^  ~~~~
recover.c:45:24: error: comparison of constant 224 with expression of type 'char' is always false [-Werror,-Wtautological-constant-out-of-range-compare]
            && (buf[3] == 0xe0 || buf[3] == 0xe1))
                ~~~~~~ ^  ~~~~
recover.c:45:42: error: comparison of constant 225 with expression of type 'char' is always false [-Werror,-Wtautological-constant-out-of-range-compare]
            && (buf[3] == 0xe0 || buf[3] == 0xe1))
                                  ~~~~~~ ^  ~~~~
5 errors generated.
make: *** [recover] Error 1

EDIT:

Thank you for your help it works now. ( I changed the buffer to an unsigned char and fread(buf...) instead of fread(&buf...).

All this help has given the rise of a few new questions if any guru has the time to answer them I'd be grateful.

  • As Quentin and WhozCraig suggested, changing the char* buf into an unsigned char* buf - why is it it works when it's unsigned?
  • As MM suggested why does it give a segmentation fault using fread(&buf instead of fread(buf when reading, shouldn't &buf be pointing to the same memory?
  • As MM again suggested why and how does sprintf buffer overflow, and what exactly does "either use snprintf, or the modulus operator to limit the operand to between 0 and 999. or increase buffer size" do ?

I know these are likely stupid question, but nonetheless valuable to me.

like image 278
lux Avatar asked Jul 11 '16 08:07

lux


1 Answers

char is signed on your platform, and 0xe0 does not fit into a signed char.
Change buf's type to unsigned char.

like image 91
Quentin Avatar answered Oct 04 '22 23:10

Quentin