Espeak-ng 1.52-dev was discovered to contain a Stack Buffer Overflow via the function RemoveEnding at dictionary.c.
**System info**
Ubuntu x86_64, clang 12.0
version: espeak-ng(1.52-dev)

**Command line**
./espeak-ng -f poc -w /dev/null

**Poc**
poc:[poc](https://github.com/SEU-SSL/Poc/blob/main/espeak-ng/id_000209%2Csig_07%2Csrc_000384%2Cop_havoc%2Crep_32)

**AddressSanitizer output**
==4070654==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffce78764a0 at pc 0x00000049796a bp 0x7ffce78758d0 sp 0x7ffce7875098
WRITE of size 393 at 0x7ffce78764a0 thread T0
 #0 0x497969 in __asan_memcpy (/src/espeak-ng/src/espeak-ng+0x497969)
 #1 0x51c13e in RemoveEnding /src/espeak-ng/src/libespeak-ng/dictionary.c:2902:3
 #2 0x5853f2 in TranslateWord3 /src/espeak-ng/src/libespeak-ng/translateword.c:444:17
 #3 0x570911 in TranslateWord /src/espeak-ng/src/libespeak-ng/translate.c:150:14
 #4 0x57c9ca in TranslateWord2 /src/espeak-ng/src/libespeak-ng/translate.c:404:11
 #5 0x57951f in TranslateClause /src/espeak-ng/src/libespeak-ng/translate.c:1594:17
 #6 0x56fe0b in SpeakNextClause /src/espeak-ng/src/libespeak-ng/synthesize.c:1560:2
 #7 0x5430bc in Synthesize /src/espeak-ng/src/libespeak-ng/speech.c:455:2
 #8 0x544552 in sync_espeak_Synth /src/espeak-ng/src/libespeak-ng/speech.c:571:29
 #9 0x544552 in espeak_ng_Synthesize /src/espeak-ng/src/libespeak-ng/speech.c:669:10
 #10 0x51fa9e in espeak_Synth /src/espeak-ng/src/libespeak-ng/espeak_api.c:90:32
 #11 0x4cde94 in main /src/espeak-ng/src/espeak-ng.c:779:3
 #12 0x7f9c6597c082 in __libc_start_main /build/glibc-BHL3KM/glibc-2.31/csu/../csu/libc-start.c:308:16
 #13 0x41d64d in _start (/src/espeak-ng/src/espeak-ng+0x41d64d)

Address 0x7ffce78764a0 is located in stack of thread T0 at offset 2368 in frame
 #0 0x58082f in TranslateWord3 /src/espeak-ng/src/libespeak-ng/translateword.c:59

This frame has 25 object(s):
 [32, 232) 'ph_buf.i.i' (line 1191)
 [304, 308) 'c.i' (line 1122)
 [320, 324) 'wc.i' (line 1048)
 [336, 416) 'word_buf.i' (line 1053)
 [448, 456) 'word1' (line 62)
 [480, 488) 'dictionary_flags' (line 68)
 [512, 520) 'dictionary_flags2' (line 69)
 [544, 552) 'wordx' (line 74)
 [576, 776) 'phonemes' (line 75)
 [848, 1048) 'phonemes2' (line 76)
 [1120, 1320) 'prefix_phonemes' (line 77)
 [1392, 1592) 'unpron_phonemes' (line 78)
 [1664, 1864) 'end_phonemes' (line 79)
 [1936, 2136) 'end_phonemes2' (line 80)
 [2208, 2368) 'word_copy' (line 81)
 [2432, 2592) 'word_copy2' (line 82) <== Memory access at offset 2368 partially underflows this variable

[2656, 2721) 'prefix_chars' (line 84) <== Memory access at offset 2368 partially underflows this variable
 [2768, 2772) 'c_temp' (line 87)
 [2784, 2788) 'first_char' (line 88)
 [2800, 2804) 'last_char' (line 89)
 [2816, 2912) 'wtab_null' (line 99)
 [2944, 2948) 'wc' (line 322)
 [2960, 3160) 'end_phonemes2410' (line 343)
 [3232, 3240) 'wordpf' (line 401)
 [3264, 3276) 'prefix_phonemes2' (line 402)
HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork
 (longjmp and C++ exceptions *are* supported)
SUMMARY: AddressSanitizer: stack-buffer-overflow (/src/espeak-ng/src/espeak-ng+0x497969) in __asan_memcpy
Shadow bytes around the buggy address:
 0x10001cf06c40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 0x10001cf06c50: 00 00 00 00 00 f2 f2 f2 f2 f2 f2 f2 f2 f2 00 00
 0x10001cf06c60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 0x10001cf06c70: 00 00 00 00 00 00 00 f2 f2 f2 f2 f2 f2 f2 f2 f2
 0x10001cf06c80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x10001cf06c90: 00 00 00 00[f2]f2 f2 f2 f2 f2 f2 f2 00 00 00 00
 0x10001cf06ca0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 0x10001cf06cb0: f2 f2 f2 f2 f2 f2 f2 f2 00 00 00 00 00 00 00 00
 0x10001cf06cc0: 01 f2 f2 f2 f2 f2 04 f2 04 f2 04 f2 00 00 00 00
 0x10001cf06cd0: 00 00 00 00 00 00 00 00 f2 f2 f2 f2 f8 f2 f8 f8
 0x10001cf06ce0: f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8
Shadow byte legend (one shadow byte represents 8 application bytes):
 Addressable: 00
 Partially addressable: 01 02 03 04 05 06 07
 Heap left redzone: fa
 Freed heap region: fd
 Stack left redzone: f1
 Stack mid redzone: f2
 Stack right redzone: f3
 Stack after return: f5
 Stack use after scope: f8
 Global redzone: f9
 Global init order: f6

 Poisoned by user: f7
 Container overflow: fc
 Array cookie: ac
 Intra object redzone: bb
 ASan internal: fe
 Left alloca redzone: ca
 Right alloca redzone: cb
 Shadow gap: cc
==4070654==ABORTING
stack-buffer-overflow exists in the function RemoveEnding in dictionary.c
This is a GitHub Issue
repo:espeak-ng
owner:espeak-ng
Title : stack-buffer-overflow exists in the function RemoveEnding in dictionary.c
Issue date:

--- start body ---
**System info**
Ubuntu x86_64, clang 12.0
version: espeak-ng(1.52-dev)

**Command line**
./espeak-ng -f poc -w /dev/null

**Poc**
poc:[poc](https://github.com/SEU-SSL/Poc/blob/main/espeak-ng/id_000209%2Csig_07%2Csrc_000384%2Cop_havoc%2Crep_32)

**AddressSanitizer output**
==4070654==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffce78764a0 at pc 0x00000049796a bp 0x7ffce78758d0 sp 0x7ffce7875098
WRITE of size 393 at 0x7ffce78764a0 thread T0
 #0 0x497969 in __asan_memcpy (/src/espeak-ng/src/espeak-ng+0x497969)
 #1 0x51c13e in RemoveEnding /src/espeak-ng/src/libespeak-ng/dictionary.c:2902:3
 #2 0x5853f2 in TranslateWord3 /src/espeak-ng/src/libespeak-ng/translateword.c:444:17
 #3 0x570911 in TranslateWord /src/espeak-ng/src/libespeak-ng/translate.c:150:14
 #4 0x57c9ca in TranslateWord2 /src/espeak-ng/src/libespeak-ng/translate.c:404:11
 #5 0x57951f in TranslateClause /src/espeak-ng/src/libespeak-ng/translate.c:1594:17
 #6 0x56fe0b in SpeakNextClause /src/espeak-ng/src/libespeak-ng/synthesize.c:1560:2
 #7 0x5430bc in Synthesize /src/espeak-ng/src/libespeak-ng/speech.c:455:2
 #8 0x544552 in sync_espeak_Synth /src/espeak-ng/src/libespeak-ng/speech.c:571:29
 #9 0x544552 in espeak_ng_Synthesize /src/espeak-ng/src/libespeak-ng/speech.c:669:10
 #10 0x51fa9e in espeak_Synth /src/espeak-ng/src/libespeak-ng/espeak_api.c:90:32
 #11 0x4cde94 in main /src/espeak-ng/src/espeak-ng.c:779:3
 #12 0x7f9c6597c082 in __libc_start_main /build/glibc-BHL3KM/glibc-2.31/csu/../csu/libc-start.c:308:16
 #13 0x41d64d in _start (/src/espeak-ng/src/espeak-ng+0x41d64d)

Address 0x7ffce78764a0 is located in stack of thread T0 at offset 2368 in frame
 #0 0x58082f in TranslateWord3 /src/espeak-ng/src/libespeak-ng/translateword.c:59

This frame has 25 object(s):
 [32, 232) 'ph_buf.i.i' (line 1191)
 [304, 308) 'c.i' (line 1122)
 [320, 324) 'wc.i' (line 1048)
 [336, 416) 'word_buf.i' (line 1053)
 [448, 456) 'word1' (line 62)
 [480, 488) 'dictionary_flags' (line 68)
 [512, 520) 'dictionary_flags2' (line 69)
 [544, 552) 'wordx' (line 74)
 [576, 776) 'phonemes' (line 75)
 [848, 1048) 'phonemes2' (line 76)
 [1120, 1320) 'prefix_phonemes' (line 77)
 [1392, 1592) 'unpron_phonemes' (line 78)
 [1664, 1864) 'end_phonemes' (line 79)
 [1936, 2136) 'end_phonemes2' (line 80)
 [2208, 2368) 'word_copy' (line 81)
 [2432, 2592) 'word_copy2' (line 82) <== Memory access at offset 2368 partially underflows this variable

[2656, 2721) 'prefix_chars' (line 84) <== Memory access at offset 2368 partially underflows this variable
 [2768, 2772) 'c_temp' (line 87)
 [2784, 2788) 'first_char' (line 88)
 [2800, 2804) 'last_char' (line 89)
 [2816, 2912) 'wtab_null' (line 99)
 [2944, 2948) 'wc' (line 322)
 [2960, 3160) 'end_phonemes2410' (line 343)
 [3232, 3240) 'wordpf' (line 401)
 [3264, 3276) 'prefix_phonemes2' (line 402)
HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork
 (longjmp and C++ exceptions *are* supported)
SUMMARY: AddressSanitizer: stack-buffer-overflow (/src/espeak-ng/src/espeak-ng+0x497969) in __asan_memcpy
Shadow bytes around the buggy address:
 0x10001cf06c40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 0x10001cf06c50: 00 00 00 00 00 f2 f2 f2 f2 f2 f2 f2 f2 f2 00 00
 0x10001cf06c60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 0x10001cf06c70: 00 00 00 00 00 00 00 f2 f2 f2 f2 f2 f2 f2 f2 f2
 0x10001cf06c80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x10001cf06c90: 00 00 00 00[f2]f2 f2 f2 f2 f2 f2 f2 00 00 00 00
 0x10001cf06ca0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 0x10001cf06cb0: f2 f2 f2 f2 f2 f2 f2 f2 00 00 00 00 00 00 00 00
 0x10001cf06cc0: 01 f2 f2 f2 f2 f2 04 f2 04 f2 04 f2 00 00 00 00
 0x10001cf06cd0: 00 00 00 00 00 00 00 00 f2 f2 f2 f2 f8 f2 f8 f8
 0x10001cf06ce0: f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8
Shadow byte legend (one shadow byte represents 8 application bytes):
 Addressable: 00
 Partially addressable: 01 02 03 04 05 06 07
 Heap left redzone: fa
 Freed heap region: fd
 Stack left redzone: f1
 Stack mid redzone: f2
 Stack right redzone: f3
 Stack after return: f5
 Stack use after scope: f8
 Global redzone: f9
 Global init order: f6

 Poisoned by user: f7
 Container overflow: fc
 Array cookie: ac
 Intra object redzone: bb
 ASan internal: fe
 Left alloca redzone: ca
 Right alloca redzone: cb
 Shadow gap: cc
==4070654==ABORTING
--- end body ---
