diff options
| author | Eli Zaretskii | 2014-10-13 14:26:58 +0300 |
|---|---|---|
| committer | Eli Zaretskii | 2014-10-13 14:26:58 +0300 |
| commit | e5500a96a713c75131806bf70d0ea752ec6b9392 (patch) | |
| tree | 3d21d5ecfcec70734d1b3ad9a4d0d524071fa31b /src/bidi.c | |
| parent | b8140e6ead2ab8149c9a450936a46cbddd19a337 (diff) | |
| download | emacs-e5500a96a713c75131806bf70d0ea752ec6b9392.tar.gz emacs-e5500a96a713c75131806bf70d0ea752ec6b9392.zip | |
Fixed BPA stack overflow and infloop with nested brackets.
Diffstat (limited to 'src/bidi.c')
| -rw-r--r-- | src/bidi.c | 32 |
1 files changed, 20 insertions, 12 deletions
diff --git a/src/bidi.c b/src/bidi.c index 6d5f281d571..d03aa4e3e10 100644 --- a/src/bidi.c +++ b/src/bidi.c | |||
| @@ -2353,7 +2353,10 @@ typedef struct bpa_stack_entry { | |||
| 2353 | do { \ | 2353 | do { \ |
| 2354 | bpa_sp++; \ | 2354 | bpa_sp++; \ |
| 2355 | if (bpa_sp >= MAX_BPA_STACK) \ | 2355 | if (bpa_sp >= MAX_BPA_STACK) \ |
| 2356 | goto bpa_give_up; \ | 2356 | { \ |
| 2357 | bpa_sp = MAX_BPA_STACK - 1; \ | ||
| 2358 | goto bpa_give_up; \ | ||
| 2359 | } \ | ||
| 2357 | bpa_stack[bpa_sp].close_bracket_char = bidi_mirror_char (bidi_it->ch); \ | 2360 | bpa_stack[bpa_sp].close_bracket_char = bidi_mirror_char (bidi_it->ch); \ |
| 2358 | bpa_stack[bpa_sp].open_bracket_idx = bidi_cache_last_idx; \ | 2361 | bpa_stack[bpa_sp].open_bracket_idx = bidi_cache_last_idx; \ |
| 2359 | STORE_BRACKET_CHARPOS; \ | 2362 | STORE_BRACKET_CHARPOS; \ |
| @@ -2389,10 +2392,15 @@ bidi_resolve_bracket_pairs (struct bidi_it *bidi_it) | |||
| 2389 | struct bidi_it saved_it; | 2392 | struct bidi_it saved_it; |
| 2390 | bidi_type_t last_strong; | 2393 | bidi_type_t last_strong; |
| 2391 | int embedding_level = bidi_it->level_stack[bidi_it->stack_idx].level; | 2394 | int embedding_level = bidi_it->level_stack[bidi_it->stack_idx].level; |
| 2395 | struct bidi_it tem_it; | ||
| 2392 | 2396 | ||
| 2393 | eassert (MAX_BPA_STACK >= 100); | 2397 | eassert (MAX_BPA_STACK >= 100); |
| 2394 | bidi_copy_it (&saved_it, bidi_it); | 2398 | bidi_copy_it (&saved_it, bidi_it); |
| 2395 | last_strong = bidi_it->prev_for_neutral.type; | 2399 | last_strong = bidi_it->prev_for_neutral.type; |
| 2400 | /* bidi_cache_iterator_state refuses to cache on backward scans, | ||
| 2401 | and bidi_cache_fetch_state doesn't bring scan_dir from the | ||
| 2402 | cache, so we must initialize this explicitly. */ | ||
| 2403 | tem_it.scan_dir = 1; | ||
| 2396 | 2404 | ||
| 2397 | while (1) | 2405 | while (1) |
| 2398 | { | 2406 | { |
| @@ -2422,17 +2430,16 @@ bidi_resolve_bracket_pairs (struct bidi_it *bidi_it) | |||
| 2422 | else if (bpa_stack[sp].flags & FLAG_OPPOSITE_INSIDE) /*N0c2*/ | 2430 | else if (bpa_stack[sp].flags & FLAG_OPPOSITE_INSIDE) /*N0c2*/ |
| 2423 | type = ((embedding_level & 1) ? STRONG_R : STRONG_L); | 2431 | type = ((embedding_level & 1) ? STRONG_R : STRONG_L); |
| 2424 | 2432 | ||
| 2425 | /* Update and cache the closing bracket. */ | 2433 | /* Update the type of the closing bracket. */ |
| 2426 | bidi_it->type = type; | 2434 | bidi_it->type = type; |
| 2427 | bidi_it->bracket_resolved = 1; | ||
| 2428 | bidi_cache_iterator_state (bidi_it, 0, 0); | ||
| 2429 | /* Update and cache the corresponding opening bracket. */ | 2435 | /* Update and cache the corresponding opening bracket. */ |
| 2430 | bidi_cache_fetch_state (bpa_stack[sp].open_bracket_idx, | 2436 | bidi_cache_fetch_state (bpa_stack[sp].open_bracket_idx, |
| 2431 | bidi_it); | 2437 | &tem_it); |
| 2432 | #ifdef ENABLE_CHECKING | 2438 | #ifdef ENABLE_CHECKING |
| 2433 | eassert (bpa_stack[sp].open_bracket_pos == bidi_it->charpos); | 2439 | eassert (bpa_stack[sp].open_bracket_pos == tem_it.charpos); |
| 2434 | #endif | 2440 | #endif |
| 2435 | bidi_it->type = type; | 2441 | tem_it.type = type; |
| 2442 | bidi_cache_iterator_state (&tem_it, 0, 0); | ||
| 2436 | bpa_sp = sp - 1; | 2443 | bpa_sp = sp - 1; |
| 2437 | } | 2444 | } |
| 2438 | bidi_it->bracket_resolved = 1; | 2445 | bidi_it->bracket_resolved = 1; |
| @@ -2496,17 +2503,18 @@ bidi_resolve_bracket_pairs (struct bidi_it *bidi_it) | |||
| 2496 | isolating run sequence, and didn't find matching | 2503 | isolating run sequence, and didn't find matching |
| 2497 | closing brackets for some opening brackets. Unwind | 2504 | closing brackets for some opening brackets. Unwind |
| 2498 | whatever is left on the BPA stack, and mark each | 2505 | whatever is left on the BPA stack, and mark each |
| 2499 | bracket there as BPA-resolved. */ | 2506 | bracket there as BPA-resolved, leaving their type |
| 2507 | unchanged. */ | ||
| 2500 | while (bpa_sp >= 0) | 2508 | while (bpa_sp >= 0) |
| 2501 | { | 2509 | { |
| 2502 | bidi_cache_fetch_state (bpa_stack[bpa_sp].open_bracket_idx, | 2510 | bidi_cache_fetch_state (bpa_stack[bpa_sp].open_bracket_idx, |
| 2503 | bidi_it); | 2511 | &tem_it); |
| 2504 | #ifdef ENABLE_CHECKING | 2512 | #ifdef ENABLE_CHECKING |
| 2505 | eassert (bpa_stack[bpa_sp].open_bracket_pos | 2513 | eassert (bpa_stack[bpa_sp].open_bracket_pos |
| 2506 | == bidi_it->charpos); | 2514 | == tem_it.charpos); |
| 2507 | #endif | 2515 | #endif |
| 2508 | bidi_it->bracket_resolved = 1; | 2516 | tem_it.bracket_resolved = 1; |
| 2509 | bidi_cache_iterator_state (bidi_it, 0, 0); | 2517 | bidi_cache_iterator_state (&tem_it, 0, 0); |
| 2510 | bpa_sp--; | 2518 | bpa_sp--; |
| 2511 | } | 2519 | } |
| 2512 | type = saved_it.type; | 2520 | type = saved_it.type; |