commit 4c35fa8e416d950cd5c72f9f240149bd4307a62e Author: Tim Hentenaar Date: Sun, 29 Mar 2026 04:51:14 -0400 fix: XmString: improve locale string handling (#16) commit ec89134f090fc50a25dbcd77993de81ebe39e10a Author: Tim Hentenaar Date: Sun, 29 Mar 2026 13:51:48 -0400 XmString: ensure the locale string is null terminated --- a/lib/Xm/XmString.c +++ b/lib/Xm/XmString.c @@ -5191,40 +5191,35 @@ return(can_do); } -static void _parse_locale(char *str, int *indx, int *len) +/** + * Parse a locale string, yielding the index and length of the character + * set identifier therein. + */ +static void _parse_locale(char *str, int *idx, int *len) { - char *temp; - int start; - int end; - - /* - * Set the return variables to zero. If we find what we're looking - * for, we reset them. - */ + int end = 0; + char *tmp = str; - *indx = 0; - *len = 0; - if (!str) return; + *idx = 0; + *len = 0; + if (!str || !*str || *str == '@' || *str == ';') + return; - /* - * The format of the locale string is: - * language[_territory[.codeset]] - */ + /** + * Locale identifiers are formatted as: + * language[_territory][.codeset][@modifier] + */ + while (tmp[end] && tmp[end] != '.' && tmp[end] != '@' && tmp[end] != ';') + end++; - temp = str; - end = 0; - while ((temp[end] != '.') && (temp[end] != 0)) - end++; + /* Bail if we didn't get a codeset */ + if (tmp[end++] != '.') + return; - if (temp[end] == '.') - { - start = end + 1; - *indx = start; - end = start; - while (temp[end] != 0) - end++; - *len = end - start; - } + /* Look for the end of the codeset */ + *idx = end; + while (tmp[end] && tmp[end] != '@' && tmp[end] != ';') end++; + *len = end - *idx; } void _XmStringSetLocaleTag(const char *lang) @@ -5268,8 +5263,10 @@ len = 5; } - locale.tag = XtNewString(str); - locale.ctype = XtNewString(ct); + locale.tag = XtCalloc(locale.taglen + 1, 1); + locale.ctype = XtCalloc(len + 1, 1); + memcpy(locale.tag, str, locale.taglen); + memcpy(locale.ctype, ct, len); _XmProcessUnlock(); }