Home > Software engineering >  Cunit test invalid read/write of size8
Cunit test invalid read/write of size8

Time:04-12

Invalid read and write of size 8 happening in modify_tab_size().

what am I doing wrong? Ive tried almost everything, I dont understand it.

Invalid read of size 8
==131939==    at 0x10ADC9: modify_tab_size (in /home/jgten/test)
...
2 errors in context 2 of 2:
==131939== Invalid write of size 8
==131939==    at 0x10ADEA: modify_tab_size (in /home/jgten/test)
// Cunit test
void test_erase_repeat_0(void) {
      int val = 3;
      int *val1 = &val;
      FILE *file = fopen("temp.txt", "w ");
      fprintf(file, "MATT MATT MIMMIE");
      rewind(file);
      char **words = calloc(3, sizeof(char *));
      place_words_in_array(file, words);
      CU_ASSERT_EQUAL(erase_repeated(val1,words), 2);
      for (int i = 0; i < 2;   i)  
        free(words[i]);  
      free(words);  
      fclose(file); 
}

// Function being tested.
int erase_repeated(int *nb_words, char **words) {
   for (int i = 0; i < *nb_words;   i) {
      if (words[i] != 0) {
         for (int b = 0; b < *nb_words;   b) {
            if (strcmp(words[i], words[b]) == 0 && b != i)
               modify_tab_size(&b, nb_words, words);
         }
      }
   }
   return *nb_mots;
}

void modify_tab_size(int *b, int *nb_words_update, char **words) {
   free(words[*b]);
   for (int k = *b; k < *nb_words_update; k  ) {
      words[k] = words[k   1];         <--------------------------read error
      words[*nb_words_update   1] = 0; <--------------------------write error
   }
   (*nb_words_update)--;
   (*b)--;
}

int place_words_in_array(FILE *file, char **words) {
   int position = 0;
   char line[80];
   while (fgets(line, 80, file)) {
      char *word = strtok(line, " ,.-\n");
      while (word != NULL) {
         words[position  ] = strdup(word);
         word = strtok(NULL, " ,.-\n");
      }
   }
   return position != 0;
}

CodePudding user response:

The problem is k 1 and *nb_words_update 1 can walk off the array, and it is. Add printf("k:%d, k 1:%d, *nb_words_update 1: %d\n", k, k 1, *nb_words_update 1); into the loop to see.

k:1, k 1:2, *nb_words_update   1: 4
k:2, k 1:3, *nb_words_update   1: 4

You've only allocated three slots, 3 and 4 walk off the end of the array.

Since nb_words_update starts as the length of the array, words[*nb_words_update 1] = 0; is always going to be too large. words[*nb_words_update] = 0; is also too large.

What you seem to be trying to do is deleting an element from an array by shifting everything after it to the left.

void delete_element(char **words, int *b, int *size) {
    // Free the string to be deleted.
    free(words[*b]);

    // Only go up to the second to last element to avoid walking off the array.
    for (int i = *b; i < *size-1; i  ) {
        // Shift everything to the left.
        words[i] = words[i 1];
    }

    // Null out the last element.
    // Don't use 0 for NULL, it's confusing.
    words[*size-1] = NULL;

    // Decrement the size of the array.
    (*size)--;

    // Redo the check with the newly shifted element.
    (*b)--;
}

This sort of thing is better done with a linked list.


Note that your code has a bug. The result is an array of two elements, but one of them is blank. In addition to the return value of erase_repeated, also test its side effect which is to modify words. Test that words contains what you think it does.

  •  Tags:  
  • c
  • Related