-
Notifications
You must be signed in to change notification settings - Fork 589
Closed
Description
A static analysis on 5.31.1 sources claims that an uninitialized curlocales[] member in locale.c:Perl_init_i18nl10n() can be passed to Safefree(). I believe that that the same flaw exists in the blead sources:
if (ok < 1) { /* If we tried to fallback */
const char* msg;
if (! setlocale_failure) { /* fallback succeeded */
msg = "Falling back to";
}
else { /* fallback failed */
unsigned int j;
/* We dropped off the end of the loop, so have to decrement i to
* get back to the value the last time through */
i--;
ok = -1;
msg = "Failed to fall back to";
/* To continue, we should use whatever values we've got */
for (j = 0; j < NOMINAL_LC_ALL_INDEX; j++) {
→ Safefree(curlocales[j]);
curlocales[j] = savepv(do_setlocale_r(categories[j], NULL));
DEBUG_LOCALE_INIT(categories[j], NULL, curlocales[j]);
}
}
There are only two places where curlocales[] members are initialized:
A place guarded with:
if (i == 0) {
unsigned int j;
if (locwarn) { /* Output failure info only on the first one *
branch. init_i18nl10n() can be called by XS code via init_i18nl14n(aTHX, 0) that will bypass this branch.
And the second place of the initialization is just above that:
# ifdef LC_ALL
sl_result[LC_ALL_INDEX] = do_setlocale_c(LC_ALL, trial_locale);
DEBUG_LOCALE_INIT(LC_ALL, trial_locale, sl_result[LC_ALL_INDEX]);
if (! sl_result[LC_ALL_INDEX]) {
setlocale_failure = TRUE;
}
else {
/* Since LC_ALL succeeded, it should have changed all the other
* categories it can to its value; so we massage things so that the
* setlocales below just return their category's current values.
* This adequately handles the case in NetBSD where LC_COLLATE may
* not be defined for a locale, and setting it individually will
* fail, whereas setting LC_ALL succeeds, leaving LC_COLLATE set to
* the POSIX locale. */
trial_locale = NULL;
}
# endif /* LC_ALL */
if (! setlocale_failure) {
unsigned int j;
for (j = 0; j < NOMINAL_LC_ALL_INDEX; j++) {
curlocales[j]
= savepv(do_setlocale_r(categories[j], trial_locale));
if (! curlocales[j]) {
setlocale_failure = TRUE;
}
DEBUG_LOCALE_INIT(categories[j], trial_locale, curlocales[j]);
}
if (! setlocale_failure) { /* All succeeded */
break; /* Exit trial_locales loop */
}
}
If the setlocale_failure is true, e.g. set in the quoted (! sl_result[LC_ALL_INDEX]) condition, then it's possible to never initialize the members of the array.
Metadata
Metadata
Assignees
Labels
No labels