Did you twist my words? Challenge
Given two strings, determine if the second string is a rotation of the first.
Specifications

The first argument is a path to a file.
The file contains multiple lines.
Each line is a test case represented by two comma separated strings.
For each test case print out True/False if the second string is a rotation of the first.

Sample Input

Code,deCo
Review,wRevie
testcase,casetoast

Sample Output

True
True
False

Source
My solution
#include &lt;stdbool.h&gt;
#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;string.h&gt;

#define LINE_LENGTH 64

char* str_mul(char* str, int times) {
    char *string_multiplied = malloc(sizeof(str) * times + 1);
    for (int i = 1; i &lt;= times; i++) {
        strcat(string_multiplied, str);
    }
    return string_multiplied;    
}

bool is_rotated(char *original, char *test_case) {
    int original_length = strlen(original);
    char *rotation_superset = str_mul(original, 2);
    bool is_substring = strstr(rotation_superset, test_case) != NULL;
    return original_length == strlen(test_case) &amp;&amp; is_substring;
}

char* parse_and_evaluate(char *line) {
    const char tokens[] = &quot;,\n\r&quot;;
    char *original = strtok(line, tokens);
    char *test_case = strtok(NULL, tokens);
    return is_rotated(original, test_case) ? &quot;True&quot; : &quot;False&quot;;
}

int main(int argc, char *args[]) {
    if (argc &lt; 2) {
        fprintf(stderr, &quot;File path not provided. Exiting...\n&quot;);
        return 1;
    }

    if (argc &gt; 2) {
        puts(&quot;Excessive arguments, only the first will be considered.&quot;);
    }

    FILE *file = fopen(args[1], &quot;r&quot;);
    if (file == NULL) {
        perror(&quot;Error&quot;);
        return 1;
    }

    char line[LINE_LENGTH];
    while (fgets(line, LINE_LENGTH, file)) {
        printf(&quot;%s\n&quot;, parse_and_evaluate(line));
    }

    fclose(file);
}
You're bleeding memory for every line in the file.  This is probably ok for the challenge, however it's a good idea to get into the habit of cleaning up after yourself.

The call to malloc in str_mul needs to have a corresponding free call somewhere to release the memory.  Looking at your program in it's current state, the easiest way to do that is probably in the is_rotated method like so:

bool is_rotated(char *original, char *test_case) {
    int original_length = strlen(original);
    char *rotation_superset = str_mul(original, 2);
    bool is_substring = strstr(rotation_superset, test_case) != NULL;
    free(rotation_superset);
    return original_length == strlen(test_case) &amp;&amp; is_substring;
}


I'd be tempted to actually move the malloc into the same method and pass the buffer into the str_mul method so that the allocation and release are at the same level.  This would also allow you to simply declare a local on the stack in is_rotated, rather than needing to use malloc:

void str_mul(char* str, char *string_multiplied, int times) {
    string_multiplied[0] = '\0';
    for (int i = 1; i &lt;= times; i++) {
        strcat(string_multiplied, str);
    }
}

bool is_rotated(char *original, char *test_case) {
    int original_length = strlen(original);
    char rotation_superset[LINE_LENGTH*2];
    str_mul(original, rotation_superset, 2);
    bool is_substring = strstr(rotation_superset, test_case) != NULL;
    return original_length == strlen(test_case) &amp;&amp; is_substring;
}


malloc Vs calloc

malloc isn't guaranteed to return zero initialized memory.  Since you're using strcat to append to the buffer, you should really ensure that the memory is a null terminated array.  You can either do that by initially null terminating it (as in my example above), or by using calloc instead.