Repository: jgaeddert/liquid-dsp (language: python)

Issue:
clang sanitizers report errors
Building liquid with clang sanitizers namely [address](https://clang.llvm.org/docs/AddressSanitizer.html) and [undefined](https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html) reports memory [leaks](https://github.com/fsheikh/liquid-dsp/blob/clang-sanitizer-build/sanitizer-address.txt) and [undefined](https://github.com/fsheikh/liquid-dsp/blob/clang-sanitizer-build/sanitizer-undefined.txt) behavior errors when tests from resulting build are run. Building liquid with clang sanitizers [fails](https://github.com/fsheikh/liquid-dsp/blob/clang-sanitizer-build/sanitizer-make-check-error.txt) due to what looks like a configuration error. A configure [patch](https://github.com/fsheikh/liquid-dsp/blob/clang-sanitizer-build/configure.patch) was used to collect the error reports, but I would consider it out-of-scope for this issue. Good news is that most errors look quite trivial to fix, another indication of liquid's already good quality. 

This issue was produced with clang-8 on Ubuntu 18.04 with GNU/Linux 5.4.0-77-generic x86_64 


Discussion / hints:

Fix patch:
diff --git a/src/fec/src/fec_hamming3126.c b/src/fec/src/fec_hamming3126.c
index bc211aedb..b1797af6a 100644
--- a/src/fec/src/fec_hamming3126.c
+++ b/src/fec/src/fec_hamming3126.c
@@ -103,7 +103,7 @@ unsigned int fec_hamming3126_encode_symbol(unsigned int _sym_dec)
 unsigned int fec_hamming3126_decode_symbol(unsigned int _sym_enc)
 {
     // validate input
-    if (_sym_enc >= (1<<31)) {
+    if (_sym_enc >= (1u<<31)) {
         liquid_error(LIQUID_EICONFIG,"fec_hamming_decode(), input symbol too large");
         return 0;
     }
diff --git a/src/filter/src/dds.c b/src/filter/src/dds.c
index b42f198b9..23b78023d 100644
--- a/src/filter/src/dds.c
+++ b/src/filter/src/dds.c
@@ -152,6 +152,7 @@ void DDS(_destroy)(DDS() _q)
 {
     // free filter parameter arrays
     free(_q->h_len);
+    free(_q->As);
     free(_q->fc);
     free(_q->ft);
 
diff --git a/src/framing/src/bpresync.c b/src/framing/src/bpresync.c
index d0a1ad9de..5bbb6f2fd 100644
--- a/src/framing/src/bpresync.c
+++ b/src/framing/src/bpresync.c
@@ -122,8 +122,8 @@ int BPRESYNC(_destroy)(BPRESYNC() _q)
     unsigned int i;
 
     // free received symbol buffers
-    free(_q->rx_i);
-    free(_q->rx_q);
+    bsequence_destroy(_q->rx_i);
+    bsequence_destroy(_q->rx_q);
 
     // free internal syncrhonizer objects
     for (i=0; i<_q->m; i++) {
diff --git a/src/framing/src/framegen64.c b/src/framing/src/framegen64.c
index dd9b9b441..dd6fd9d7e 100644
--- a/src/framing/src/framegen64.c
+++ b/src/framing/src/framegen64.c
@@ -91,6 +91,7 @@ int framegen64_destroy(framegen64 _q)
     // destroy internal objects
     qpacketmodem_destroy(_q->enc);
     qpilotgen_destroy(_q->pilotgen);
+    firinterp_crcf_destroy(_q->interp);
 
     // free main object memory
     free(_q);
diff --git a/src/math/src/poly.lagrange.c b/src/math/src/poly.lagrange.c
index ad98eb13c..b794bf444 100644
--- a/src/math/src/poly.lagrange.c
+++ b/src/math/src/poly.lagrange.c
@@ -114,11 +114,12 @@ int POLY(_fit_lagrange_barycentric)(T *         _x,
             else        _w[j] *= (_x[j] - _x[k]);
         }
 
+        if (_w[j] == 0.0f) _w[j] += 1.0e-9f;
         _w[j] = 1. / _w[j];
     }
 
-    // normalize by _w[0]
-    T w0 = _w[0];
+    // normalize by _w[0], add minuscule margin to avoid divide-by-zero warning
+    T w0 = _w[0] + 1.0e-9f;
     for (j=0; j<_n; j++)
         _w[j] /= w0;
     return LIQUID_OK;
diff --git a/src/multichannel/src/ofdmframesync.c b/src/multichannel/src/ofdmframesync.c
index c49df3ae1..4bc36c2c2 100644
--- a/src/multichannel/src/ofdmframesync.c
+++ b/src/multichannel/src/ofdmframesync.c
@@ -442,7 +442,8 @@ int ofdmframesync_execute_seekplcp(ofdmframesync _q)
 
     // estimate gain
     unsigned int i;
-    float g = 0.0f;
+    // start with a reasonbly small number to avoid divide-by-zero warning
+    float g = 1.0e-9f;
     for (i=_q->cp_len; i<_q->M + _q->cp_len; i++) {
         // compute |rc[i]|^2 efficiently
         g += crealf(rc[i])*crealf(rc[i]) + cimagf(rc[i])*cimagf(rc[i]);
diff --git a/src/nco/src/nco.c b/src/nco/src/nco.c
index 28ff66097..c1b8fe9a0 100644
--- a/src/nco/src/nco.c
+++ b/src/nco/src/nco.c
@@ -25,6 +25,7 @@
 // loop (pll) implementation
 //
 
+#include <limits.h>
 #include <math.h>
 #include <stdlib.h>
 #include <stdio.h>
@@ -377,7 +378,8 @@ uint32_t NCO(_constrain)(float _theta)
     if (fpart < 0.) fpart += 1.;
 
     // map to range of precision needed
-    return (uint32_t)(fpart * 0xffffffff);
+    long retVal = (long)(fpart * 0xffffffff);
+    return retVal >= UINT_MAX ? UINT_MAX : retVal;
 }
 
 // compute index for sine look-up table
diff --git a/src/optim/src/gradsearch.c b/src/optim/src/gradsearch.c
index b5b031d59..3bbca6c20 100644
--- a/src/optim/src/gradsearch.c
+++ b/src/optim/src/gradsearch.c
@@ -328,7 +328,9 @@ float gradsearch_linesearch(utility_function _utility,
 float gradsearch_norm(float *      _v,
                       unsigned int _n)
 {
-    float vnorm = 0.0f;
+    // start with a small value still big enough
+    // to avoid warning in gradstep function
+    float vnorm = 1.0e-7f;
 
     unsigned int i;
     for (i=0; i<_n; i++)
diff --git a/src/sequence/src/bsequence.c b/src/sequence/src/bsequence.c
index 6356f914a..8c44e57ea 100644
--- a/src/sequence/src/bsequence.c
+++ b/src/sequence/src/bsequence.c
@@ -171,7 +171,7 @@ int bsequence_push(bsequence    _bs,
 int bsequence_circshift(bsequence _bs)
 {
     // extract most-significant (left-most) bit
-    unsigned int msb_mask = 1 << (_bs->num_bits_msb-1);
+    unsigned int msb_mask = 1u << (_bs->num_bits_msb-1);
     unsigned int b = (_bs->s[0] & msb_mask) >> (_bs->num_bits_msb-1);
 
     // push bit into sequence
diff --git a/src/utility/src/byte_utilities.c b/src/utility/src/byte_utilities.c
index 0f4d46464..b205b0447 100644
--- a/src/utility/src/byte_utilities.c
+++ b/src/utility/src/byte_utilities.c
@@ -228,7 +228,7 @@ unsigned int liquid_reverse_uint24(unsigned int _x)
 // reverse integer with 32 bits of data
 unsigned int liquid_reverse_uint32(unsigned int _x)
 {
-    return (liquid_reverse_byte_gentab[(_x      ) & 0xff] << 24) |
+    return ((unsigned int)(liquid_reverse_byte_gentab[(_x      ) & 0xff]) << 24) |
            (liquid_reverse_byte_gentab[(_x >>  8) & 0xff] << 16) |
            (liquid_reverse_byte_gentab[(_x >> 16) & 0xff] <<  8) |
            (liquid_reverse_byte_gentab[(_x >> 24) & 0xff]      );


Test patch:
diff --git a/src/equalization/tests/eqlms_cccf_autotest.c b/src/equalization/tests/eqlms_cccf_autotest.c
index ceda5e27c..9349a3ede 100644
--- a/src/equalization/tests/eqlms_cccf_autotest.c
+++ b/src/equalization/tests/eqlms_cccf_autotest.c
@@ -115,6 +115,7 @@ void autotest_eqlms_cccf_blind()
 
     // clean up objects
     firfilt_cccf_destroy(fchannel);
+    firinterp_crcf_destroy(interp);
     eqlms_cccf_destroy(eq);
     msequence_destroy(ms);
 }
@@ -206,6 +207,7 @@ void autotest_eqlms_cccf_decisiondirected()
 
     // clean up objects
     firfilt_cccf_destroy(fchannel);
+    firinterp_crcf_destroy(interp);
     eqlms_cccf_destroy(eq);
     msequence_destroy(ms);
 }