1 /* $OpenBSD: rune.c,v 1.7 2016/09/05 09:47:03 schwarze Exp $ */ 2 /* $NetBSD: rune.c,v 1.26 2004/05/09 11:26:33 kleink Exp $ */ 3 4 /*- 5 * Copyright (c)1999 Citrus Project, 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30 /*- 31 * Copyright (c) 1993 32 * The Regents of the University of California. All rights reserved. 33 * 34 * This code is derived from software contributed to Berkeley by 35 * Paul Borman at Krystal Technologies. 36 * 37 * Redistribution and use in source and binary forms, with or without 38 * modification, are permitted provided that the following conditions 39 * are met: 40 * 1. Redistributions of source code must retain the above copyright 41 * notice, this list of conditions and the following disclaimer. 42 * 2. Redistributions in binary form must reproduce the above copyright 43 * notice, this list of conditions and the following disclaimer in the 44 * documentation and/or other materials provided with the distribution. 45 * 3. Neither the name of the University nor the names of its contributors 46 * may be used to endorse or promote products derived from this software 47 * without specific prior written permission. 48 * 49 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 50 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 51 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 52 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 53 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 54 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 55 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 56 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 57 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 58 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 59 * SUCH DAMAGE. 60 */ 61 62 #include <sys/types.h> 63 #include <sys/stat.h> 64 #include <assert.h> 65 #include <errno.h> 66 #include <stdint.h> 67 #include <stdio.h> 68 #include <stdlib.h> 69 #include <string.h> 70 #include <wchar.h> 71 #include "rune.h" 72 #include "rune_local.h" 73 74 #define SAFE_ADD(x, y) \ 75 do { \ 76 if ((x) > SIZE_MAX - (y)) \ 77 return NULL; \ 78 (x) += (y); \ 79 } while (0); 80 81 static int readrange(_RuneLocale *, _RuneRange *, uint32_t, void *, FILE *); 82 static void _freeentry(_RuneRange *); 83 static void _wctype_init(_RuneLocale *rl); 84 85 static int 86 readrange(_RuneLocale *rl, _RuneRange *rr, uint32_t nranges, void *lastp, 87 FILE *fp) 88 { 89 uint32_t i; 90 _RuneEntry *re; 91 _FileRuneEntry fre; 92 93 re = (_RuneEntry *)rl->rl_variable; 94 95 rr->rr_nranges = nranges; 96 if (rr->rr_nranges == 0) { 97 rr->rr_rune_ranges = NULL; 98 return 0; 99 } 100 101 rr->rr_rune_ranges = re; 102 for (i = 0; i < rr->rr_nranges; i++) { 103 if ((void *)re >= lastp) 104 return -1; 105 106 if (fread(&fre, sizeof(fre), 1, fp) != 1) 107 return -1; 108 109 re->re_min = ntohl((uint32_t)fre.fre_min); 110 re->re_max = ntohl((uint32_t)fre.fre_max); 111 re->re_map = ntohl((uint32_t)fre.fre_map); 112 re++; 113 } 114 rl->rl_variable = re; 115 return 0; 116 } 117 118 static int 119 readentry(_RuneRange *rr, FILE *fp) 120 { 121 _RuneEntry *re; 122 size_t l, i, j; 123 int error; 124 125 re = rr->rr_rune_ranges; 126 for (i = 0; i < rr->rr_nranges; i++) { 127 if (re[i].re_map != 0) { 128 re[i].re_rune_types = NULL; 129 continue; 130 } 131 132 if (re[i].re_max < re[i].re_min) { 133 error = EINVAL; 134 goto fail; 135 } 136 137 l = re[i].re_max - re[i].re_min + 1; 138 re[i].re_rune_types = calloc(l, sizeof(_RuneType)); 139 if (!re[i].re_rune_types) { 140 error = ENOMEM; 141 goto fail; 142 } 143 144 if (fread(re[i].re_rune_types, sizeof(_RuneType), l, fp) != l) 145 goto fail2; 146 147 for (j = 0; j < l; j++) 148 re[i].re_rune_types[j] = ntohl(re[i].re_rune_types[j]); 149 } 150 return 0; 151 152 fail: 153 for (j = 0; j < i; j++) { 154 free(re[j].re_rune_types); 155 re[j].re_rune_types = NULL; 156 } 157 return error; 158 fail2: 159 for (j = 0; j <= i; j++) { 160 free(re[j].re_rune_types); 161 re[j].re_rune_types = NULL; 162 } 163 return errno; 164 } 165 166 /* XXX: temporary implementation */ 167 static int 168 find_codeset(_RuneLocale *rl) 169 { 170 char *top, *codeset, *tail, *ep; 171 172 if (rl->rl_variable == NULL) 173 return 0; 174 175 /* end of rl_variable region */ 176 ep = (char *)rl->rl_variable; 177 ep += rl->rl_variable_len; 178 rl->rl_codeset = NULL; 179 if (!(top = strstr(rl->rl_variable, _RUNE_CODESET))) 180 return 0; 181 tail = strpbrk(top, " \t"); 182 codeset = top + sizeof(_RUNE_CODESET) - 1; 183 if (tail) { 184 *top = *tail; 185 *tail = '\0'; 186 rl->rl_codeset = strdup(codeset); 187 strlcpy(top + 1, tail + 1, (unsigned)(ep - (top + 1))); 188 } else { 189 *top = '\0'; 190 rl->rl_codeset = strdup(codeset); 191 } 192 return (rl->rl_codeset == NULL); 193 } 194 195 void 196 _freeentry(_RuneRange *rr) 197 { 198 _RuneEntry *re; 199 uint32_t i; 200 201 re = rr->rr_rune_ranges; 202 for (i = 0; i < rr->rr_nranges; i++) { 203 free(re[i].re_rune_types); 204 re[i].re_rune_types = NULL; 205 } 206 } 207 208 void 209 _wctype_init(_RuneLocale *rl) 210 { 211 memcpy(&rl->rl_wctype, &_DefaultRuneLocale.rl_wctype, 212 sizeof(rl->rl_wctype)); 213 } 214 215 216 _RuneLocale * 217 _Read_RuneMagi(FILE *fp) 218 { 219 /* file */ 220 _FileRuneLocale frl; 221 /* host data */ 222 char *hostdata; 223 size_t hostdatalen; 224 void *lastp; 225 _RuneLocale *rl; 226 struct stat sb; 227 int x; 228 uint32_t runetype_nranges, maplower_nranges, mapupper_nranges, var_len; 229 230 if (fstat(fileno(fp), &sb) < 0) 231 return NULL; 232 233 if (sb.st_size < sizeof(_FileRuneLocale)) 234 return NULL; 235 /* XXX more validation? */ 236 237 /* Someone might have read the magic number once already */ 238 rewind(fp); 239 240 if (fread(&frl, sizeof(frl), 1, fp) != 1) 241 return NULL; 242 if (memcmp(frl.frl_magic, _RUNE_MAGIC_1, sizeof(frl.frl_magic))) 243 return NULL; 244 245 runetype_nranges = ntohl(frl.frl_runetype_ext.frr_nranges); 246 maplower_nranges = ntohl(frl.frl_maplower_ext.frr_nranges); 247 mapupper_nranges = ntohl(frl.frl_mapupper_ext.frr_nranges); 248 var_len = ntohl((uint32_t)frl.frl_variable_len); 249 250 #if SIZE_MAX <= UINT32_MAX 251 if (runetype_nranges > SIZE_MAX / sizeof(_RuneEntry) || 252 maplower_nranges > SIZE_MAX / sizeof(_RuneEntry) || 253 mapupper_nranges > SIZE_MAX / sizeof(_RuneEntry)) 254 return NULL; 255 #endif 256 257 if (var_len > INT32_MAX) 258 return NULL; 259 260 hostdatalen = sizeof(*rl); 261 SAFE_ADD(hostdatalen, var_len); 262 SAFE_ADD(hostdatalen, runetype_nranges * sizeof(_RuneEntry)); 263 SAFE_ADD(hostdatalen, maplower_nranges * sizeof(_RuneEntry)); 264 SAFE_ADD(hostdatalen, mapupper_nranges * sizeof(_RuneEntry)); 265 266 if ((hostdata = calloc(hostdatalen, 1)) == NULL) 267 return NULL; 268 lastp = hostdata + hostdatalen; 269 270 rl = (_RuneLocale *)hostdata; 271 rl->rl_variable = rl + 1; 272 273 memcpy(rl->rl_magic, frl.frl_magic, sizeof(rl->rl_magic)); 274 memcpy(rl->rl_encoding, frl.frl_encoding, sizeof(rl->rl_encoding)); 275 276 /* XXX assumes rune_t = uint32_t */ 277 rl->rl_invalid_rune = ntohl((uint32_t)frl.frl_invalid_rune); 278 rl->rl_variable_len = ntohl((uint32_t)frl.frl_variable_len); 279 280 for (x = 0; x < _CACHED_RUNES; ++x) { 281 rl->rl_runetype[x] = ntohl(frl.frl_runetype[x]); 282 283 /* XXX assumes rune_t = uint32_t */ 284 rl->rl_maplower[x] = ntohl((uint32_t)frl.frl_maplower[x]); 285 rl->rl_mapupper[x] = ntohl((uint32_t)frl.frl_mapupper[x]); 286 } 287 288 if (readrange(rl, &rl->rl_runetype_ext, runetype_nranges, lastp, fp) || 289 readrange(rl, &rl->rl_maplower_ext, maplower_nranges, lastp, fp) || 290 readrange(rl, &rl->rl_mapupper_ext, mapupper_nranges, lastp, fp)) 291 goto err; 292 293 if (readentry(&rl->rl_runetype_ext, fp) != 0) 294 goto err; 295 296 if ((uint8_t *)rl->rl_variable + rl->rl_variable_len > 297 (uint8_t *)lastp) 298 goto rune_err; 299 300 if (rl->rl_variable_len == 0) 301 rl->rl_variable = NULL; 302 else if (fread(rl->rl_variable, rl->rl_variable_len, 1, fp) != 1) 303 goto rune_err; 304 if (find_codeset(rl)) 305 goto rune_err; 306 _wctype_init(rl); 307 308 /* 309 * error if we have junk at the tail, 310 * or if we can't allocate memory. 311 */ 312 if (ftello(fp) != sb.st_size || __make_ctype_tabs(rl) == -1) 313 goto rune_err; 314 315 return(rl); 316 rune_err: 317 _freeentry(&rl->rl_runetype_ext); 318 err: 319 free(hostdata); 320 return NULL; 321 } 322