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 | } |