Your message dated Sat, 10 Feb 2024 13:11:20 +0000
with message-id <e1ryn8a-002ya7...@coccia.debian.org>
and subject line Released with 12.5
has caused the Debian Bug report #1059656,
regarding bookworm-pu: package espeak-ng/1.51+dfsg-10+deb12u1
to be marked as done.

This means that you claim that the problem has been dealt with.
If this is not the case it is now your responsibility to reopen the
Bug report if necessary, and/or fix the problem forthwith.

(NB: If you are a system administrator and have no idea what this
message is talking about, this may indicate a serious mail system
misconfiguration somewhere. Please contact ow...@bugs.debian.org
immediately.)


-- 
1059656: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1059656
Debian Bug Tracking System
Contact ow...@bugs.debian.org with problems
--- Begin Message ---
Package: release.debian.org
Severity: normal
Tags: bookworm
User: release.debian....@packages.debian.org
Usertags: pu
X-Debbugs-Cc: espeak...@packages.debian.org
Control: affects -1 + src:espeak-ng

[ Reason ]
This upload provides fixes for CVEs. They are not a regression over
oldstable.

[ Impact ]
Blind users using the espeak-ng speech synthesis might be at risk when
e.g. reading a webpage that contains the CVE triggers.

[ Tests ]
CVE tests are getting added in the patch.

[ Risks ]
The code is relatively simple, comes from upstream, and has been in
testing since December 24th.

[ Checklist ]
  [X] *all* changes are documented in the d/changelog
  [X] I reviewed all changes and I approve them
  [X] attach debdiff against the package in (old)stable
  [X] the issue is verified as fixed in unstable

[ Change s]in *all* the changes)

The changes fix various use-after-free, unitialized buffers (which lead
to missing \0 terminators), and missing buffer bound checks.
diff -Nru espeak-ng-1.51+dfsg/debian/changelog 
espeak-ng-1.51+dfsg/debian/changelog
--- espeak-ng-1.51+dfsg/debian/changelog        2023-01-26 01:09:47.000000000 
+0100
+++ espeak-ng-1.51+dfsg/debian/changelog        2023-12-21 01:26:02.000000000 
+0100
@@ -1,3 +1,10 @@
+espeak-ng (1.51+dfsg-10+deb12u1) bookworm; urgency=medium
+
+  * patches/CVE: Fix CVE-2023-49990, CVE-2023-49991, CVE-2023-49992,
+    CVE-2023-49993, CVE-2023-49994 (Closes: Bug#1059060)
+
+ -- Samuel Thibault <sthiba...@debian.org>  Thu, 21 Dec 2023 01:26:02 +0100
+
 espeak-ng (1.51+dfsg-10) unstable; urgency=medium
 
   * watch: Use API instead of releases page.
diff -Nru espeak-ng-1.51+dfsg/debian/patches/CVE 
espeak-ng-1.51+dfsg/debian/patches/CVE
--- espeak-ng-1.51+dfsg/debian/patches/CVE      1970-01-01 01:00:00.000000000 
+0100
+++ espeak-ng-1.51+dfsg/debian/patches/CVE      2023-12-21 01:26:02.000000000 
+0100
@@ -0,0 +1,326 @@
+commit 58f1e0b6a4e6aa55621c6f01118994d01fd6f68c
+Merge: f983e445 e7bcd3cc
+Author: Alexander Epaneshnikov <aarnaa...@gmail.com>
+Date:   Sun Dec 17 15:29:30 2023 +0300
+
+    tests: fix CVE crashes (#1846)
+    
+    Fixes: #1823, #1824, #1825, #1826, #1827
+    
+    - Add crash test and vectors provided by @SEU-SSL
+    - Disallow dummy/null voice load (that causes incorrect translator
+    initialization)
+    - Fix empty `phondata` file load (that causes unitialized memory access)
+    - Limit max word length for RemoveEnding (causes buffer overflow)
+    - Limit punctlist initialization from embedded commands (buffer
+    overflow)
+    - Fix unitialized pitch in wavegen (DBZ and indexing problems)
+    - Properly zeroize stack variables before use in TranslateClause and
+    SetWordStress
+    
+    TODO (in nextup PR): add & fix more vectors from fuzzer.
+
+commit 9decedb8c229e1a4219baceaab7a3d656e889e31
+Author: Samuel Thibault <samuel.thiba...@ens-lyon.org>
+Date:   Thu Jun 30 00:50:18 2022 +0200
+
+    Fix missing checks for EOF
+
+commit c4c05820c4a47369d5a81e4a506fe7abb2fa7ed6
+Author: Yury Popov <g...@phoenix.dj>
+Date:   Sat Dec 16 19:24:51 2023 +0300
+
+    tests: add CVE crash vectors
+
+commit e79405772cecf47053116aeaad10e64606292b14
+Author: Yury Popov <g...@phoenix.dj>
+Date:   Sat Dec 16 23:55:03 2023 +0300
+
+    voices: disallow dummy voice when not compiling
+
+commit 7d4ad3c2ae063cb08bfd606021bc323dfbadaba9
+Author: Yury Popov <g...@phoenix.dj>
+Date:   Sat Dec 16 21:50:07 2023 +0300
+
+    synthdata: fix empty file load
+
+commit b99f332c576eb49839613a55cfd3e0e1b5487191
+Author: Yury Popov <g...@phoenix.dj>
+Date:   Sat Dec 16 22:45:15 2023 +0300
+
+    dictionary: limit word length
+
+commit 1a7ecfc2f202438b17e742368f910e6099ce02b7
+Author: Yury Popov <g...@phoenix.dj>
+Date:   Sat Dec 16 22:50:01 2023 +0300
+
+    readclause: limit embedded punctlist length
+
+commit a5eb246debb51ba328ef399350dfcd5d87782245
+Author: Yury Popov <g...@phoenix.dj>
+Date:   Sat Dec 16 23:03:16 2023 +0300
+
+    wavegen: fix unitialized pitch
+
+commit 5f7db763e2eff1d8174d2b65a4bbe4b2a85c8a0c
+Author: Yury Popov <g...@phoenix.dj>
+Date:   Sat Dec 16 23:17:45 2023 +0300
+
+    translate: fix number_buf initialization
+
+commit e7bcd3cc1599ebb531bb62fc3007d3ce1dade167
+Author: Yury Popov <g...@phoenix.dj>
+Date:   Sat Dec 16 23:26:07 2023 +0300
+
+    dictionary: fix stack initialization
+
+---
+ src/libespeak-ng/dictionary.c          |    4 ++++
+ src/libespeak-ng/readclause.c          |   12 ++++++------
+ src/libespeak-ng/synthdata.c           |   18 ++++++++++++++----
+ src/libespeak-ng/translate.c           |    1 +
+ src/libespeak-ng/voices.c              |   20 ++++++++++++--------
+ src/libespeak-ng/wavegen.c             |    9 ++++++---
+ tests/crash.test                       |   17 +++++++++++++++++
+ tests/crash_vectors/cve-2023-49990.txt |    1 +
+ tests/crash_vectors/cve-2023-49991.txt |    1 +
+ tests/crash_vectors/cve-2023-49994.txt |    1 +
+ 10 files changed, 63 insertions(+), 21 deletions(-)
+
+--- a/src/libespeak-ng/readclause.c
++++ b/src/libespeak-ng/readclause.c
+@@ -335,7 +335,7 @@ static int AnnouncePunctuation(Translato
+ 
+               if ((*bufix == 0) || (end_clause == 0) || 
(tr->langopts.param[LOPT_ANNOUNCE_PUNCT] & 2)) {
+                       punct_count = 1;
+-                      while ((c2 == c1) && (c1 != '<')) { // don't eat extra 
'<', it can miss XML tags
++                      while (!Eof() && (c2 == c1) && (c1 != '<')) { // don't 
eat extra '<', it can miss XML tags
+                               punct_count++;
+                               c2 = GetC();
+                       }
+@@ -647,7 +647,7 @@ int ReadClause(Translator *tr, char *buf
+                       // an embedded command. If it's a voice change, end the 
clause
+                       if (c2 == 'V') {
+                               buf[ix++] = 0; // end the clause at this point
+-                              while (!iswspace(c1 = GetC()) && !Eof() && (ix 
< (n_buf-1)))
++                              while (!Eof() && !iswspace(c1 = GetC()) && (ix 
< (n_buf-1)))
+                                       buf[ix++] = c1; // add voice name to 
end of buffer, after the text
+                               buf[ix++] = 0;
+                               return CLAUSE_VOICE;
+@@ -657,7 +657,7 @@ int ReadClause(Translator *tr, char *buf
+                               strcpy(&buf[ix], "   ");
+                               ix += 3;
+ 
+-                              if ((c2 = GetC()) == '0')
++                              if (!Eof() && (c2 = GetC()) == '0')
+                                       option_punctuation = 0;
+                               else {
+                                       option_punctuation = 1;
+@@ -665,7 +665,7 @@ int ReadClause(Translator *tr, char *buf
+                                       if (c2 != '1') {
+                                               // a list of punctuation 
characters to be spoken, terminated by space
+                                               j = 0;
+-                                              while (!iswspace(c2) && !Eof()) 
{
++                                              while (!Eof() && !iswspace(c2) 
&& (j < N_PUNCTLIST-1)) {
+                                                       option_punctlist[j++] = 
c2;
+                                                       c2 = GetC();
+                                                       buf[ix++] = ' ';
+@@ -791,7 +791,7 @@ int ReadClause(Translator *tr, char *buf
+                       }
+ 
+                       if ((c1 == '.') && (c2 == '.')) {
+-                              while ((c_next = GetC()) == '.') {
++                              while (!Eof() && (c_next = GetC()) == '.') {
+                                       // 3 or more dots, replace by elipsis
+                                       c1 = 0x2026;
+                                       c2 = ' ';
+@@ -808,7 +808,7 @@ int ReadClause(Translator *tr, char *buf
+                               // Handling of sequences of ? and ! like ??!?, 
!!??!, ?!! etc
+                               // Use only first char as determinant
+                               if(punct_data & (CLAUSE_QUESTION | 
CLAUSE_EXCLAMATION)) {
+-                                      while(clause_type_from_codepoint(c2) & 
(CLAUSE_QUESTION | CLAUSE_EXCLAMATION)) {
++                                      while(!Eof() && 
clause_type_from_codepoint(c2) & (CLAUSE_QUESTION | CLAUSE_EXCLAMATION)) {
+                                               c_next = GetC();
+                                               c2 = c_next;
+                                       }
+--- /dev/null
++++ b/tests/crash.test
+@@ -0,0 +1,17 @@
++#!/bin/sh
++# include common script
++. "`dirname $0`/common"
++
++test_crash() {
++      TEST_NAME=$1
++
++      echo "testing CVE-${TEST_NAME}"
++      ESPEAK_DATA_PATH=`pwd` LD_LIBRARY_PATH=src:${LD_LIBRARY_PATH} \
++              $VALGRIND src/espeak-ng -f "$(dirname 
$0)/crash_vectors/${TEST_NAME}.txt" -w /dev/null || exit 1
++}
++
++test_crash cve-2023-49990
++test_crash cve-2023-49991
++test_crash cve-2023-49992
++test_crash cve-2023-49993
++test_crash cve-2023-49994
+--- /dev/null
++++ b/tests/crash_vectors/cve-2023-49990.txt
+@@ -0,0 +1 @@
++��V��
��V
��V������s������������s��������eeeeeeeeseee�����
+\ No newline at end of file
+--- /dev/null
++++ b/tests/crash_vectors/cve-2023-49991.txt
+@@ -0,0 +1 @@
++��V�
��V��h�����VD�Z�������������컻��־�����ִ��ֻ������ֻ���ժ�������`v
+\ No newline at end of file
+--- /dev/null
++++ b/tests/crash_vectors/cve-2023-49994.txt
+@@ -0,0 +1 @@
++"[[-#,-      -1-2.
r--�#--O)C--!�E-1�@5-!-V-1--
+\ No newline at end of file
+--- a/src/libespeak-ng/voices.c
++++ b/src/libespeak-ng/voices.c
+@@ -554,6 +554,10 @@ voice_t *LoadVoice(const char *vname, in
+       static char voice_name[40];       // voice name for 
current_voice_selected
+       static char voice_languages[100]; // list of languages and priorities 
for current_voice_selected
+ 
++      if ((vname == NULL || vname[0] == 0) && !(control & 8)) {
++              return NULL;
++      }
++
+       strncpy0(voicename, vname, sizeof(voicename));
+       if (control & 0x10) {
+               strcpy(buf, vname);
+@@ -937,14 +941,14 @@ voice_t *LoadVoice(const char *vname, in
+ 
+       if (!tone_only) {
+               if (!!(control & 8/*compiling phonemes*/)) {
+-                        /* Set by espeak_ng_CompilePhonemeDataPath when it
+-                         * calls LoadVoice("", 8) to set up a dummy(?) voice.
+-                         * As phontab may not yet exist this avoids the 
spurious
+-                         * error message and guarantees consistent results by
+-                         * not actually reading a potentially bogus phontab...
+-                         */
+-                        ix = 0;
+-                } else if ((ix = SelectPhonemeTableName(phonemes_name)) < 0) {
++                      /* Set by espeak_ng_CompilePhonemeDataPath when it
++                              * calls LoadVoice("", 8) to set up a dummy(?) 
voice.
++                              * As phontab may not yet exist this avoids the 
spurious
++                              * error message and guarantees consistent 
results by
++                              * not actually reading a potentially bogus 
phontab...
++                              */
++                      ix = 0;
++              } else if ((ix = SelectPhonemeTableName(phonemes_name)) < 0) {
+                       fprintf(stderr, "Unknown phoneme table: '%s'\n", 
phonemes_name);
+                       ix = 0;
+               }
+--- a/src/libespeak-ng/synthdata.c
++++ b/src/libespeak-ng/synthdata.c
+@@ -75,8 +75,15 @@ static espeak_ng_STATUS ReadPhFile(void
+       if ((f_in = fopen(buf, "rb")) == NULL)
+               return create_file_error_context(context, errno, buf);
+ 
+-      if (*ptr != NULL)
++      if (*ptr != NULL) {
+               free(*ptr);
++              *ptr = NULL;
++      }
++
++      if (length == 0) {
++              *ptr = NULL;
++              return 0;
++      }
+ 
+       if ((*ptr = malloc(length)) == NULL) {
+               fclose(f_in);
+@@ -86,6 +93,7 @@ static espeak_ng_STATUS ReadPhFile(void
+               int error = errno;
+               fclose(f_in);
+               free(*ptr);
++              *ptr = NULL;
+               return create_file_error_context(context, error, buf);
+       }
+ 
+@@ -119,9 +127,11 @@ espeak_ng_STATUS LoadPhData(int *srate,
+       // read the version number and sample rate from the first 8 bytes of 
phondata
+       version = 0; // bytes 0-3, version number
+       rate = 0;    // bytes 4-7, sample rate
+-      for (ix = 0; ix < 4; ix++) {
+-              version += (wavefile_data[ix] << (ix*8));
+-              rate += (wavefile_data[ix+4] << (ix*8));
++      if (wavefile_data) {
++              for (ix = 0; ix < 4; ix++) {
++                      version += (wavefile_data[ix] << (ix*8));
++                      rate += (wavefile_data[ix+4] << (ix*8));
++              }
+       }
+ 
+       if (version != version_phdata)
+--- a/src/libespeak-ng/dictionary.c
++++ b/src/libespeak-ng/dictionary.c
+@@ -1062,6 +1062,9 @@ void SetWordStress(Translator *tr, char
+ 
+       static char consonant_types[16] = { 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 
0, 0, 0, 0 };
+ 
++      memset(syllable_weight, 0, sizeof(syllable_weight));
++      memset(vowel_length, 0, sizeof(vowel_length));
++
+       stressflags = tr->langopts.stress_flags;
+ 
+       if (dictionary_flags != NULL)
+@@ -3070,6 +3073,7 @@ int RemoveEnding(Translator *tr, char *w
+                       *word_end = 'e';
+       }
+       i = word_end - word;
++      if (i >= N_WORD_BYTES) i = N_WORD_BYTES-1;
+ 
+       if (word_copy != NULL) {
+               memcpy(word_copy, word, i);
+--- a/src/libespeak-ng/wavegen.c
++++ b/src/libespeak-ng/wavegen.c
+@@ -537,14 +537,14 @@ static void AdvanceParameters()
+       if (wvoice == NULL)
+               return;
+ 
+-      int x;
++      int x = 0;
+       int ix;
+       static int Flutter_ix = 0;
+ 
+       // advance the pitch
+       wdata.pitch_ix += wdata.pitch_inc;
+       if ((ix = wdata.pitch_ix>>8) > 127) ix = 127;
+-      x = wdata.pitch_env[ix] * wdata.pitch_range;
++      if (wdata.pitch_env) x = wdata.pitch_env[ix] * wdata.pitch_range;
+       wdata.pitch = (x>>8) + wdata.pitch_base;
+       
+       
+@@ -560,7 +560,7 @@ static void AdvanceParameters()
+       
+       if(const_f0)
+               wdata.pitch = (const_f0<<12);
+-      
++
+       if (wdata.pitch < 102400)
+               wdata.pitch = 102400; // min pitch, 25 Hz  (25 << 12)
+ 
+@@ -1268,6 +1268,9 @@ static int WavegenFill2()
+       static bool resume = false;
+       static int echo_complete = 0;
+ 
++      if (wdata.pitch < 102400)
++              wdata.pitch = 102400; // min pitch, 25 Hz  (25 << 12)
++
+       while (out_ptr < out_end) {
+               if (WcmdqUsed() <= 0) {
+                       if (echo_complete > 0) {
+--- a/src/libespeak-ng/translate.c
++++ b/src/libespeak-ng/translate.c
+@@ -2630,6 +2630,7 @@ void TranslateClause(Translator *tr, int
+                       if (dict_flags & FLAG_SPELLWORD) {
+                               // redo the word, speaking single letters
+                               for (pw = word; *pw != ' ';) {
++                                      memset(number_buf, 0, 
sizeof(number_buf));
+                                       memset(number_buf, ' ', 9);
+                                       nx = utf8_in(&c_temp, pw);
+                                       memcpy(&number_buf[2], pw, nx);
diff -Nru espeak-ng-1.51+dfsg/debian/patches/series 
espeak-ng-1.51+dfsg/debian/patches/series
--- espeak-ng-1.51+dfsg/debian/patches/series   2022-09-23 00:13:40.000000000 
+0200
+++ espeak-ng-1.51+dfsg/debian/patches/series   2023-12-21 01:26:02.000000000 
+0100
@@ -9,3 +9,4 @@
 lang
 long-build-path
 mb-fr
+CVE
diff -Nru espeak-ng-1.51+dfsg/debian/salsa-ci.yml 
espeak-ng-1.51+dfsg/debian/salsa-ci.yml
--- espeak-ng-1.51+dfsg/debian/salsa-ci.yml     2022-09-23 01:53:17.000000000 
+0200
+++ espeak-ng-1.51+dfsg/debian/salsa-ci.yml     2023-12-21 01:26:02.000000000 
+0100
@@ -5,6 +5,8 @@
 
 # needs building a host espeak-ng to generate the phoneme databases
 variables:
+  RELEASE: bookworm
+
   SALSA_CI_DISABLE_CROSSBUILD_ARM64: '1'
 
   SALSA_CI_REPROTEST_ENABLE_DIFFOSCOPE: 1

--- End Message ---
--- Begin Message ---
Version: 12.5

The upload requested in this bug has been released as part of 12.5.

--- End Message ---

Reply via email to