1

I want to read a file (plain text) and see if it contains 12 bytes of data, starting with "CLOSE" and end with "SCDH". I am using memcpy to copy over the buffer string in order to compare consecutive memory address. However, the resulting buffer, buffer_two has an extra \377 at the end. The other variable buffer is able to print out CLOSE if the passing file contains it. I am not sure why I got the extra character for buffer_two.

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

int main(int argc, char *argv[])  {
   FILE *f = fopen(argv[1], "r");
   int size;
   fseek(f, 0, SEEK_END);
   size = ftell(f);
   rewind(f);
   char *temp = malloc(sizeof(char) * size);
   fread(temp, sizeof(char), size, f);

   int i;
   for (i = 0; i < size - 12; ++i) {
      if (temp[i] == 'F') {
         char buffer[4];
         char buffer_two[4];
         memcpy(buffer, &temp[i], 4*sizeof(char));
         memcpy(buffer_two, &temp[i+8], 4*sizeof(char));
         printf("buffer %s\n", buffer);
         printf("buffer_two %s\n", buffer_two);

         if (memcmp(buffer, "CLOSE", 4) == 0 && memcmp(buffer_two, "SCDH", 4) ==0) {
            return 1;
         }

      }
   }

      return 0;
}

Here is the output from GDB after memcpy

(gdb) print buffer_two
$1 = "SCDH\377"
Kabocha Porter
  • 301
  • 3
  • 8

1 Answers1

2

memcpy does not append a '\0' to the buffer so printf can't tell where the chunk of memory that you treat as a string ends. Either add that terminating '\0' to your buffer:

char buffer[5];
...
buffer[4] = '\0';

or pass in the size to print:

printf("buffer %.*s\n", 4, buffer);

You can write 4 * sizeof(char) as just 4:

When sizeof is applied to an operand that has type char, unsigned char, or signed char, (or a qualified version thereof) the result is 1. (C.5.3.3)

Allan Wind
  • 23,068
  • 5
  • 28
  • 38
  • Thanks. I was able to fix it as you said. I assume this apply to `memcmp` as well? Is `memcmp` comparing the buffer to a string as a string comparison? I only want to print out buffer because I want to debug the function. I don't need the buffer to behave like a string. All I need to copy over 4 bytes and see if they are what I am looking for. – Kabocha Porter Mar 20 '21 at 01:58
  • memcpy takes a length as long as your both strings are at least that long you you're good. memcmp(buffer, "CLOSE", 4) look wrong. Either leave out the E or ensure buffer is 5 bytes. – Allan Wind Mar 20 '21 at 02:00
  • 1
    Also, your gdb output is not wrong, you just need to use to use `p *buffer@4` or `x/4c buffer` – Allan Wind Mar 20 '21 at 02:10
  • @chux-ReinstateMonica The point was that sizeof(char) is defined as 1. I don't get any warnings at -Wall -Wextra -pedantic for using memcpy(..., .., 4) and https://stackoverflow.com/questions/5481067/c-cast-int-to-size-t says that cast is implicit. Can you spell it out more what you were concerned about? That you can't pass a size_t for the precision field in print without a cast? You are right about that but that was opposite of what I was saying. Thanks for pointing out the missing quote and that I was missing the .* in the format string. – Allan Wind Mar 20 '21 at 06:58