From 55b2e9b2a3cf80989a4dcfe6afde122e3bb92297 Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Sun, 20 Mar 2022 21:42:04 +0100 Subject: [PATCH] MatchRule: Prevent non-eating special characters from eating characters Special characters such as N, S1, etc. are not actually eating characters. Their treatment should thus *not* update pre_ptr and post_ptr, otherwise those would underflow/overflow, e.g. in the case @) s (_NS1 [z] this would overflow. This for instance noticeable with the memory sanitizer: ESPEAK_DATA_PATH=$PWD ./src/espeak-ng -qX "capitals" Translate 'capitals' 1 c [k] 1 a [a] 1 p [p] 1 i [I] 1 t [t] 1 a [a] 1 l [l] 20 l (C [l] ==2837201==WARNING: MemorySanitizer: use-of-uninitialized-value #0 0x7f7f4422744b in utf8_in2 /home/samy/brl/speech/espeak-ng-git/src/libespeak-ng/translate.c:281:2 #1 0x7f7f442281bc in utf8_in /home/samy/brl/speech/espeak-ng-git/src/libespeak-ng/translate.c:332:9 #2 0x7f7f440e0d31 in MatchRule /home/samy/brl/speech/espeak-ng-git/src/libespeak-ng/dictionary.c:1767:21 #3 0x7f7f440d937f in TranslateRules /home/samy/brl/speech/espeak-ng-git/src/libespeak-ng/dictionary.c:2320:6 #4 0x7f7f44230e5f in TranslateWord3 /home/samy/brl/speech/espeak-ng-git/src/libespeak-ng/translate.c:733:15 #5 0x7f7f44229844 in TranslateWord /home/samy/brl/speech/espeak-ng-git/src/libespeak-ng/translate.c:1100:14 #6 0x7f7f44256e50 in TranslateWord2 /home/samy/brl/speech/espeak-ng-git/src/libespeak-ng/translate.c:1361:11 #7 0x7f7f4424d6cc in TranslateClause /home/samy/brl/speech/espeak-ng-git/src/libespeak-ng/translate.c:2623:17 #8 0x7f7f44213359 in SpeakNextClause /home/samy/brl/speech/espeak-ng-git/src/libespeak-ng/synthesize.c:1569:2 #9 0x7f7f441a9f56 in Synthesize /home/samy/brl/speech/espeak-ng-git/src/libespeak-ng/speech.c:457:2 #10 0x7f7f441a9023 in sync_espeak_Synth /home/samy/brl/speech/espeak-ng-git/src/libespeak-ng/speech.c:570:29 #11 0x7f7f441ad59f in espeak_ng_Synthesize /home/samy/brl/speech/espeak-ng-git/src/libespeak-ng/speech.c:678:10 #12 0x7f7f4410b3f4 in espeak_Synth /home/samy/brl/speech/espeak-ng-git/src/libespeak-ng/espeak_api.c:90:32 #13 0x4a8be3 in main /home/samy/brl/speech/espeak-ng-git/src/espeak-ng.c:691:3 #14 0x7f7f43a2e7fc in __libc_start_main csu/../csu/libc-start.c:332:16 #15 0x421449 in _start (/home/samy/ens/projet/1/speech/espeak-ng-git/src/.libs/espeak-ng+0x421449) Uninitialized value was created by an allocation of 'sbuf' in the stack frame of function 'TranslateClause' #0 0x7f7f4423a1f0 in TranslateClause /home/samy/brl/speech/espeak-ng-git/src/libespeak-ng/translate.c:1941 While trying to match _NS1, MatchRule is overflowing the buffer. It happens that this had not usually posed problem because rules usually have these non-eating special characters last in the rule and thus it wasn't mattering that post_ptr is pointing outside valid text. --- src/libespeak-ng/dictionary.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/libespeak-ng/dictionary.c b/src/libespeak-ng/dictionary.c index d7cf1396..746c2ecb 100644 --- a/src/libespeak-ng/dictionary.c +++ b/src/libespeak-ng/dictionary.c @@ -1816,6 +1816,7 @@ static void MatchRule(Translator *tr, char *word[], char *word_start, int group_ failed = 1; break; case RULE_DOLLAR: + post_ptr--; command = *rule++; if (command == DOLLAR_UNPR) match.end_type = SUFX_UNPRON; // $unpron @@ -1912,9 +1913,11 @@ static void MatchRule(Translator *tr, char *word[], char *word_start, int group_ } break; case RULE_INC_SCORE: + post_ptr--; add_points = 20; // force an increase in points break; case RULE_DEC_SCORE: + post_ptr--; add_points = -20; // force an decrease in points break; case RULE_DEL_FWD: @@ -1943,8 +1946,10 @@ static void MatchRule(Translator *tr, char *word[], char *word_start, int group_ case RULE_NO_SUFFIX: if (word_flags & FLAG_SUFFIX_REMOVED) failed = 1; // a suffix has been removed - else + else { + post_ptr--; add_points = 1; + } break; default: if (letter == rb) { @@ -2024,6 +2029,7 @@ static void MatchRule(Translator *tr, char *word[], char *word_start, int group_ failed = 1; break; case RULE_DOLLAR: + pre_ptr++; command = *rule++; if ((command == DOLLAR_LIST) || ((command & 0xf0) == 0x20)) { // $list or $p_alt @@ -2055,6 +2061,7 @@ static void MatchRule(Translator *tr, char *word[], char *word_start, int group_ failed = 1; break; case RULE_STRESSED: + pre_ptr++; if (tr->word_stressed_count > 0) add_points = 19; else @@ -2075,12 +2082,14 @@ static void MatchRule(Translator *tr, char *word[], char *word_start, int group_ } break; case RULE_IFVERB: + pre_ptr++; if (tr->expect_verb) add_points = 1; else failed = 1; break; case RULE_CAPITAL: + pre_ptr++; if (word_flags & FLAG_FIRST_UPPER) add_points = 1; else