Search code examples
cgccbinaryfread

correct way to copy binary file to buffer in c


I'm trying to open a bin file an get its data into a buffer and copy the data from that buffer to a section that I made called .my_data. When I do hexdump binfile.bin I see

   00000000 4455 e589 00bf 0000 e800 0000 00b8
   00000010 5d00 00c3
   00000015

and when I printf the buffer and buffer2 I see

   55 48 89 e5 bf 00 00 00 00 e8 00 00 00 00 b8 00 00 00 00 5d c3 

   55 48 89 e5 bf 00 00 00 00 e8 00 00 00 00 b8 00 00 00 00 5d c3

which matches the output from hexdump. However when load buffer2 into my new section (I didn't include that part of the code), I used objdump -s -j .my_data foo and I see some other data not similar to the output above.

I apologize for the dumb question but I just want to confirm if the memcpy I used it's actually copying the data from buffer to buffer2 so I can discard this part and look for the error in the rest of my program. From the output of the second for loop I would think it is. I'm also using gcc, thanks.

   #include <stdio.h>
   #include <stdint.h>
   #include <string.h>
   #include <stdlib.h>
   
   int main (){

   uint8_t buffer[21];
   uint8_t buffer2[21];
   FILE *ptr;
   ptr = fopen("binfile.bin", "rb");
   size_t file_size = 0;
   
   if(!ptr)
   {
     printf("unable to open file");
     return 1;
   }

   fseek(ptr, 0, SEEK_END);
   file_size = ftell(ptr); 
   rewind(ptr);

   int i = 0;
   
   fread(buffer, sizeof(buffer), 1, ptr);
   memcpy(buffer2, buffer, sizeof(buffer));

   for(i = 0; i < 21; i++)
   {
    printf("%02x ", buffer[i]);
   }

   printf("\n\n");
   for(i = 0; i < 21; i++)
   {
    printf("%02x ", buffer2[i]);
   }

   fclose(ptr);
  
   return 0;

   }

    

Solution

  • You are thinking right as far as how you are approaching copying buffer to buffer2, but you are failing to ensure you only attempt to access the elements of buffer that are validly initialized. Since your file contains only 20 bytes, when you attempt to access buffer[20] you are attempting to access a variable with automatic storage duration while the value is indeterminate invoking Undefined Behavior. All bets are off.

    You can handle this by fully initializing buffer, e.g.

    uint8_t buffer[21] = {0);
    

    which if you fill less than all elements with fread is still okay because all elements are validly initialized.

    The other way is simply to read with the size parameter to fread set at 1 so fread returns the number of bytes read. Then you can use that value to output your results, e.g.

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    #define MAXC 1024       /* max number of characters (bytes) */
    
    int main (int argc, char **argv) {
        
        size_t nbytes = 0;
        unsigned char buf1[MAXC] = {0}, buf2[MAXC] = {0};
        /* use filename provided as 1st argument (stdin by default) */
        FILE *fp = argc > 1 ? fopen (argv[1], "rb") : stdin;
        
        if (!fp) {  /* validate file open for reading */
            perror ("file open failed");
            return 1;
        }
        
        nbytes = fread (buf1, 1, MAXC, fp);     /* with size=1, no. of bytes returned */
        
        if (fp != stdin)                        /* close file if not stdin */
            fclose (fp);
        
        memcpy (buf2, buf1, nbytes);            /* copy nbytes buf1, buf2 */
        
        for (size_t i = 0; i < nbytes; i++)     /* outuput buf1 contents */
            printf (" %02x", buf1[i]);
        putchar ('\n');
    
        for (size_t i = 0; i < nbytes; i++)     /* output buf2 contents */
            printf (" %02x", buf2[i]);
        putchar ('\n');
    }
    

    Example Use/Output

    With your data in the file dat/bytes20.bin, you would receive:

    $ ./bin/fread_bytes dat/bytes20.bin
     44 55 e5 89 00 bf 00 00 e8 00 00 00 00 b8 5d 00 00 c3
     44 55 e5 89 00 bf 00 00 e8 00 00 00 00 b8 5d 00 00 c3
    

    Let me know if you have further questions.