Summary
At pin 4a7456e2, next_token enters the number branch when the next byte is a digit or '.', then calls strtod (tinyexpr.c:250-252). strtod honours LC_NUMERIC. After setlocale to a comma-decimal locale, expressions that are valid in the C locale fail to parse.
This is a correctness bug for any host that calls setlocale. It is not a hang/DoS in our measurements: parse returns an error. Env-only LC_ALL=de_DE.UTF-8 without setlocale does not trigger it, because the process stays in the C locale (the upstream smoke suite never calls setlocale either).
Observed behaviour
macOS 15.1.1 / Apple clang 16 and Ubuntu 24.04 aarch64 / gcc 13.3, after setlocale(LC_ALL, "de_DE.UTF-8") (or fr_FR.UTF-8):
| Expression |
err |
notes |
1.5 |
1 |
nan; valid in C locale |
.5 |
1 |
completes; no hang within the run |
1,5 |
0 |
value 1.5 (comma accepted) |
2.25+3.5 |
1 |
fails |
Under setlocale(LC_ALL, "C"), 1.5 and 2.25+3.5 succeed.
Expected behaviour
For a math expression library, decimal-point tokenization should follow a fixed convention (typically C-locale '.'), or the docs should state that callers must keep LC_NUMERIC at "C".
Root cause
if ((s->next[0] >= '0' && s->next[0] <= '9') || s->next[0] == '.') {
s->value = strtod(s->next, (char**)&s->next);
s->type = TOK_NUMBER;
}
The '.' trigger is locale-independent; strtod is not.
Minimal reproducer
#include <locale.h>
#include <stdio.h>
#include "tinyexpr.h"
int main(void) {
setlocale(LC_ALL, "de_DE.UTF-8");
int err = 0;
double v = te_interp("1.5", &err);
printf("err=%d value=%.17g\n", err, v);
return 0;
}
Note on hang hypothesis
We also checked whether a non-advancing strtod on ".5" under a comma locale could loop forever. On the platforms above, te_interp(".5") returned err=1 and completed. So we are filing a locale correctness issue, not a DoS.
Summary
At pin
4a7456e2,next_tokenenters the number branch when the next byte is a digit or'.', then callsstrtod(tinyexpr.c:250-252).strtodhonoursLC_NUMERIC. Aftersetlocaleto a comma-decimal locale, expressions that are valid in the C locale fail to parse.This is a correctness bug for any host that calls
setlocale. It is not a hang/DoS in our measurements: parse returns an error. Env-onlyLC_ALL=de_DE.UTF-8withoutsetlocaledoes not trigger it, because the process stays in the C locale (the upstreamsmokesuite never callssetlocaleeither).Observed behaviour
macOS 15.1.1 / Apple clang 16 and Ubuntu 24.04 aarch64 / gcc 13.3, after
setlocale(LC_ALL, "de_DE.UTF-8")(orfr_FR.UTF-8):1.5.51,52.25+3.5Under
setlocale(LC_ALL, "C"),1.5and2.25+3.5succeed.Expected behaviour
For a math expression library, decimal-point tokenization should follow a fixed convention (typically C-locale
'.'), or the docs should state that callers must keepLC_NUMERICat"C".Root cause
The
'.'trigger is locale-independent;strtodis not.Minimal reproducer
Note on hang hypothesis
We also checked whether a non-advancing
strtodon".5"under a comma locale could loop forever. On the platforms above,te_interp(".5")returnederr=1and completed. So we are filing a locale correctness issue, not a DoS.