From fe9a9d5bc504712effcb45b218d52d5e0d6c480a Mon Sep 17 00:00:00 2001 From: ache Date: Sun, 4 Aug 2002 14:03:59 +0000 Subject: Try harder to check lang as path component (".", "..", / inside). Try harder to not overwrite failure errno. style(9) whitespace reformatting for code readability. --- lib/libc/nls/msgcat.c | 652 ++++++++++++++++++++++++++------------------------ 1 file changed, 345 insertions(+), 307 deletions(-) (limited to 'lib') diff --git a/lib/libc/nls/msgcat.c b/lib/libc/nls/msgcat.c index ff60122..570dd10 100644 --- a/lib/libc/nls/msgcat.c +++ b/lib/libc/nls/msgcat.c @@ -53,6 +53,7 @@ __FBSDID("$FreeBSD$"); #include "un-namespace.h" #include "msgcat.h" +#include "../locale/setlocale.h" /* for ENCODING_LEN */ #define _DEFAULT_NLS_PATH "/usr/share/nls/%L/%N.cat:/usr/share/nls/%N/%L:/usr/local/share/nls/%L/%N.cat:/usr/local/share/nls/%N/%L" @@ -60,125 +61,133 @@ __FBSDID("$FreeBSD$"); #define FALSE 0 #define NLERR ((nl_catd) -1) -#define NLRETERR(errc) errno = errc; return(NLERR); +#define NLRETERR(errc) { errno = errc; return (NLERR); } -static nl_catd loadCat(); -static int loadSet(); -static void __nls_free_resources(); +static nl_catd loadCat(); +static int loadSet(); +static void __nls_free_resources(); nl_catd -catopen( name, type) - __const char *name; - int type; +catopen(name, type) + __const char *name; + int type; { - int spcleft; - char path[PATH_MAX]; - char *nlspath, *lang, *base, *cptr, *pathP, *tmpptr; - char *cptr1, *plang, *pter, *pcode; - struct stat sbuf; + int spcleft, saverr; + char path[PATH_MAX]; + char *nlspath, *lang, *base, *cptr, *pathP, *tmpptr; + char *cptr1, *plang, *pter, *pcode; + struct stat sbuf; + + if (name == NULL || *name == '\0') + NLRETERR(EINVAL); + + /* is it absolute path ? if yes, load immediately */ + if (strchr(name, '/') != NULL) + return (loadCat(name)); + + if (type == NL_CAT_LOCALE) + lang = setlocale(LC_MESSAGES, NULL); + else + lang = getenv("LANG"); + + if (lang == NULL || *lang == '\0' || strlen(lang) > ENCODING_LEN || + (lang[0] == '.' && + (lang[1] == '\0' || (lang[1] == '.' && lang[2] == '\0'))) || + strchr(lang, '/') != NULL) + lang = "C"; + + if ((plang = cptr1 = strdup(lang)) == NULL) + return (NLERR); + if ((cptr = strchr(cptr1, '@')) != NULL) + *cptr = '\0'; + pter = pcode = ""; + if ((cptr = strchr(cptr1, '_')) != NULL) { + *cptr++ = '\0'; + pter = cptr1 = cptr; + } + if ((cptr = strchr(cptr1, '.')) != NULL) { + *cptr++ = '\0'; + pcode = cptr; + } - if (name == NULL || *name == '\0') { - NLRETERR(ENOENT); - } - - /* is it absolute path ? if yes, load immidiately */ - if (strchr(name, '/')) - return loadCat(name); - - if (type == NL_CAT_LOCALE) - lang = setlocale(LC_MESSAGES, NULL); - else - lang = getenv("LANG"); - if (lang == NULL || *lang == '\0' || strchr(lang, '/') != NULL) - lang = "C"; - - if ((plang = cptr1 = strdup(lang)) == NULL) - return (NLERR); - if ((cptr = strchr(cptr1, '@')) != NULL) - *cptr = '\0'; - pter = pcode = ""; - if ((cptr = strchr(cptr1, '_')) != NULL) { - *cptr++ = '\0'; - pter = cptr1 = cptr; - } - if ((cptr = strchr(cptr1, '.')) != NULL) { - *cptr++ = '\0'; - pcode = cptr; - } - - if ((nlspath = getenv("NLSPATH")) == NULL + if ((nlspath = getenv("NLSPATH")) == NULL #ifndef __NETBSD_SYSCALLS - || issetugid() + || issetugid() #endif - ) - nlspath = _DEFAULT_NLS_PATH; + ) + nlspath = _DEFAULT_NLS_PATH; + + if ((base = cptr = strdup(nlspath)) == NULL) { + saverr = errno; + free(plang); + errno = saverr; + return (NLERR); + } - if ((base = cptr = strdup(nlspath)) == NULL) { - free(plang); - return (NLERR); - } - - while ((nlspath = strsep(&cptr, ":")) != NULL) { - pathP = path; - if (*nlspath) { - for ( ; *nlspath; ++nlspath) { - if (*nlspath == '%') { - switch (*(nlspath + 1)) { - case 'l': - tmpptr = plang; - break; - case 't': - tmpptr = pter; - break; - case 'c': - tmpptr = pcode; - break; - case 'L': - tmpptr = lang; - break; - case 'N': - tmpptr = (char*)name; - break; - case '%': - ++nlspath; - /* fallthrough */ - default: - if (pathP - path >= sizeof(path) - 1) - goto too_long; - *(pathP++) = *nlspath; - continue; + while ((nlspath = strsep(&cptr, ":")) != NULL) { + pathP = path; + if (*nlspath) { + for (; *nlspath; ++nlspath) { + if (*nlspath == '%') { + switch (*(nlspath + 1)) { + case 'l': + tmpptr = plang; + break; + case 't': + tmpptr = pter; + break; + case 'c': + tmpptr = pcode; + break; + case 'L': + tmpptr = lang; + break; + case 'N': + tmpptr = (char *)name; + break; + case '%': + ++nlspath; + /* fallthrough */ + default: + if (pathP - path >= + sizeof(path) - 1) + goto too_long; + *(pathP++) = *nlspath; + continue; + } + ++nlspath; + put_tmpptr: + spcleft = sizeof(path) - + (pathP - path) - 1; + if (strlcpy(pathP, tmpptr, spcleft) >= + spcleft) { + too_long: + free(plang); + free(base); + NLRETERR(ENAMETOOLONG); + } + pathP += strlen(tmpptr); + } else { + if (pathP - path >= sizeof(path) - 1) + goto too_long; + *(pathP++) = *nlspath; + } } - ++nlspath; - put_tmpptr: - spcleft = sizeof(path) - (pathP - path) - 1; - if (strlcpy(pathP, tmpptr, spcleft) >= spcleft) { - too_long: + *pathP = '\0'; + if (stat(path, &sbuf) == 0) { free(plang); free(base); - NLRETERR(ENAMETOOLONG); + return (loadCat(path)); } - pathP += strlen(tmpptr); - } else { - if (pathP - path >= sizeof(path) - 1) - goto too_long; - *(pathP++) = *nlspath; - } - } - *pathP = '\0'; - if (stat(path, &sbuf) == 0) { - free(plang); - free(base); - return loadCat(path); + } else { + tmpptr = (char *)name; + --nlspath; + goto put_tmpptr; } - } else { - tmpptr = (char*)name; - --nlspath; - goto put_tmpptr; } - } - free(plang); - free(base); - NLRETERR(ENOENT); + free(plang); + free(base); + NLRETERR(ENOENT); } /* @@ -202,97 +211,105 @@ catopen( name, type) * */ -#define LOOKUP(PARENT, CHILD, ID, NUM, SET) { \ - lo = 0; \ - if (ID - 1 < PARENT->NUM) { \ - cur = ID - 1; hi = ID; \ - } else { \ - hi = PARENT->NUM; cur = (hi - lo) / 2; \ - } \ - while (TRUE) { \ - CHILD = PARENT->SET + cur; \ - if (CHILD->ID == ID) break; \ - if (CHILD->ID < ID) { \ - lo = cur+1; \ - if (hi > cur+(ID-CHILD->ID)+1) \ - hi = cur+(ID-CHILD->ID)+1; \ - dir = 1; \ - } else { \ - hi = cur; dir = -1; \ - } \ - if (lo >= hi) return(NULL); \ - if (hi - lo == 1) cur += dir; \ - else cur += ((hi - lo) / 2) * dir; \ - } \ - } - -static MCSetT* -MCGetSet( cat, setId) - MCCatT *cat; - int setId; -{ - MCSetT *set; - long lo, hi, cur, dir; - - if (cat == NULL || setId <= 0) return(NULL); - LOOKUP(cat, set, setId, numSets, sets); - if (set->invalid && loadSet(cat, set) <= 0) - return(NULL); - return(set); +#define LOOKUP(PARENT, CHILD, ID, NUM, SET) { \ + lo = 0; \ + if (ID - 1 < PARENT->NUM) { \ + cur = ID - 1; \ + hi = ID; \ + } else { \ + hi = PARENT->NUM; \ + cur = (hi - lo) / 2; \ + } \ + while (TRUE) { \ + CHILD = PARENT->SET + cur; \ + if (CHILD->ID == ID) \ + break; \ + if (CHILD->ID < ID) { \ + lo = cur + 1; \ + if (hi > cur + (ID - CHILD->ID) + 1) \ + hi = cur + (ID - CHILD->ID) + 1; \ + dir = 1; \ + } else { \ + hi = cur; \ + dir = -1; \ + } \ + if (lo >= hi) \ + return (NULL); \ + if (hi - lo == 1) \ + cur += dir; \ + else \ + cur += ((hi - lo) / 2) * dir; \ + } \ } +static MCSetT * +MCGetSet(cat, setId) + MCCatT *cat; + int setId; +{ + MCSetT *set; + long lo, hi, cur, dir; + + if (cat == NULL || setId <= 0) + return (NULL); + LOOKUP(cat, set, setId, numSets, sets); + if (set->invalid && loadSet(cat, set) <= 0) + return (NULL); + return (set); +} -static MCMsgT* -MCGetMsg( set, msgId) - MCSetT *set; - int msgId; +static MCMsgT * +MCGetMsg(set, msgId) + MCSetT *set; + int msgId; { - MCMsgT *msg; - long lo, hi, cur, dir; + MCMsgT *msg; + long lo, hi, cur, dir; - if (set == NULL || set->invalid || msgId <= 0) return(NULL); - LOOKUP(set, msg, msgId, numMsgs, u.msgs); - return(msg); + if (set == NULL || set->invalid || msgId <= 0) + return (NULL); + LOOKUP(set, msg, msgId, numMsgs, u.msgs); + return (msg); } -char* -catgets( catd, setId, msgId, dflt) - nl_catd catd; - int setId; - int msgId; - __const char *dflt; +char * +catgets(catd, setId, msgId, dflt) + nl_catd catd; + int setId; + int msgId; + __const char *dflt; { - MCMsgT *msg; - MCCatT *cat = (MCCatT *) catd; - __const char *cptr; - - if (catd == NULL || catd == NLERR) - return((char *)dflt); - msg = MCGetMsg(MCGetSet(cat, setId), msgId); - if (msg != NULL) cptr = msg->msg.str; - else cptr = dflt; - return((char *)cptr); + MCMsgT *msg; + MCCatT *cat = (MCCatT *)catd; + __const char *cptr; + + if (catd == NULL || catd == NLERR) + return ((char *)dflt); + msg = MCGetMsg(MCGetSet(cat, setId), msgId); + if (msg != NULL) + cptr = msg->msg.str; + else + cptr = dflt; + return ((char *)cptr); } - int -catclose( catd) +catclose(catd) nl_catd catd; { - MCCatT *cat = (MCCatT *) catd; - - if (catd == NULL || catd == NLERR) { - errno = EBADF; return(-1); - } + MCCatT *cat = (MCCatT *)catd; + if (catd == NULL || catd == NLERR) { + errno = EBADF; + return (-1); + } #if 0 - if (cat->loadType != MCLoadAll) + if (cat->loadType != MCLoadAll) #endif - (void) fclose(cat->fp); - __nls_free_resources(cat, cat->numSets); - free(cat); - - return(0); + (void)fclose(cat->fp); + __nls_free_resources(cat, cat->numSets); + free(cat); + return (0); } /* @@ -300,159 +317,180 @@ catclose( catd) */ /* Note that only malloc failures are allowed to return an error */ -static char* _errowner = "Message Catalog System";; -#define CORRUPT() { \ - fprintf(stderr, "%s: corrupt file.", _errowner); \ - free(cat); \ - NLRETERR(EINVAL); \ - } +static char *_errowner = "Message Catalog System"; -#define NOSPACE() { \ - fprintf(stderr, "%s: no more memory.", _errowner); \ - free(cat); \ - return(NLERR); \ - } +#define CORRUPT() { \ + (void)fprintf(stderr, "%s: corrupt file.", _errowner); \ + free(cat); \ + NLRETERR(EFTYPE); \ +} + +#define NOSPACE() { \ + saverr = errno; \ + (void)fprintf(stderr, "%s: no more memory.", _errowner); \ + free(cat); \ + errno = saverr; \ + return (NLERR); \ +} static void __nls_free_resources(cat, i) - MCCatT *cat; - int i; + MCCatT *cat; + int i; { - MCSetT *set; - int j; - - for (j = 0; j < i; j++) { - set = cat->sets + j; - if (!set->invalid) { - free(set->data.str); - free(set->u.msgs); + MCSetT *set; + int j; + + for (j = 0; j < i; j++) { + set = cat->sets + j; + if (!set->invalid) { + free(set->data.str); + free(set->u.msgs); + } } - } - free(cat->sets); + free(cat->sets); } static nl_catd loadCat(catpath) - __const char *catpath; + __const char *catpath; { - MCHeaderT header; - MCCatT *cat; - MCSetT *set; - long i; - off_t nextSet; - - cat = (MCCatT *) malloc(sizeof(MCCatT)); - if (cat == NULL) return(NLERR); - cat->loadType = MCLoadBySet; - - if ((cat->fp = fopen(catpath, "r")) == NULL) { - free(cat); - return(NLERR); - } - - (void) _fcntl(fileno(cat->fp), F_SETFD, FD_CLOEXEC); - - if (fread(&header, sizeof(header), 1, cat->fp) != 1) - CORRUPT(); - - if (strncmp(header.magic, MCMagic, MCMagicLen) != 0) CORRUPT(); - - if (header.majorVer != MCMajorVer) { - free(cat); - fprintf(stderr, "%s: %s is version %ld, we need %ld.\n", _errowner, - catpath, header.majorVer, MCMajorVer); - NLRETERR(EINVAL); - } - - if (header.numSets <= 0) { - free(cat); - fprintf(stderr, "%s: %s has %ld sets!\n", _errowner, catpath, - header.numSets); - NLRETERR(EINVAL); - } - - cat->numSets = header.numSets; - cat->sets = (MCSetT *) malloc(sizeof(MCSetT) * header.numSets); - if (cat->sets == NULL) NOSPACE(); - - nextSet = header.firstSet; - for (i = 0; i < cat->numSets; ++i) { - if (fseeko(cat->fp, nextSet, SEEK_SET) == -1) { - __nls_free_resources(cat, i); - CORRUPT(); + MCHeaderT header; + MCCatT *cat; + MCSetT *set; + long i; + off_t nextSet; + int saverr; + + if ((cat = (MCCatT *)malloc(sizeof(MCCatT))) == NULL) + return (NLERR); + cat->loadType = MCLoadBySet; + + if ((cat->fp = fopen(catpath, "r")) == NULL) { + saverr = errno; + free(cat); + errno = saverr; + return (NLERR); } + (void)_fcntl(fileno(cat->fp), F_SETFD, FD_CLOEXEC); - /* read in the set header */ - set = cat->sets + i; - if (fread(set, sizeof(*set), 1, cat->fp) != 1) { - __nls_free_resources(cat, i); + if (fread(&header, sizeof(header), 1, cat->fp) != 1 || + strncmp(header.magic, MCMagic, MCMagicLen) != 0) CORRUPT(); - } - /* if it's invalid, skip over it (and backup 'i') */ - if (set->invalid) { - --i; - nextSet = set->nextSet; - continue; + if (header.majorVer != MCMajorVer) { + free(cat); + (void)fprintf(stderr, "%s: %s is version %ld, we need %ld.\n", + _errowner, catpath, header.majorVer, MCMajorVer); + NLRETERR(EFTYPE); + } + if (header.numSets <= 0) { + free(cat); + (void)fprintf(stderr, "%s: %s has %ld sets!\n", + _errowner, catpath, header.numSets); + NLRETERR(EFTYPE); } -#if 0 - if (cat->loadType == MCLoadAll) { - int res; + cat->numSets = header.numSets; + if ((cat->sets = (MCSetT *)malloc(sizeof(MCSetT) * header.numSets)) == + NULL) + NOSPACE(); - if ((res = loadSet(cat, set)) <= 0) { - __nls_free_resources(cat, i); - if (res < 0) NOSPACE(); - CORRUPT(); - } - } else + nextSet = header.firstSet; + for (i = 0; i < cat->numSets; ++i) { + if (fseeko(cat->fp, nextSet, SEEK_SET) == -1) { + __nls_free_resources(cat, i); + CORRUPT(); + } + + /* read in the set header */ + set = cat->sets + i; + if (fread(set, sizeof(*set), 1, cat->fp) != 1) { + __nls_free_resources(cat, i); + CORRUPT(); + } + + /* if it's invalid, skip over it (and backup 'i') */ + if (set->invalid) { + --i; + nextSet = set->nextSet; + continue; + } +#if 0 + if (cat->loadType == MCLoadAll) { + int res; + + if ((res = loadSet(cat, set)) <= 0) { + __nls_free_resources(cat, i); + if (res < 0) + NOSPACE(); + CORRUPT(); + } + } else #endif - set->invalid = TRUE; - nextSet = set->nextSet; - } + set->invalid = TRUE; + nextSet = set->nextSet; + } #if 0 - if (cat->loadType == MCLoadAll) { - (void) fclose(cat->fp); - cat->fp = NULL; - } + if (cat->loadType == MCLoadAll) { + (void)fclose(cat->fp); + cat->fp = NULL; + } #endif - return((nl_catd) cat); + return ((nl_catd) cat); } static int loadSet(cat, set) - MCCatT *cat; - MCSetT *set; + MCCatT *cat; + MCSetT *set; { - MCMsgT *msg; - int i; - - /* Get the data */ - if (fseeko(cat->fp, set->data.off, SEEK_SET) == -1) return(0); - if ((set->data.str = malloc(set->dataLen)) == NULL) return(-1); - if (fread(set->data.str, set->dataLen, 1, cat->fp) != 1) { - free(set->data.str); return(0); - } - - /* Get the messages */ - if (fseeko(cat->fp, set->u.firstMsg, SEEK_SET) == -1) { - free(set->data.str); return(0); - } - if ((set->u.msgs = (MCMsgT *) malloc(sizeof(MCMsgT) * set->numMsgs)) == NULL) { - free(set->data.str); return(-1); - } - - for (i = 0; i < set->numMsgs; ++i) { - msg = set->u.msgs + i; - if (fread(msg, sizeof(*msg), 1, cat->fp) != 1) { - free(set->u.msgs); free(set->data.str); return(0); + MCMsgT *msg; + int i; + int saverr; + + /* Get the data */ + if (fseeko(cat->fp, set->data.off, SEEK_SET) == -1) + return (0); + if ((set->data.str = malloc(set->dataLen)) == NULL) + return (-1); + if (fread(set->data.str, set->dataLen, 1, cat->fp) != 1) { + saverr = errno; + free(set->data.str); + errno = saverr; + return (0); } - if (msg->invalid) { - --i; - continue; + + /* Get the messages */ + if (fseeko(cat->fp, set->u.firstMsg, SEEK_SET) == -1) { + saverr = errno; + free(set->data.str); + errno = saverr; + return (0); + } + if ((set->u.msgs = (MCMsgT *)malloc(sizeof(MCMsgT) * set->numMsgs)) == + NULL) { + saverr = errno; + free(set->data.str); + errno = saverr; + return (-1); + } + + for (i = 0; i < set->numMsgs; ++i) { + msg = set->u.msgs + i; + if (fread(msg, sizeof(*msg), 1, cat->fp) != 1) { + saverr = errno; + free(set->u.msgs); + free(set->data.str); + errno = saverr; + return (0); + } + if (msg->invalid) { + --i; + continue; + } + msg->msg.str = (char *)(set->data.str + msg->msg.off); } - msg->msg.str = (char *) (set->data.str + msg->msg.off); - } - set->invalid = FALSE; - return(1); + set->invalid = FALSE; + return (1); } -- cgit v1.1