Index: head/lib/libc/locale/collate.c =================================================================== --- head/lib/libc/locale/collate.c +++ head/lib/libc/locale/collate.c @@ -53,6 +53,7 @@ #include #include "un-namespace.h" +#include "endian.h" #include "collate.h" #include "setlocale.h" #include "ldpart.h" @@ -160,7 +161,7 @@ if ((info->directive_count < 1) || (info->directive_count >= COLL_WEIGHTS_MAX) || - ((chains = info->chain_count) < 0)) { + ((chains = BSWAP(info->chain_count)) < 0)) { (void) munmap(map, sbuf.st_size); errno = EINVAL; return (_LDP_ERROR); @@ -168,9 +169,9 @@ i = (sizeof (collate_char_t) * (UCHAR_MAX + 1)) + (sizeof (collate_chain_t) * chains) + - (sizeof (collate_large_t) * info->large_count); + (sizeof (collate_large_t) * BSWAP(info->large_count)); for (z = 0; z < info->directive_count; z++) { - i += sizeof (collate_subst_t) * info->subst_count[z]; + i += sizeof (collate_subst_t) * BSWAP(info->subst_count[z]); } if (i != (sbuf.st_size - (TMP - map))) { (void) munmap(map, sbuf.st_size); @@ -183,9 +184,9 @@ TMP += sizeof (collate_char_t) * (UCHAR_MAX + 1); for (z = 0; z < info->directive_count; z++) { - if (info->subst_count[z] > 0) { + if (BSWAP(info->subst_count[z]) > 0) { table->subst_table[z] = (void *)TMP; - TMP += info->subst_count[z] * sizeof (collate_subst_t); + TMP += BSWAP(info->subst_count[z]) * sizeof (collate_subst_t); } else { table->subst_table[z] = NULL; } @@ -196,7 +197,7 @@ TMP += chains * sizeof (collate_chain_t); } else table->chain_pri_table = NULL; - if (info->large_count > 0) + if (BSWAP(info->large_count) > 0) table->large_pri_table = (void *)TMP; else table->large_pri_table = NULL; @@ -209,7 +210,7 @@ substsearch(struct xlocale_collate *table, const wchar_t key, int pass) { const collate_subst_t *p; - int n = table->info->subst_count[pass]; + int n = BSWAP(table->info->subst_count[pass]); if (n == 0) return (NULL); @@ -221,7 +222,8 @@ return (NULL); p = table->subst_table[pass] + (key & ~COLLATE_SUBST_PRIORITY); - assert(p->key == key); + assert(BSWAP(p->key) == key); + return (p->pri); } @@ -229,7 +231,7 @@ chainsearch(struct xlocale_collate *table, const wchar_t *key, int *len) { int low = 0; - int high = table->info->chain_count - 1;; + int high = BSWAP(table->info->chain_count) - 1; int next, compar, l; collate_chain_t *p; collate_chain_t *tab = table->chain_pri_table; @@ -240,7 +242,7 @@ while (low <= high) { next = (low + high) / 2; p = tab + next; - compar = *key - *p->str; + compar = *key - le16toh(*p->str); if (compar == 0) { l = wcsnlen(p->str, COLLATE_STR_LEN); compar = wcsncmp(key, p->str, l); @@ -261,7 +263,7 @@ largesearch(struct xlocale_collate *table, const wchar_t key) { int low = 0; - int high = table->info->large_count - 1; + int high = BSWAP(table->info->large_count) - 1; int next, compar; collate_large_t *p; collate_large_t *tab = table->large_pri_table; @@ -272,7 +274,7 @@ while (low <= high) { next = (low + high) / 2; p = tab + next; - compar = key - p->val; + compar = key - BSWAP(p->val); if (compar == 0) return (p); if (compar > 0) @@ -337,15 +339,15 @@ * Character is a small (8-bit) character. * We just look these up directly for speed. */ - *pri = table->char_pri_table[*t].pri[which]; + *pri = BSWAP(table->char_pri_table[*t].pri[which]); - } else if ((table->info->large_count > 0) && + } else if ((BSWAP(table->info->large_count) > 0) && ((match = largesearch(table, *t)) != NULL)) { /* * Character was found in the extended table. */ - *pri = match->pri.pri[which]; + *pri = BSWAP(match->pri.pri[which]); } else { /* @@ -355,7 +357,7 @@ /* Mask off sign bit to prevent ordering confusion. */ *pri = (*t & COLLATE_MAX_PRIORITY); } else { - *pri = table->info->undef_pri[which]; + *pri = BSWAP(table->info->undef_pri[which]); } /* No substitutions for undefined characters! */ return; @@ -374,9 +376,9 @@ * code ensures this for us. */ if ((sptr = substsearch(table, *pri, which)) != NULL) { - if ((*pri = *sptr) > 0) { + if ((*pri = BSWAP(*sptr)) > 0) { sptr++; - *state = *sptr ? sptr : NULL; + *state = BSWAP(*sptr) ? sptr : NULL; } } @@ -518,7 +520,7 @@ xfrm(struct xlocale_collate *table, unsigned char *p, int pri, int pass) { /* we use unsigned to ensure zero fill on right shift */ - uint32_t val = (uint32_t)table->info->pri_count[pass]; + uint32_t val = BSWAP((uint32_t)table->info->pri_count[pass]); int nc = 0; while (val) { @@ -678,7 +680,7 @@ e = -1; if (*str <= UCHAR_MAX) e = table->char_pri_table[*str].pri[0]; - else if (table->info->large_count > 0) { + else if (BSWAP(table->info->large_count) > 0) { collate_large_t *match_large; match_large = largesearch(table, *str); if (match_large) @@ -688,7 +690,7 @@ return (1); return (e > 0 ? e : 0); } - if (table->info->chain_count > 0) { + if (BSWAP(table->info->chain_count) > 0) { wchar_t name[COLLATE_STR_LEN]; collate_chain_t *match_chain; int clen; Index: head/lib/libc/locale/endian.h =================================================================== --- head/lib/libc/locale/endian.h +++ head/lib/libc/locale/endian.h @@ -0,0 +1,52 @@ +/*- + * Copyright (c) 2016 Ruslan Bukin + * All rights reserved. + * + * Portions of this software were developed by SRI International and the + * University of Cambridge Computer Laboratory under DARPA/AFRL contract + * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme. + * + * Portions of this software were developed by the University of Cambridge + * Computer Laboratory as part of the CTSRD Project, with support from the + * UK Higher Education Innovation Fund (HEIF). + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include + +/* + * We assume locale files were generated on EL machine + * (e.g. during cross build on amd64 host), but used on EB + * machine (e.g. MIPS64EB), so convert it to host endianness. + * + * TODO: detect host endianness on the build machine and use + * correct macros here. + */ + +#if BYTE_ORDER == BIG_ENDIAN && defined(__mips__) +#define BSWAP(x) le32toh(x) +#else +#define BSWAP(x) x +#endif Index: head/lib/libc/locale/rune.c =================================================================== --- head/lib/libc/locale/rune.c +++ head/lib/libc/locale/rune.c @@ -52,6 +52,7 @@ #include #include "un-namespace.h" +#include "endian.h" #include "runefile.h" _RuneLocale * @@ -107,29 +108,29 @@ } runetype_ext_ranges = (_FileRuneEntry *)variable; - variable = runetype_ext_ranges + frl->runetype_ext_nranges; + variable = runetype_ext_ranges + BSWAP(frl->runetype_ext_nranges); if (variable > lastp) { goto invalid; } maplower_ext_ranges = (_FileRuneEntry *)variable; - variable = maplower_ext_ranges + frl->maplower_ext_nranges; + variable = maplower_ext_ranges + BSWAP(frl->maplower_ext_nranges); if (variable > lastp) { goto invalid; } mapupper_ext_ranges = (_FileRuneEntry *)variable; - variable = mapupper_ext_ranges + frl->mapupper_ext_nranges; + variable = mapupper_ext_ranges + BSWAP(frl->mapupper_ext_nranges); if (variable > lastp) { goto invalid; } frr = runetype_ext_ranges; - for (x = 0; x < frl->runetype_ext_nranges; ++x) { + for (x = 0; x < BSWAP(frl->runetype_ext_nranges); ++x) { uint32_t *types; - if (frr[x].map == 0) { - int len = frr[x].max - frr[x].min + 1; + if (BSWAP(frr[x].map) == 0) { + int len = BSWAP(frr[x].max) - BSWAP(frr[x].min) + 1; types = variable; variable = types + len; runetype_ext_len += len; @@ -139,7 +140,7 @@ } } - if ((char *)variable + frl->variable_len > (char *)lastp) { + if ((char *)variable + BSWAP(frl->variable_len) > (char *)lastp) { goto invalid; } @@ -147,10 +148,10 @@ * Convert from disk format to host format. */ data = malloc(sizeof(_RuneLocale) + - (frl->runetype_ext_nranges + frl->maplower_ext_nranges + - frl->mapupper_ext_nranges) * sizeof(_RuneEntry) + + (BSWAP(frl->runetype_ext_nranges) + BSWAP(frl->maplower_ext_nranges) + + BSWAP(frl->mapupper_ext_nranges)) * sizeof(_RuneEntry) + runetype_ext_len * sizeof(*rr->__types) + - frl->variable_len); + BSWAP(frl->variable_len)); if (data == NULL) { saverr = errno; munmap(fdata, sb.st_size); @@ -164,15 +165,15 @@ memcpy(rl->__magic, _RUNE_MAGIC_1, sizeof(rl->__magic)); memcpy(rl->__encoding, frl->encoding, sizeof(rl->__encoding)); - rl->__variable_len = frl->variable_len; - rl->__runetype_ext.__nranges = frl->runetype_ext_nranges; - rl->__maplower_ext.__nranges = frl->maplower_ext_nranges; - rl->__mapupper_ext.__nranges = frl->mapupper_ext_nranges; + rl->__variable_len = BSWAP(frl->variable_len); + rl->__runetype_ext.__nranges = BSWAP(frl->runetype_ext_nranges); + rl->__maplower_ext.__nranges = BSWAP(frl->maplower_ext_nranges); + rl->__mapupper_ext.__nranges = BSWAP(frl->mapupper_ext_nranges); for (x = 0; x < _CACHED_RUNES; ++x) { - rl->__runetype[x] = frl->runetype[x]; - rl->__maplower[x] = frl->maplower[x]; - rl->__mapupper[x] = frl->mapupper[x]; + rl->__runetype[x] = BSWAP(frl->runetype[x]); + rl->__maplower[x] = BSWAP(frl->maplower[x]); + rl->__mapupper[x] = BSWAP(frl->mapupper[x]); } rl->__runetype_ext.__ranges = (_RuneEntry *)rl->__variable; @@ -187,15 +188,15 @@ rl->__variable = rl->__mapupper_ext.__ranges + rl->__mapupper_ext.__nranges; - variable = mapupper_ext_ranges + frl->mapupper_ext_nranges; + variable = mapupper_ext_ranges + BSWAP(frl->mapupper_ext_nranges); frr = runetype_ext_ranges; rr = rl->__runetype_ext.__ranges; for (x = 0; x < rl->__runetype_ext.__nranges; ++x) { uint32_t *types; - rr[x].__min = frr[x].min; - rr[x].__max = frr[x].max; - rr[x].__map = frr[x].map; + rr[x].__min = BSWAP(frr[x].min); + rr[x].__max = BSWAP(frr[x].max); + rr[x].__map = BSWAP(frr[x].map); if (rr[x].__map == 0) { int len = rr[x].__max - rr[x].__min + 1; types = variable; @@ -211,17 +212,17 @@ frr = maplower_ext_ranges; rr = rl->__maplower_ext.__ranges; for (x = 0; x < rl->__maplower_ext.__nranges; ++x) { - rr[x].__min = frr[x].min; - rr[x].__max = frr[x].max; - rr[x].__map = frr[x].map; + rr[x].__min = BSWAP(frr[x].min); + rr[x].__max = BSWAP(frr[x].max); + rr[x].__map = BSWAP(frr[x].map); } frr = mapupper_ext_ranges; rr = rl->__mapupper_ext.__ranges; for (x = 0; x < rl->__mapupper_ext.__nranges; ++x) { - rr[x].__min = frr[x].min; - rr[x].__max = frr[x].max; - rr[x].__map = frr[x].map; + rr[x].__min = BSWAP(frr[x].min); + rr[x].__max = BSWAP(frr[x].max); + rr[x].__map = BSWAP(frr[x].map); } memcpy(rl->__variable, variable, rl->__variable_len);