Repository: valkey-io/valkey
File: src/util.c (C)

Code before:
        patternLen--;
        if (stringLen == 0) {
            while (patternLen && *pattern == '*') {
                pattern++;
                patternLen--;
            }
            break;
        }
    }
    if (patternLen == 0 && stringLen == 0) return 1;
    return 0;
}

int stringmatchlen(const char *pattern, int patternLen, const char *string, int stringLen, int nocase) {
    int skipLongerMatches = 0;
    return stringmatchlen_impl(pattern, patternLen, string, stringLen, nocase, &skipLongerMatches, 0);
}

int stringmatch(const char *pattern, const char *string, int nocase) {
    return stringmatchlen(pattern, strlen(pattern), string, strlen(string), nocase);
}

int prefixmatchlen(const char *pattern, int patternLen, const char *string, int stringLen, int nocase) {
    if (patternLen == 1 && pattern[0] == '*') {
        // Minor optimization: fast path: avoid calling "stringmatchlen" if the input pattern is exactly "*":
        // We always return 1 in this case.
        return 1;
    } else if (patternLen > 0 && pattern[patternLen - 1] != '*') {
        // Reject the pattern if it doesn't end with '*'
        return 0;
    } else {
        // Call existing string match algorithm
        return stringmatchlen(pattern, patternLen, string, stringLen, nocase);
    }
}

/* Fuzz stringmatchlen() trying to crash it with bad input. */
int stringmatchlen_fuzz_test(void) {
    char str[32];
    char pat[32];
    int cycles = 10000000;
    int total_matches = 0;
    while (cycles--) {
        int strlen = rand() % sizeof(str);
        int patlen = rand() % sizeof(pat);
        for (int j = 0; j < strlen; j++) str[j] = rand() % 128;
        for (int j = 0; j < patlen; j++) pat[j] = rand() % 128;
        total_matches += stringmatchlen(pat, patlen, str, strlen, 0);
    }
    return total_matches;
}

Review comment (suggestion):
```suggestion
        /* Minor optimization: fast path: avoid calling "stringmatchlen" if the input pattern is exactly "*":
         * We always return 1 in this case. */
```

Code after:
        patternLen--;
        if (stringLen == 0) {
            while (patternLen && *pattern == '*') {
                pattern++;
                patternLen--;
            }
            break;
        }
    }
    if (patternLen == 0 && stringLen == 0) return 1;
    return 0;
}

int stringmatchlen(const char *pattern, int patternLen, const char *string, int stringLen, int nocase) {
    int skipLongerMatches = 0;
    return stringmatchlen_impl(pattern, patternLen, string, stringLen, nocase, &skipLongerMatches, 0);
}

int stringmatch(const char *pattern, const char *string, int nocase) {
    return stringmatchlen(pattern, strlen(pattern), string, strlen(string), nocase);
}

int prefixmatchlen(const char *pattern, int patternLen, const char *string, int stringLen, int nocase) {
    if (patternLen == 1 && pattern[0] == '*') {
        /* Minor optimization: fast path: avoid calling "stringmatchlen" if the input pattern is exactly "*":
         * We always return 1 in this case. */
        return 1;
    } else if (patternLen > 0 && pattern[patternLen - 1] != '*') {
        /* Reject the pattern if it doesn't end with '*' */
        return 0;
    } else {
        /* Call existing string match algorithm */
        return stringmatchlen(pattern, patternLen, string, stringLen, nocase);
    }
}

/* Fuzz stringmatchlen() trying to crash it with bad input. */
int stringmatchlen_fuzz_test(void) {
    char str[32];
    char pat[32];
    int cycles = 10000000;
    int total_matches = 0;
    while (cycles--) {
        int strlen = rand() % sizeof(str);
        int patlen = rand() % sizeof(pat);
        for (int j = 0; j < strlen; j++) str[j] = rand() % 128;
        for (int j = 0; j < patlen; j++) pat[j] = rand() % 128;
        total_matches += stringmatchlen(pat, patlen, str, strlen, 0);
    }
    return total_matches;
}