1

I've been asked to analyze some C code with Flawfinder:

char * buffer;
size_t len;
// my_fd is a file descriptor
read(my_fd, &len, sizeof(len));
buffer = malloc(len + 1);
read(my_fd, buffer, len);
buffer[len] = '\0';

I get the following warnings on the 2 read:

test.c:xx:  [1] (buffer) read:
  Check buffer boundaries if used in a loop including recursive loops
  (CWE-120, CWE-20).
test.c:xx:  [1] (buffer) read:
  Check buffer boundaries if used in a loop including recursive loops
  (CWE-120, CWE-20). 

I tried following this answer, modifying the function as follows:

char * buffer;
size_t len;
// my_fd is a file descriptor
ssize_t ret = read(my_fd, &len, sizeof(len));

if (ret == -1 || ret != sizeof len) {
     buffer = NULL;
} else {
     buffer = malloc(len + 1);
     ret = read(my_fd, buffer, len);
     buffer[ret] = '\0';
}
free(buffer);

But the vulnerabilities are still detected. What am I missing?

Update #1:

I updated the function according to @4386427 suggestions, checking both read() and malloc():

char * buffer = NULL;
size_t len;
ssize_t ret = read(my_fd, &len, sizeof(len));

if (ret == sizeof len)
{
     buffer = malloc(len + 1);

     if (buffer != NULL)
     {
          ret = read(my_fd, buffer, len);

          if (ret == len)
          {
               buffer[ret] = '\0';
          }
          free(buffer);
     }
}

But nothing has changed, how can i further improve security?

Update #2

Because Flawfinder only does pattern check, and because it seems that no more improvements can be applied; at this point I'm marking these errors as false positive.

LucaBonadia
  • 91
  • 2
  • 12

1 Answers1

2

I see two places in your last code snippet where you don't handle return values correct. 1) You don't check the malloc 2) You don't check the read

Try:

char * buffer;
size_t len;
// my_fd is a file descriptor
ssize_t ret = read(my_fd, &len, sizeof(len));

if (ret != sizeof len) {
     buffer = NULL;
} else {
    buffer = malloc(len + 1);
    if (buffer != NULL)        // Check that malloc was ok
    {
         ret = read(my_fd, buffer, len);

         if (ret == -1)        // Check that read was ok
         {
             // error handling....
             //
             // for now just do:
             ret = 0;
         }
         else if (ret != len)
         {
             // Didn't get as much data as expected
             //
             // Add some error handling....
         }
         buffer[ret] = '\0';
    }
}
free(buffer);
Support Ukraine
  • 42,271
  • 4
  • 38
  • 63