codeplea / tinyexpr

tiny recursive descent expression parser, compiler, and evaluation engine for math expressions
https://codeplea.com/tinyexpr
zlib License
1.61k stars 245 forks source link

Segfault when two variables follow each other #112

Closed Sercurio closed 7 months ago

Sercurio commented 7 months ago

Hi, When trying to compile and evaluate that kind of expression "xx + 1", we got a segfault instead of compile error

codeplea commented 7 months ago

I'm stating the obvious here, but it's impossible to help you if you don't post your code. Post the most minimal complete example that demonstrates your problem.

Sercurio commented 7 months ago
int main()
{
    int t = 0;
    te_expr *expr;
    int err = 0;

    te_variable vars[] = {{"t", &t, TE_VARIABLE}};

    int FORMULA_SIZE = 126;
    char formula[FORMULA_SIZE];
    memset(formula, 0, FORMULA_SIZE);
    char *initStr = "tt + 0";
    strncpy(formula, initStr, strlen(initStr));
    for (int i = 0; i < FORMULA_SIZE; i++)
    {
        if (formula[i] == '\0')
        {
            formula[i] = ' ';
        }
    }
    formula[FORMULA_SIZE - 1] = 0;

    while (t < 100000)
    {
        int varsCount = 0;
        for (int i = 0; i < FORMULA_SIZE; i++)
        {
            if (formula[i] == 't')
                varsCount++;
        }

        printf("vars: %d\n", varsCount);
        printf("tinyExpr formula: %s\n", formula);

        expr = te_compile(formula, vars, varsCount, 0);

        if (expr)
        {
            unsigned char result = te_eval(expr);
        }
        else
        {
            printf("parse error at %d\n", err);
        }
        t++;
    }

    te_free(expr);
}

When changing the variable initStr to ""t t + 0", we got the parse error, but when ""tt + 0", segmentation fault

codeplea commented 7 months ago

It's because you're making varCount = 2, when vars has only one element. If you tell tinyexpr that there are two elements in vars, it'll try to access the second element, which will segfault, because the second element does not exist. If the length of vars is 1, then you should always tell tinyexpr that it is 1.

This section of code is nonsense:

int varsCount = 0;
        for (int i = 0; i < FORMULA_SIZE; i++)
        {
            if (formula[i] == 't')
                varsCount++;
        }

It should just be:

int varCount = 1;

Let me give you some debugging advice. This is why I asked for the "most minimal complete example". If you tried reducing your code down to the minimal example that still shows the error, you would have spotted the error easily. This is the "most minimal complete example," that I asked for, and it makes the error completely obvious:

te_variable vars[] = {{"t", &t, TE_VARIABLE}};
expr = te_compile("tt + 0", vars, 2, 0); //seg fault

I asset that this will work without segfault:

te_variable vars[] = {{"t", &t, TE_VARIABLE}};
expr = te_compile("tt + 0", vars, 1, 0); //no seg fault
Sercurio commented 7 months ago

Oh ok thank you !