| File: | modules/im/ximcp/imLcPrs.c |
| Location: | line 390, column 18 |
| Description: | String copy function overflows destination buffer |
| 1 | /****************************************************************** | |||||
| 2 | ||||||
| 3 | Copyright 1992 by Oki Technosystems Laboratory, Inc. | |||||
| 4 | Copyright 1992 by Fuji Xerox Co., Ltd. | |||||
| 5 | ||||||
| 6 | Permission to use, copy, modify, distribute, and sell this software | |||||
| 7 | and its documentation for any purpose is hereby granted without fee, | |||||
| 8 | provided that the above copyright notice appear in all copies and | |||||
| 9 | that both that copyright notice and this permission notice appear | |||||
| 10 | in supporting documentation, and that the name of Oki Technosystems | |||||
| 11 | Laboratory and Fuji Xerox not be used in advertising or publicity | |||||
| 12 | pertaining to distribution of the software without specific, written | |||||
| 13 | prior permission. | |||||
| 14 | Oki Technosystems Laboratory and Fuji Xerox make no representations | |||||
| 15 | about the suitability of this software for any purpose. It is provided | |||||
| 16 | "as is" without express or implied warranty. | |||||
| 17 | ||||||
| 18 | OKI TECHNOSYSTEMS LABORATORY AND FUJI XEROX DISCLAIM ALL WARRANTIES | |||||
| 19 | WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF | |||||
| 20 | MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL OKI TECHNOSYSTEMS | |||||
| 21 | LABORATORY AND FUJI XEROX BE LIABLE FOR ANY SPECIAL, INDIRECT OR | |||||
| 22 | CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS | |||||
| 23 | OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE | |||||
| 24 | OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE | |||||
| 25 | OR PERFORMANCE OF THIS SOFTWARE. | |||||
| 26 | ||||||
| 27 | Author: Yasuhiro Kawai Oki Technosystems Laboratory | |||||
| 28 | Author: Kazunori Nishihara Fuji Xerox | |||||
| 29 | ||||||
| 30 | ******************************************************************/ | |||||
| 31 | ||||||
| 32 | ||||||
| 33 | #ifdef HAVE_CONFIG_H1 | |||||
| 34 | #include <config.h> | |||||
| 35 | #endif | |||||
| 36 | #include <X11/Xlib.h> | |||||
| 37 | #include <X11/Xmd.h> | |||||
| 38 | #include <X11/Xos.h> | |||||
| 39 | #include "Xlibint.h" | |||||
| 40 | #include "Xlcint.h" | |||||
| 41 | #include "Ximint.h" | |||||
| 42 | #include <sys/stat.h> | |||||
| 43 | #include <stdio.h> | |||||
| 44 | #include <limits.h> | |||||
| 45 | #include "pathmax.h" | |||||
| 46 | ||||||
| 47 | #define XLC_BUFSIZE256 256 | |||||
| 48 | ||||||
| 49 | extern int _Xmbstowcs( | |||||
| 50 | wchar_t *wstr, | |||||
| 51 | char *str, | |||||
| 52 | int len | |||||
| 53 | ); | |||||
| 54 | ||||||
| 55 | extern int _Xmbstoutf8( | |||||
| 56 | char *ustr, | |||||
| 57 | const char *str, | |||||
| 58 | int len | |||||
| 59 | ); | |||||
| 60 | ||||||
| 61 | static void parsestringfile(FILE *fp, Xim im, int depth); | |||||
| 62 | ||||||
| 63 | /* | |||||
| 64 | * Parsing File Format: | |||||
| 65 | * | |||||
| 66 | * FILE ::= { [PRODUCTION] [COMMENT] "\n"} | |||||
| 67 | * PRODUCTION ::= LHS ":" RHS [ COMMENT ] | |||||
| 68 | * COMMENT ::= "#" {<any character except null or newline>} | |||||
| 69 | * LHS ::= EVENT { EVENT } | |||||
| 70 | * EVENT ::= [MODIFIER_LIST] "<" keysym ">" | |||||
| 71 | * MODIFIER_LIST ::= (["!"] {MODIFIER} ) | "None" | |||||
| 72 | * MODIFIER ::= ["~"] MODIFIER_NAME | |||||
| 73 | * MODIFIER_NAME ::= ("Ctrl"|"Lock"|"Caps"|"Shift"|"Alt"|"Meta") | |||||
| 74 | * RHS ::= ( STRING | keysym | STRING keysym ) | |||||
| 75 | * STRING ::= '"' { CHAR } '"' | |||||
| 76 | * CHAR ::= GRAPHIC_CHAR | ESCAPED_CHAR | |||||
| 77 | * GRAPHIC_CHAR ::= locale (codeset) dependent code | |||||
| 78 | * ESCAPED_CHAR ::= ('\\' | '\"' | OCTAL | HEX ) | |||||
| 79 | * OCTAL ::= '\' OCTAL_CHAR [OCTAL_CHAR [OCTAL_CHAR]] | |||||
| 80 | * OCTAL_CHAR ::= (0|1|2|3|4|5|6|7) | |||||
| 81 | * HEX ::= '\' (x|X) HEX_CHAR [HEX_CHAR]] | |||||
| 82 | * HEX_CHAR ::= (0|1|2|3|4|5|6|7|8|9|A|B|C|D|E|F|a|b|c|d|e|f) | |||||
| 83 | * | |||||
| 84 | */ | |||||
| 85 | ||||||
| 86 | static int | |||||
| 87 | nextch( | |||||
| 88 | FILE *fp, | |||||
| 89 | int *lastch) | |||||
| 90 | { | |||||
| 91 | int c; | |||||
| 92 | ||||||
| 93 | if (*lastch != 0) { | |||||
| 94 | c = *lastch; | |||||
| 95 | *lastch = 0; | |||||
| 96 | } else { | |||||
| 97 | c = getc(fp); | |||||
| 98 | if (c == '\\') { | |||||
| 99 | c = getc(fp); | |||||
| 100 | if (c == '\n') { | |||||
| 101 | c = getc(fp); | |||||
| 102 | } else { | |||||
| 103 | ungetc(c, fp); | |||||
| 104 | c = '\\'; | |||||
| 105 | } | |||||
| 106 | } | |||||
| 107 | } | |||||
| 108 | return(c); | |||||
| 109 | } | |||||
| 110 | ||||||
| 111 | static void | |||||
| 112 | putbackch( | |||||
| 113 | int c, | |||||
| 114 | int *lastch) | |||||
| 115 | { | |||||
| 116 | *lastch = c; | |||||
| 117 | } | |||||
| 118 | ||||||
| 119 | #define ENDOFFILE0 0 | |||||
| 120 | #define ENDOFLINE1 1 | |||||
| 121 | #define COLON2 2 | |||||
| 122 | #define LESS3 3 | |||||
| 123 | #define GREATER4 4 | |||||
| 124 | #define EXCLAM5 5 | |||||
| 125 | #define TILDE6 6 | |||||
| 126 | #define STRING7 7 | |||||
| 127 | #define KEY8 8 | |||||
| 128 | #define ERROR9 9 | |||||
| 129 | ||||||
| 130 | #ifndef isalnum | |||||
| 131 | #define isalnum(c)(('0' <= (c) && (c) <= '9') || ('A' <= (c) && (c) <= 'Z') || ('a' <= (c) && (c) <= 'z')) \ | |||||
| 132 | (('0' <= (c) && (c) <= '9') || \ | |||||
| 133 | ('A' <= (c) && (c) <= 'Z') || \ | |||||
| 134 | ('a' <= (c) && (c) <= 'z')) | |||||
| 135 | #endif | |||||
| 136 | ||||||
| 137 | static int | |||||
| 138 | nexttoken( | |||||
| 139 | FILE *fp, | |||||
| 140 | char *tokenbuf, | |||||
| 141 | int *lastch) | |||||
| 142 | { | |||||
| 143 | int c; | |||||
| 144 | int token; | |||||
| 145 | char *p; | |||||
| 146 | int i, j; | |||||
| 147 | ||||||
| 148 | while ((c = nextch(fp, lastch)) == ' ' || c == '\t') { | |||||
| 149 | } | |||||
| 150 | switch (c) { | |||||
| 151 | case EOF(-1): | |||||
| 152 | token = ENDOFFILE0; | |||||
| 153 | break; | |||||
| 154 | case '\n': | |||||
| 155 | token = ENDOFLINE1; | |||||
| 156 | break; | |||||
| 157 | case '<': | |||||
| 158 | token = LESS3; | |||||
| 159 | break; | |||||
| 160 | case '>': | |||||
| 161 | token = GREATER4; | |||||
| 162 | break; | |||||
| 163 | case ':': | |||||
| 164 | token = COLON2; | |||||
| 165 | break; | |||||
| 166 | case '!': | |||||
| 167 | token = EXCLAM5; | |||||
| 168 | break; | |||||
| 169 | case '~': | |||||
| 170 | token = TILDE6; | |||||
| 171 | break; | |||||
| 172 | case '"': | |||||
| 173 | p = tokenbuf; | |||||
| 174 | while ((c = nextch(fp, lastch)) != '"') { | |||||
| 175 | if (c == '\n' || c == EOF(-1)) { | |||||
| 176 | putbackch(c, lastch); | |||||
| 177 | token = ERROR9; | |||||
| 178 | goto string_error; | |||||
| 179 | } else if (c == '\\') { | |||||
| 180 | c = nextch(fp, lastch); | |||||
| 181 | switch (c) { | |||||
| 182 | case '\\': | |||||
| 183 | case '"': | |||||
| 184 | *p++ = c; | |||||
| 185 | break; | |||||
| 186 | case 'n': | |||||
| 187 | *p++ = '\n'; | |||||
| 188 | break; | |||||
| 189 | case 'r': | |||||
| 190 | *p++ = '\r'; | |||||
| 191 | break; | |||||
| 192 | case 't': | |||||
| 193 | *p++ = '\t'; | |||||
| 194 | break; | |||||
| 195 | case '0': | |||||
| 196 | case '1': | |||||
| 197 | case '2': | |||||
| 198 | case '3': | |||||
| 199 | case '4': | |||||
| 200 | case '5': | |||||
| 201 | case '6': | |||||
| 202 | case '7': | |||||
| 203 | i = c - '0'; | |||||
| 204 | c = nextch(fp, lastch); | |||||
| 205 | for (j = 0; j < 2 && c >= '0' && c <= '7'; j++) { | |||||
| 206 | i <<= 3; | |||||
| 207 | i += c - '0'; | |||||
| 208 | c = nextch(fp, lastch); | |||||
| 209 | } | |||||
| 210 | putbackch(c, lastch); | |||||
| 211 | *p++ = (char)i; | |||||
| 212 | break; | |||||
| 213 | case 'X': | |||||
| 214 | case 'x': | |||||
| 215 | i = 0; | |||||
| 216 | for (j = 0; j < 2; j++) { | |||||
| 217 | c = nextch(fp, lastch); | |||||
| 218 | i <<= 4; | |||||
| 219 | if (c >= '0' && c <= '9') { | |||||
| 220 | i += c - '0'; | |||||
| 221 | } else if (c >= 'A' && c <= 'F') { | |||||
| 222 | i += c - 'A' + 10; | |||||
| 223 | } else if (c >= 'a' && c <= 'f') { | |||||
| 224 | i += c - 'a' + 10; | |||||
| 225 | } else { | |||||
| 226 | putbackch(c, lastch); | |||||
| 227 | i >>= 4; | |||||
| 228 | break; | |||||
| 229 | } | |||||
| 230 | } | |||||
| 231 | if (j == 0) { | |||||
| 232 | token = ERROR9; | |||||
| 233 | goto string_error; | |||||
| 234 | } | |||||
| 235 | *p++ = (char)i; | |||||
| 236 | break; | |||||
| 237 | case EOF(-1): | |||||
| 238 | putbackch(c, lastch); | |||||
| 239 | token = ERROR9; | |||||
| 240 | goto string_error; | |||||
| 241 | default: | |||||
| 242 | *p++ = c; | |||||
| 243 | break; | |||||
| 244 | } | |||||
| 245 | } else { | |||||
| 246 | *p++ = c; | |||||
| 247 | } | |||||
| 248 | } | |||||
| 249 | *p = '\0'; | |||||
| 250 | token = STRING7; | |||||
| 251 | break; | |||||
| 252 | case '#': | |||||
| 253 | while ((c = nextch(fp, lastch)) != '\n' && c != EOF(-1)) { | |||||
| 254 | } | |||||
| 255 | if (c == '\n') { | |||||
| 256 | token = ENDOFLINE1; | |||||
| 257 | } else { | |||||
| 258 | token = ENDOFFILE0; | |||||
| 259 | } | |||||
| 260 | break; | |||||
| 261 | default: | |||||
| 262 | if (isalnum(c)(('0' <= (c) && (c) <= '9') || ('A' <= (c) && (c) <= 'Z') || ('a' <= (c) && (c) <= 'z')) || c == '_' || c == '-') { | |||||
| 263 | p = tokenbuf; | |||||
| 264 | *p++ = c; | |||||
| 265 | c = nextch(fp, lastch); | |||||
| 266 | while (isalnum(c)(('0' <= (c) && (c) <= '9') || ('A' <= (c) && (c) <= 'Z') || ('a' <= (c) && (c) <= 'z')) || c == '_' || c == '-') { | |||||
| 267 | *p++ = c; | |||||
| 268 | c = nextch(fp, lastch); | |||||
| 269 | } | |||||
| 270 | *p = '\0'; | |||||
| 271 | putbackch(c, lastch); | |||||
| 272 | token = KEY8; | |||||
| 273 | } else { | |||||
| 274 | token = ERROR9; | |||||
| 275 | } | |||||
| 276 | break; | |||||
| 277 | } | |||||
| 278 | string_error: | |||||
| 279 | return(token); | |||||
| 280 | } | |||||
| 281 | ||||||
| 282 | static long | |||||
| 283 | modmask( | |||||
| 284 | char *name) | |||||
| 285 | { | |||||
| 286 | struct _modtbl { | |||||
| 287 | const char name[6]; | |||||
| 288 | long mask; | |||||
| 289 | }; | |||||
| 290 | ||||||
| 291 | static const struct _modtbl tbl[] = { | |||||
| 292 | { "Ctrl", ControlMask(1<<2) }, | |||||
| 293 | { "Lock", LockMask(1<<1) }, | |||||
| 294 | { "Caps", LockMask(1<<1) }, | |||||
| 295 | { "Shift", ShiftMask(1<<0) }, | |||||
| 296 | { "Alt", Mod1Mask(1<<3) }, | |||||
| 297 | { "Meta", Mod1Mask(1<<3) }}; | |||||
| 298 | ||||||
| 299 | int i, num_entries = sizeof (tbl) / sizeof (tbl[0]); | |||||
| 300 | ||||||
| 301 | for (i = 0; i < num_entries; i++) | |||||
| 302 | if (!strcmp (name, tbl[i].name)) | |||||
| 303 | return tbl[i].mask; | |||||
| 304 | ||||||
| 305 | return 0; | |||||
| 306 | } | |||||
| 307 | ||||||
| 308 | static char* | |||||
| 309 | TransFileName(Xim im, char *name) | |||||
| 310 | { | |||||
| 311 | char *home = NULL((void*)0), *lcCompose = NULL((void*)0); | |||||
| 312 | char dir[XLC_BUFSIZE256] = ""; | |||||
| 313 | char *i = name, *ret = NULL((void*)0), *j; | |||||
| 314 | size_t l = 0; | |||||
| 315 | ||||||
| 316 | while (*i) { | |||||
| ||||||
| 317 | if (*i == '%') { | |||||
| 318 | i++; | |||||
| 319 | switch (*i) { | |||||
| 320 | case '%': | |||||
| 321 | l++; | |||||
| 322 | break; | |||||
| 323 | case 'H': | |||||
| 324 | if (home == NULL((void*)0)) | |||||
| 325 | home = getenv("HOME"); | |||||
| 326 | if (home) { | |||||
| 327 | size_t Hsize = strlen(home); | |||||
| 328 | if (Hsize > PATH_MAX1024) | |||||
| 329 | /* your home directory length is ridiculous */ | |||||
| 330 | goto end; | |||||
| 331 | l += Hsize; | |||||
| 332 | } | |||||
| 333 | break; | |||||
| 334 | case 'L': | |||||
| 335 | if (lcCompose == NULL((void*)0)) | |||||
| 336 | lcCompose = _XlcFileName(im->core.lcd, COMPOSE_FILE"Compose"); | |||||
| 337 | if (lcCompose) { | |||||
| 338 | size_t Lsize = strlen(lcCompose); | |||||
| 339 | if (Lsize > PATH_MAX1024) | |||||
| 340 | /* your compose pathname length is ridiculous */ | |||||
| 341 | goto end; | |||||
| 342 | l += Lsize; | |||||
| 343 | } | |||||
| 344 | break; | |||||
| 345 | case 'S': | |||||
| 346 | if (dir[0] == '\0') | |||||
| 347 | xlocaledir(dir, XLC_BUFSIZE256); | |||||
| 348 | if (dir[0]) { | |||||
| 349 | size_t Ssize = strlen(dir); | |||||
| 350 | if (Ssize > PATH_MAX1024) | |||||
| 351 | /* your locale directory path length is ridiculous */ | |||||
| 352 | goto end; | |||||
| 353 | l += Ssize; | |||||
| 354 | } | |||||
| 355 | break; | |||||
| 356 | } | |||||
| 357 | } else { | |||||
| 358 | l++; | |||||
| 359 | } | |||||
| 360 | i++; | |||||
| 361 | if (l > PATH_MAX1024) | |||||
| 362 | /* your expanded path length is ridiculous */ | |||||
| 363 | goto end; | |||||
| 364 | } | |||||
| 365 | ||||||
| 366 | j = ret = Xmalloc(l+1)malloc(((l+1) == 0 ? 1 : (l+1))); | |||||
| 367 | if (ret == NULL((void*)0)) | |||||
| 368 | goto end; | |||||
| 369 | i = name; | |||||
| 370 | while (*i) { | |||||
| 371 | if (*i == '%') { | |||||
| 372 | i++; | |||||
| 373 | switch (*i) { | |||||
| 374 | case '%': | |||||
| 375 | *j++ = '%'; | |||||
| 376 | break; | |||||
| 377 | case 'H': | |||||
| 378 | if (home) { | |||||
| 379 | strcpy(j, home)__builtin___strcpy_chk (j, home, __builtin_object_size (j, 2 > 1 ? 1 : 0)); | |||||
| 380 | j += strlen(home); | |||||
| 381 | } | |||||
| 382 | break; | |||||
| 383 | case 'L': | |||||
| 384 | if (lcCompose) { | |||||
| 385 | strcpy(j, lcCompose)__builtin___strcpy_chk (j, lcCompose, __builtin_object_size ( j, 2 > 1 ? 1 : 0)); | |||||
| 386 | j += strlen(lcCompose); | |||||
| 387 | } | |||||
| 388 | break; | |||||
| 389 | case 'S': | |||||
| 390 | strcpy(j, dir)__builtin___strcpy_chk (j, dir, __builtin_object_size (j, 2 > 1 ? 1 : 0)); | |||||
| ||||||
| 391 | j += strlen(dir); | |||||
| 392 | break; | |||||
| 393 | } | |||||
| 394 | i++; | |||||
| 395 | } else { | |||||
| 396 | *j++ = *i++; | |||||
| 397 | } | |||||
| 398 | } | |||||
| 399 | *j = '\0'; | |||||
| 400 | end: | |||||
| 401 | Xfree(lcCompose)free((lcCompose)); | |||||
| 402 | return ret; | |||||
| 403 | } | |||||
| 404 | ||||||
| 405 | #ifndef MB_LEN_MAX6 | |||||
| 406 | #define MB_LEN_MAX6 6 | |||||
| 407 | #endif | |||||
| 408 | ||||||
| 409 | static int | |||||
| 410 | get_mb_string (Xim im, char *buf, KeySym ks) | |||||
| 411 | { | |||||
| 412 | XPointer from, to; | |||||
| 413 | int from_len, to_len, len; | |||||
| 414 | XPointer args[1]; | |||||
| 415 | XlcCharSet charset; | |||||
| 416 | char local_buf[MB_LEN_MAX6]; | |||||
| 417 | unsigned int ucs; | |||||
| 418 | ucs = KeySymToUcs4(ks); | |||||
| 419 | ||||||
| 420 | from = (XPointer) &ucs; | |||||
| 421 | to = (XPointer) local_buf; | |||||
| 422 | from_len = 1; | |||||
| 423 | to_len = MB_LEN_MAX6; | |||||
| 424 | args[0] = (XPointer) &charset; | |||||
| 425 | if (_XlcConvert(im->private.local.ucstoc_conv, | |||||
| 426 | &from, &from_len, &to, &to_len, args, 1 ) != 0) { | |||||
| 427 | return 0; | |||||
| 428 | } | |||||
| 429 | ||||||
| 430 | from = (XPointer) local_buf; | |||||
| 431 | to = (XPointer) buf; | |||||
| 432 | from_len = MB_LEN_MAX6 - to_len; | |||||
| 433 | to_len = MB_LEN_MAX6 + 1; | |||||
| 434 | args[0] = (XPointer) charset; | |||||
| 435 | if (_XlcConvert(im->private.local.cstomb_conv, | |||||
| 436 | &from, &from_len, &to, &to_len, args, 1 ) != 0) { | |||||
| 437 | return 0; | |||||
| 438 | } | |||||
| 439 | len = MB_LEN_MAX6 + 1 - to_len; | |||||
| 440 | buf[len] = '\0'; | |||||
| 441 | return len; | |||||
| 442 | } | |||||
| 443 | ||||||
| 444 | #define AllMask((1<<0) | (1<<1) | (1<<2) | (1<<3)) (ShiftMask(1<<0) | LockMask(1<<1) | ControlMask(1<<2) | Mod1Mask(1<<3)) | |||||
| 445 | #define LOCAL_WC_BUFSIZE128 128 | |||||
| 446 | #define LOCAL_UTF8_BUFSIZE256 256 | |||||
| 447 | #define SEQUENCE_MAX10 10 | |||||
| 448 | ||||||
| 449 | static int | |||||
| 450 | parseline( | |||||
| 451 | FILE *fp, | |||||
| 452 | Xim im, | |||||
| 453 | char* tokenbuf, | |||||
| 454 | int depth) | |||||
| 455 | { | |||||
| 456 | int token; | |||||
| 457 | DTModifier modifier_mask; | |||||
| 458 | DTModifier modifier; | |||||
| 459 | DTModifier tmp; | |||||
| 460 | KeySym keysym = NoSymbol0L; | |||||
| 461 | DTIndex *top = &im->private.local.top; | |||||
| 462 | DefTreeBase *b = &im->private.local.base; | |||||
| 463 | DTIndex t; | |||||
| 464 | DefTree *p = NULL((void*)0); | |||||
| 465 | Boolint exclam, tilde; | |||||
| 466 | KeySym rhs_keysym = 0; | |||||
| 467 | char *rhs_string_mb; | |||||
| 468 | int l; | |||||
| 469 | int lastch = 0; | |||||
| 470 | char local_mb_buf[MB_LEN_MAX6+1]; | |||||
| 471 | wchar_t local_wc_buf[LOCAL_WC_BUFSIZE128], *rhs_string_wc; | |||||
| 472 | char local_utf8_buf[LOCAL_UTF8_BUFSIZE256], *rhs_string_utf8; | |||||
| 473 | ||||||
| 474 | struct DefBuffer { | |||||
| 475 | DTModifier modifier_mask; | |||||
| 476 | DTModifier modifier; | |||||
| 477 | KeySym keysym; | |||||
| 478 | }; | |||||
| 479 | ||||||
| 480 | struct DefBuffer buf[SEQUENCE_MAX10]; | |||||
| 481 | int i, n; | |||||
| 482 | ||||||
| 483 | do { | |||||
| 484 | token = nexttoken(fp, tokenbuf, &lastch); | |||||
| 485 | } while (token == ENDOFLINE1); | |||||
| 486 | ||||||
| 487 | if (token == ENDOFFILE0) { | |||||
| 488 | return(-1); | |||||
| 489 | } | |||||
| 490 | ||||||
| 491 | n = 0; | |||||
| 492 | do { | |||||
| 493 | if ((token == KEY8) && (strcmp("include", tokenbuf) == 0)) { | |||||
| 494 | char *filename; | |||||
| 495 | FILE *infp; | |||||
| 496 | token = nexttoken(fp, tokenbuf, &lastch); | |||||
| 497 | if (token != KEY8 && token != STRING7) | |||||
| 498 | goto error; | |||||
| 499 | if (++depth > 100) | |||||
| 500 | goto error; | |||||
| 501 | if ((filename = TransFileName(im, tokenbuf)) == NULL((void*)0)) | |||||
| 502 | goto error; | |||||
| 503 | infp = _XFopenFile(filename, "r")fopen(filename,"r"); | |||||
| 504 | Xfree(filename)free((filename)); | |||||
| 505 | if (infp == NULL((void*)0)) | |||||
| 506 | goto error; | |||||
| 507 | parsestringfile(infp, im, depth); | |||||
| 508 | fclose(infp); | |||||
| 509 | return (0); | |||||
| 510 | } else if ((token == KEY8) && (strcmp("None", tokenbuf) == 0)) { | |||||
| 511 | modifier = 0; | |||||
| 512 | modifier_mask = AllMask((1<<0) | (1<<1) | (1<<2) | (1<<3)); | |||||
| 513 | token = nexttoken(fp, tokenbuf, &lastch); | |||||
| 514 | } else { | |||||
| 515 | modifier_mask = modifier = 0; | |||||
| 516 | exclam = False0; | |||||
| 517 | if (token == EXCLAM5) { | |||||
| 518 | exclam = True1; | |||||
| 519 | token = nexttoken(fp, tokenbuf, &lastch); | |||||
| 520 | } | |||||
| 521 | while (token == TILDE6 || token == KEY8) { | |||||
| 522 | tilde = False0; | |||||
| 523 | if (token == TILDE6) { | |||||
| 524 | tilde = True1; | |||||
| 525 | token = nexttoken(fp, tokenbuf, &lastch); | |||||
| 526 | if (token != KEY8) | |||||
| 527 | goto error; | |||||
| 528 | } | |||||
| 529 | tmp = modmask(tokenbuf); | |||||
| 530 | if (!tmp) { | |||||
| 531 | goto error; | |||||
| 532 | } | |||||
| 533 | modifier_mask |= tmp; | |||||
| 534 | if (tilde) { | |||||
| 535 | modifier &= ~tmp; | |||||
| 536 | } else { | |||||
| 537 | modifier |= tmp; | |||||
| 538 | } | |||||
| 539 | token = nexttoken(fp, tokenbuf, &lastch); | |||||
| 540 | } | |||||
| 541 | if (exclam) { | |||||
| 542 | modifier_mask = AllMask((1<<0) | (1<<1) | (1<<2) | (1<<3)); | |||||
| 543 | } | |||||
| 544 | } | |||||
| 545 | ||||||
| 546 | if (token != LESS3) { | |||||
| 547 | goto error; | |||||
| 548 | } | |||||
| 549 | ||||||
| 550 | token = nexttoken(fp, tokenbuf, &lastch); | |||||
| 551 | if (token != KEY8) { | |||||
| 552 | goto error; | |||||
| 553 | } | |||||
| 554 | ||||||
| 555 | token = nexttoken(fp, tokenbuf, &lastch); | |||||
| 556 | if (token != GREATER4) { | |||||
| 557 | goto error; | |||||
| 558 | } | |||||
| 559 | ||||||
| 560 | keysym = XStringToKeysym(tokenbuf); | |||||
| 561 | if (keysym == NoSymbol0L) { | |||||
| 562 | goto error; | |||||
| 563 | } | |||||
| 564 | ||||||
| 565 | buf[n].keysym = keysym; | |||||
| 566 | buf[n].modifier = modifier; | |||||
| 567 | buf[n].modifier_mask = modifier_mask; | |||||
| 568 | n++; | |||||
| 569 | if( n >= SEQUENCE_MAX10 ) | |||||
| 570 | goto error; | |||||
| 571 | token = nexttoken(fp, tokenbuf, &lastch); | |||||
| 572 | } while (token != COLON2); | |||||
| 573 | ||||||
| 574 | token = nexttoken(fp, tokenbuf, &lastch); | |||||
| 575 | if (token == STRING7) { | |||||
| 576 | l = strlen(tokenbuf) + 1; | |||||
| 577 | while (b->mbused + l > b->mbsize) { | |||||
| 578 | DTCharIndex newsize = b->mbsize ? b->mbsize * 1.5 : 1024; | |||||
| 579 | char *newmb = Xrealloc (b->mb, newsize)realloc((b->mb), ((newsize) == 0 ? 1 : (newsize))); | |||||
| 580 | if (newmb == NULL((void*)0)) | |||||
| 581 | goto error; | |||||
| 582 | b->mb = newmb; | |||||
| 583 | b->mbsize = newsize; | |||||
| 584 | } | |||||
| 585 | rhs_string_mb = &b->mb[b->mbused]; | |||||
| 586 | b->mbused += l; | |||||
| 587 | strcpy(rhs_string_mb, tokenbuf)__builtin___strcpy_chk (rhs_string_mb, tokenbuf, __builtin_object_size (rhs_string_mb, 2 > 1 ? 1 : 0)); | |||||
| 588 | token = nexttoken(fp, tokenbuf, &lastch); | |||||
| 589 | if (token == KEY8) { | |||||
| 590 | rhs_keysym = XStringToKeysym(tokenbuf); | |||||
| 591 | if (rhs_keysym == NoSymbol0L) { | |||||
| 592 | goto error; | |||||
| 593 | } | |||||
| 594 | token = nexttoken(fp, tokenbuf, &lastch); | |||||
| 595 | } | |||||
| 596 | if (token != ENDOFLINE1 && token != ENDOFFILE0) { | |||||
| 597 | goto error; | |||||
| 598 | } | |||||
| 599 | } else if (token == KEY8) { | |||||
| 600 | rhs_keysym = XStringToKeysym(tokenbuf); | |||||
| 601 | if (rhs_keysym == NoSymbol0L) { | |||||
| 602 | goto error; | |||||
| 603 | } | |||||
| 604 | token = nexttoken(fp, tokenbuf, &lastch); | |||||
| 605 | if (token != ENDOFLINE1 && token != ENDOFFILE0) { | |||||
| 606 | goto error; | |||||
| 607 | } | |||||
| 608 | ||||||
| 609 | l = get_mb_string(im, local_mb_buf, rhs_keysym); | |||||
| 610 | while (b->mbused + l + 1 > b->mbsize) { | |||||
| 611 | DTCharIndex newsize = b->mbsize ? b->mbsize * 1.5 : 1024; | |||||
| 612 | char *newmb = Xrealloc (b->mb, newsize)realloc((b->mb), ((newsize) == 0 ? 1 : (newsize))); | |||||
| 613 | if (newmb == NULL((void*)0)) | |||||
| 614 | goto error; | |||||
| 615 | b->mb = newmb; | |||||
| 616 | b->mbsize = newsize; | |||||
| 617 | } | |||||
| 618 | rhs_string_mb = &b->mb[b->mbused]; | |||||
| 619 | b->mbused += l + 1; | |||||
| 620 | memcpy(rhs_string_mb, local_mb_buf, l)__builtin___memcpy_chk (rhs_string_mb, local_mb_buf, l, __builtin_object_size (rhs_string_mb, 0)); | |||||
| 621 | rhs_string_mb[l] = '\0'; | |||||
| 622 | } else { | |||||
| 623 | goto error; | |||||
| 624 | } | |||||
| 625 | ||||||
| 626 | l = _Xmbstowcs(local_wc_buf, rhs_string_mb, LOCAL_WC_BUFSIZE128 - 1); | |||||
| 627 | if (l == LOCAL_WC_BUFSIZE128 - 1) { | |||||
| 628 | local_wc_buf[l] = (wchar_t)'\0'; | |||||
| 629 | } | |||||
| 630 | while (b->wcused + l + 1 > b->wcsize) { | |||||
| 631 | DTCharIndex newsize = b->wcsize ? b->wcsize * 1.5 : 512; | |||||
| 632 | wchar_t *newwc = Xrealloc (b->wc, sizeof(wchar_t) * newsize)realloc((b->wc), ((sizeof(wchar_t) * newsize) == 0 ? 1 : ( sizeof(wchar_t) * newsize))); | |||||
| 633 | if (newwc == NULL((void*)0)) | |||||
| 634 | goto error; | |||||
| 635 | b->wc = newwc; | |||||
| 636 | b->wcsize = newsize; | |||||
| 637 | } | |||||
| 638 | rhs_string_wc = &b->wc[b->wcused]; | |||||
| 639 | b->wcused += l + 1; | |||||
| 640 | memcpy((char *)rhs_string_wc, (char *)local_wc_buf, (l + 1) * sizeof(wchar_t) )__builtin___memcpy_chk ((char *)rhs_string_wc, (char *)local_wc_buf , (l + 1) * sizeof(wchar_t), __builtin_object_size ((char *)rhs_string_wc , 0)); | |||||
| 641 | ||||||
| 642 | l = _Xmbstoutf8(local_utf8_buf, rhs_string_mb, LOCAL_UTF8_BUFSIZE256 - 1); | |||||
| 643 | if (l == LOCAL_UTF8_BUFSIZE256 - 1) { | |||||
| 644 | local_utf8_buf[l] = '\0'; | |||||
| 645 | } | |||||
| 646 | while (b->utf8used + l + 1 > b->utf8size) { | |||||
| 647 | DTCharIndex newsize = b->utf8size ? b->utf8size * 1.5 : 1024; | |||||
| 648 | char *newutf8 = Xrealloc (b->utf8, newsize)realloc((b->utf8), ((newsize) == 0 ? 1 : (newsize))); | |||||
| 649 | if (newutf8 == NULL((void*)0)) | |||||
| 650 | goto error; | |||||
| 651 | b->utf8 = newutf8; | |||||
| 652 | b->utf8size = newsize; | |||||
| 653 | } | |||||
| 654 | rhs_string_utf8 = &b->utf8[b->utf8used]; | |||||
| 655 | b->utf8used += l + 1; | |||||
| 656 | memcpy(rhs_string_utf8, local_utf8_buf, l + 1)__builtin___memcpy_chk (rhs_string_utf8, local_utf8_buf, l + 1 , __builtin_object_size (rhs_string_utf8, 0)); | |||||
| 657 | ||||||
| 658 | for (i = 0; i < n; i++) { | |||||
| 659 | for (t = *top; t; t = b->tree[t].next) { | |||||
| 660 | if (buf[i].keysym == b->tree[t].keysym && | |||||
| 661 | buf[i].modifier == b->tree[t].modifier && | |||||
| 662 | buf[i].modifier_mask == b->tree[t].modifier_mask) { | |||||
| 663 | break; | |||||
| 664 | } | |||||
| 665 | } | |||||
| 666 | if (t) { | |||||
| 667 | p = &b->tree[t]; | |||||
| 668 | top = &p->succession; | |||||
| 669 | } else { | |||||
| 670 | while (b->treeused >= b->treesize) { | |||||
| 671 | DefTree *old = b->tree; | |||||
| 672 | int oldsize = b->treesize; | |||||
| 673 | int newsize = b->treesize ? b->treesize * 1.5 : 256; | |||||
| 674 | DefTree *new = Xrealloc (b->tree, sizeof(DefTree) * newsize)realloc((b->tree), ((sizeof(DefTree) * newsize) == 0 ? 1 : (sizeof(DefTree) * newsize))); | |||||
| 675 | if (new == NULL((void*)0)) | |||||
| 676 | goto error; | |||||
| 677 | b->tree = new; | |||||
| 678 | b->treesize = newsize; | |||||
| 679 | if (top >= (DTIndex *) old && top < (DTIndex *) &old[oldsize]) | |||||
| 680 | top = (DTIndex *) (((char *) top) + (((char *)b->tree)-(char *)old)); | |||||
| 681 | } | |||||
| 682 | p = &b->tree[b->treeused]; | |||||
| 683 | p->keysym = buf[i].keysym; | |||||
| 684 | p->modifier = buf[i].modifier; | |||||
| 685 | p->modifier_mask = buf[i].modifier_mask; | |||||
| 686 | p->succession = 0; | |||||
| 687 | p->next = *top; | |||||
| 688 | p->mb = 0; | |||||
| 689 | p->wc = 0; | |||||
| 690 | p->utf8 = 0; | |||||
| 691 | p->ks = NoSymbol0L; | |||||
| 692 | *top = b->treeused; | |||||
| 693 | top = &p->succession; | |||||
| 694 | b->treeused++; | |||||
| 695 | } | |||||
| 696 | } | |||||
| 697 | ||||||
| 698 | /* old entries no longer freed... */ | |||||
| 699 | p->mb = rhs_string_mb - b->mb; | |||||
| 700 | p->wc = rhs_string_wc - b->wc; | |||||
| 701 | p->utf8 = rhs_string_utf8 - b->utf8; | |||||
| 702 | p->ks = rhs_keysym; | |||||
| 703 | return(n); | |||||
| 704 | error: | |||||
| 705 | while (token != ENDOFLINE1 && token != ENDOFFILE0) { | |||||
| 706 | token = nexttoken(fp, tokenbuf, &lastch); | |||||
| 707 | } | |||||
| 708 | return(0); | |||||
| 709 | } | |||||
| 710 | ||||||
| 711 | void | |||||
| 712 | _XimParseStringFile( | |||||
| 713 | FILE *fp, | |||||
| 714 | Xim im) | |||||
| 715 | { | |||||
| 716 | parsestringfile(fp, im, 0); | |||||
| 717 | } | |||||
| 718 | ||||||
| 719 | static void | |||||
| 720 | parsestringfile( | |||||
| 721 | FILE *fp, | |||||
| 722 | Xim im, | |||||
| 723 | int depth) | |||||
| 724 | { | |||||
| 725 | char tb[8192]; | |||||
| 726 | char* tbp; | |||||
| 727 | struct stat st; | |||||
| 728 | ||||||
| 729 | if (fstat (fileno (fp), &st) != -1) { | |||||
| 730 | unsigned long size = (unsigned long) st.st_size; | |||||
| 731 | if (st.st_size >= INT_MAX2147483647) | |||||
| 732 | return; | |||||
| 733 | if (size <= sizeof tb) tbp = tb; | |||||
| 734 | else tbp = malloc (size); | |||||
| 735 | ||||||
| 736 | if (tbp != NULL((void*)0)) { | |||||
| 737 | while (parseline(fp, im, tbp, depth) >= 0) {} | |||||
| 738 | if (tbp != tb) free (tbp); | |||||
| 739 | } | |||||
| 740 | } | |||||
| 741 | } |