Load_simple public test

Hi,

my current code doesn’t pass the “load_simple” public test. However, when I take all relevant files (wordle.c, dict.c, dict.h etc.) into an online C compiler (just for convenience so that there is no mess when experimenting) and run the below code (which resembles the “load_simple” public test), then it prints “Success”. Hence, it seems as though my code does what it is supposed to do in order to pass the “load_simple” test and I’m not sure why I’m failing the test.

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

#include "dict.h"
#include "wordle.h"

void wordle_load_simple() {
    int k = 5;
    char filename[] = "5_simple.txt";

    char *selected = malloc(k + 1);
    void *dict = generateDict(filename, k, selected, NULL);
    destroy(dict);
    
    if (strcmp("hotel", selected) == 0) {
        printf("Success");
    }
    
    free(selected);
}

int main()
{
    wordle_load_simple();
    return 0;
}

I suggest testing inside the testing infrastructure to have the added bonus of address sanitizer and other tooling.

You can/should modify and extend the unit tests.
For instance, here it might be useful to add debug information.
If the string is not equal, just print it:

        fprintf(stderr, "expected 'hotel' but got '%s'\n", selected);

after if before free.

What do you notice? How could you further refine the feedback to get more information?

2 Likes

Thanks for your feedback. Now, I see that the issue is a heap buffer overflow. I’ve actually encountered the same issue before when trying to play the game via the command line (using a different code, which passed the “load_simple” public test). Since I couldn’t figure out why I was getting the overflow, I changed my methodology but apparently I still get the same issue. The overflow error message is already quite detailed (see image below) so I’m not sure whether any more detail would help?

grafik

I guess the main components of the error message are the mentioning of specific lines in my files; those lines contain the pointer “selected”, so I presume the overflow is caused by selected. In addition, it says that the problematic address is located 0 bytes to the right of some 6-byte region. Hence, I presume that I’m accessing a location right behind the 6-byte region belonging to “selected”, which was allocated as part of malloc(k+1), with k=5 (on line 153). The other problematic line is 158 in unit_tests, which is the fprintf-statement that you suggested. On that line, I simply access “selected” so I’m not sure how I would access anything behind “selected”. Also, when writing to “selected” I only write k+1 elements. Hence, I’m confused how I’m causing an overflow.

You are right that the ASAN error (which only showed up after adding the print statement) is quite informative.
It contains all information needed to identify the error if you know what you are looking at.
But as you noticed it is otherwise a bit hard to read.

It tells you that it ran over the string into invalid memory after the string. The string is six characters long.
=> Why is it six (or k+1 in general) characters long?

You could not think about this error or you could add more debug information and think about it then.
For instance, my approach would be:

        fprintf(stderr, "got char pointer %p\n", selected); // did we accessed a NULL pointer? (ASAN already told us otherwise here so this is superfluous)
        fprintf(stderr, "str[0...4]: %c%c%c%c%c\n", selected[0], selected[1],
                selected[2], selected[3], selected[4]); // okay ASAN ran **over** the string bounds but did the string at least contained the correct characters?
        fprintf(stderr, "null terminator: %d\n", selected[5]); // now the k+1 secret is what we expect here
1 Like

Thank you very much for your help! As by your suggested fprintf-statements, the terminator turned out to be -66 (weird value). I set the last entry of “selected” to be ‘\0’, i.e. the null terminator, and now it works. I had previously only replaced newlines by the null terminator but overlooked that the last element of the dictionary isn’t terminated by a newline.

Hello Marcel,
I have been quietly reading the discussion and the string comparisons have already helped me a lot. Although I get “hotel” as a string I fail the public test. Am I missing an important point in the task?

  1. i create a trie.
  2. i insert each line of the file into the trie with the insert function.
  3. i calculate a random selected1 string.
    I also checked this one, it is “hotel” .

Do you properly store the guess into the selected1 buffer?

Yes in my own test I print printf("%s",selected1);

You’re not, actually. See Why does it say unused? - #3 by johannes

1 Like

Thanks that helped me a lot! :slight_smile: