From 29f5fb6aa78fea53cbe3fb28693c93abdeae3632 Mon Sep 17 00:00:00 2001
From: Steve Underwood <steveu@coppice.org>
Date: Wed, 31 Aug 2016 23:59:32 +0800
Subject: [PATCH] The band filter for G.722 could cause numerical overflow in
 unusual circumstances with the maximum possiblke signal level. The filter
 output is now saturated to 16 bits to avoid this.

---
 libs/spandsp/spandsp/fax-tests.xml | 26 +++++++-------------------
 libs/spandsp/src/g722.c            |  4 ++--
 2 files changed, 9 insertions(+), 21 deletions(-)

diff --git a/libs/spandsp/spandsp/fax-tests.xml b/libs/spandsp/spandsp/fax-tests.xml
index 8c03d0e22f..b6ff399699 100644
--- a/libs/spandsp/spandsp/fax-tests.xml
+++ b/libs/spandsp/spandsp/fax-tests.xml
@@ -381,7 +381,7 @@
         <step type="STATUS" value="OK"/>
     </test>
     <test name="ECM-DCN-clipped">
-        <!-- Tester calls DUT and sends one 31k byte STAIRSTEP page and one 15k byte STAIRSTEP page. -->
+        <!-- Tester calls DUT and send a WHITE page. The find DCN is missing. -->
         <step type="CALL"/>
 
         <!--<step dir="T" type="CNG"/>-->
@@ -402,23 +402,11 @@
 
         <step type="WAIT" value="75"/>
         <step dir="T" type="PREAMBLE" modem="V.27ter/4800"/>
-        <step dir="T" type="PP" value="etsi_300_242_a4_stairstep.tif" min_bits="141"/>
+        <step dir="T" type="PP" value="etsi_300_242_a4_white.tif" min_bits="141"/>
         <step dir="T" type="POSTAMBLE"/>
         <step type="WAIT" value="75"/>
         <step dir="T" type="PREAMBLE" modem="V.21"/>
-        <step dir="T" type="HDLC" tag="PPS-NULL" value="FF C8 7D 00 00 00 08"/>
-        <step dir="T" type="POSTAMBLE"/>
-
-        <step dir="R" type="HDLC" modem="V.21" tag="MCF" value="FF C8 31"/>
-        <step dir="R" type="SILENCE"/>
-
-        <step type="WAIT" value="75"/>
-        <step dir="T" type="PREAMBLE" modem="V.27ter/4800"/>
-        <step dir="T" type="PP" value="etsi_300_242_a4_stairstep.tif"/>
-        <step dir="T" type="POSTAMBLE"/>
-        <step type="WAIT" value="75"/>
-        <step dir="T" type="PREAMBLE" modem="V.21"/>
-        <step dir="T" type="HDLC" tag="PPS-EOP" value="FF C8 7D 74 00 80 08"/>
+        <step dir="T" type="HDLC" tag="PPS-EOP" value="FF C8 7D 74 00 00 08"/>
         <step dir="T" type="POSTAMBLE"/>
 
         <step dir="R" type="HDLC" modem="V.21" tag="MCF" value="FF C8 31"/>
@@ -437,7 +425,7 @@
         <step type="STATUS" value="OK"/>
     </test>
     <test name="Non-ECM-DCN-clipped">
-        <!-- Tester calls DUT and sends 2 WHITE pages. DUT should send CSI for this test procedure. -->
+        <!-- Tester calls DUT and send a WHITE page. The find DCN is missing. -->
         <step type="CALL"/>
         <step dir="T" type="SET" tag="IDENT" value="+0123456789"/>
 
@@ -461,7 +449,7 @@
         <step dir="T" type="MSG" modem="V.27ter/4800" value="etsi_300_242_a4_white.tif"/>
         <step type="WAIT" value="75"/>
         <step dir="T" type="PREAMBLE" modem="V.21"/>
-        <step dir="T" type="HDLC" tag="EOP" value="FF C8 72"/>
+        <step dir="T" type="HDLC" tag="EOP" value="FF C8 74"/>
         <step dir="T" type="POSTAMBLE"/>
 
         <step dir="R" type="HDLC" modem="V.21" tag="MCF" value="FF C8 31"/>
@@ -644,7 +632,7 @@
         <step type="STATUS" value="T0_EXPIRED"/>
     </test>
     <test name="T1-after-EOM">
-        <!-- After and EOM exchange the far end no longer responds. -->
+        <!-- After an EOM exchange the far end no longer responds. -->
         <step type="CALL" value="etsi_300_242_a4_white.tif"/>
 
         <step dir="R" type="CED"/>
@@ -686,7 +674,7 @@
         <step type="STATUS" value="T1_EXPIRED"/>
     </test>
     <test name="T1-after-EOMx">
-        <!-- After and EOM exchange the far end no longer responds. -->
+        <!-- After an EOM exchange the far end no longer responds. -->
         <step type="ANSWER" value="etsi_300_242_a4_white.tif"/>
 
         <step dir="R" type="CNG"/>
diff --git a/libs/spandsp/src/g722.c b/libs/spandsp/src/g722.c
index f3126e8aa1..f9bd7f37b2 100644
--- a/libs/spandsp/src/g722.c
+++ b/libs/spandsp/src/g722.c
@@ -426,8 +426,8 @@ SPAN_DECLARE(int) g722_decode(g722_decode_state_t *s, int16_t amp[], const uint8
                     s->ptr = 0;
                 /* We shift by 12 to allow for the QMF filters (DC gain = 4096), less 1
                    to allow for the 15 bit input to the G.722 algorithm. */
-                amp[outlen++] = (int16_t) (vec_circular_dot_prodi16(s->y, qmf_coeffs_rev, 12, s->ptr) >> 11);
-                amp[outlen++] = (int16_t) (vec_circular_dot_prodi16(s->x, qmf_coeffs_fwd, 12, s->ptr) >> 11);
+                amp[outlen++] = saturate16(vec_circular_dot_prodi16(s->y, qmf_coeffs_rev, 12, s->ptr) >> 11);
+                amp[outlen++] = saturate16(vec_circular_dot_prodi16(s->x, qmf_coeffs_fwd, 12, s->ptr) >> 11);
             }
         }
     }