Commit 2096f83f53b32db56304b0d0fe5eaec45d4d788a

humphreyj 2018-10-06T20:02:58

Add clang build to Makefile and fix clang compiler warnings.

diff --git a/Makefile b/Makefile
index fbf6971..0518ccb 100644
--- a/Makefile
+++ b/Makefile
@@ -20,7 +20,6 @@ INSTALL_PREFIX = /usr/local
 SILENT = @
 
 CWARN += -Waggregate-return
-CWARN += -Wno-aggressive-loop-optimizations
 CWARN += -Wall
 CWARN += -Wbad-function-cast
 CWARN += -Wcast-align
@@ -37,15 +36,12 @@ CWARN += -Wframe-larger-than=5000
 CWARN += -Winit-self
 CWARN += -Winline
 CWARN += -Winvalid-pch
-CWARN += -Wjump-misses-init
 CWARN += -Wlarger-than=10000
-CWARN += -Wlogical-op
 CWARN += -Wlong-long
 CWARN += -Wmissing-declarations
 CWARN += -Wmissing-include-dirs
 CWARN += -Wmissing-prototypes
 CWARN += -Wnested-externs
-CWARN += -Wnormalized=nfkc
 CWARN += -Wold-style-definition
 CWARN += -Wpacked
 CWARN += -Wpedantic
@@ -53,23 +49,30 @@ CWARN += -pedantic-errors
 CWARN += -Wredundant-decls
 CWARN += -Wshadow
 CWARN += -Wstack-protector
-CWARN += -Wstack-usage=5000
 CWARN += -Wstrict-aliasing
 CWARN += -Wstrict-prototypes
 CWARN += -Wswitch-default
 CWARN += -Wswitch-enum
-CWARN += -Wsync-nand
-CWARN += -Wtrampolines
 CWARN += -Wundef
 CWARN += -Wuninitialized
 CWARN += -Wunknown-pragmas
-CWARN += -Wunsafe-loop-optimizations
-CWARN += -Wunsuffixed-float-constants
 CWARN += -Wunused-parameter
-CWARN += -Wvector-operation-performance
 CWARN += -Wvla
 CWARN += -Wwrite-strings
 
+CWARN.gcc += -Wno-aggressive-loop-optimizations
+CWARN.gcc += -Wjump-misses-init
+CWARN.gcc += -Wlogical-op
+CWARN.gcc += -Wnormalized=nfkc
+CWARN.gcc += -Wstack-usage=5000
+CWARN.gcc += -Wsync-nand
+CWARN.gcc += -Wtrampolines
+CWARN.gcc += -Wunsafe-loop-optimizations
+CWARN.gcc += -Wunsuffixed-float-constants
+CWARN.gcc += -Wvector-operation-performance
+
+CWARN.clang += -Wno-format-nonliteral
+
 CFLAGS += $(CWARN)
 CFLAGS += -fstack-protector-all
 CFLAGS += -fstrict-overflow
@@ -77,12 +80,14 @@ CFLAGS += -std=c89
 CFLAGS += -MD
 CFLAGS += -DSMTP_OPENSSL
 
+CFLAGS.debug   += $(CFLAGS)
 CFLAGS.debug   += -g3
 CFLAGS.debug   += -DSMTP_TEST
 CFLAGS.debug   += -Wno-missing-prototypes
 CFLAGS.debug   += -fprofile-arcs -ftest-coverage
 CFLAGS.debug   += -fsanitize=undefined
 
+CFLAGS.release += $(CFLAGS)
 CFLAGS.release += -O3
 
 CPPFLAGS += -DSMTP_OPENSSL
@@ -91,6 +96,11 @@ CPPFLAGS += -fpermissive
 
 CPPFLAGS.release = $(CPPFLAGS)
 
+CFLAGS.gcc.debug     += $(CFLAGS.debug)   $(CWARN.gcc)
+CFLAGS.gcc.release   += $(CFLAGS.release) $(CWARN.gcc)
+CFLAGS.clang.debug   += $(CFLAGS.debug)   $(CWARN.clang)
+CFLAGS.clang.release += $(CFLAGS.release) $(CWARN.clang)
+
 VFLAGS += -q
 VFLAGS += --error-exitcode=1
 VFLAGS += --gen-suppressions=yes
@@ -107,13 +117,17 @@ VALGRIND_MEMCHECK = $(SILENT) valgrind $(VFLAGS) $(VFLAGS_MEMCHECK)
 CC  = gcc
 CPP = g++
 
+CC.clang = clang
+
 AR.c.debug          = $(SILENT) $(AR) -c -r $@ $^
 AR.c.release        = $(SILENT) $(AR) -c -r $@ $^
-COMPILE.c.debug     = $(SILENT) $(CC) $(CFLAGS) $(CFLAGS.debug) -c -o $@ $<
-COMPILE.c.release   = $(SILENT) $(CC) $(CFLAGS) $(CFLAGS.release) -c -o $@ $<
+COMPILE.c.debug     = $(SILENT) $(CC) $(CFLAGS.gcc.debug) -c -o $@ $<
+COMPILE.c.release   = $(SILENT) $(CC) $(CFLAGS.gcc.release) -c -o $@ $<
+COMPILE.c.clang     = $(SILENT) $(CC.clang) $(CFLAGS.clang.debug) -c -o $@ $<
 COMPILE.cpp.release = $(SILENT) $(CPP) $(CPPFLAGS.release) -c -o $@ $<
-LINK.c.debug        = $(SILENT) $(CC) $(CFLAGS) $(CFLAGS.debug) -o $@ $^
-LINK.c.release      = $(SILENT) $(CC) $(CFLAGS) $(CFLAGS.release) -o $@ $^
+LINK.c.debug        = $(SILENT) $(CC) $(CFLAGS.gcc.debug) -o $@ $^
+LINK.c.release      = $(SILENT) $(CC) $(CFLAGS.gcc.release) -o $@ $^
+LINK.c.clang        = $(SILENT) $(CC.clang) $(CFLAGS.clang.debug) -o $@ $^
 LINK.cpp.release    = $(SILENT) $(CPP) $(CPPFLAGS.release) -o $@ $^
 INKSCAPE            = $(SILENT) inkscape
 MOGRIFY             = $(SILENT) mogrify
@@ -129,6 +143,7 @@ all: $(BDIR)/debug/libsmtp.a          \
      $(BDIR)/release/test_cpp_wrapper \
      $(BDIR)/doc/html/index.html      \
      $(BDIR)/debug/test               \
+     $(BDIR)/debug/clang_test         \
      $(BDIR)/release/test_nossl       \
      $(BDIR)/www/images/logo.png
 
@@ -153,13 +168,15 @@ install: all
 	cp src/smtp.h $(INSTALL_PREFIX)/include/smtp.h
 	cp $(BDIR)/release/libsmtp.a $(INSTALL_PREFIX)/lib/libsmtp.a
 
-test: all
+test: all       \
+      test_unit
 	$(VALGRIND_MEMCHECK) $(BDIR)/debug/test
 	$(VALGRIND_MEMCHECK) $(BDIR)/release/test_nossl
 	$(BDIR)/release/test_cpp_wrapper
 
 test_unit: all
 	$(VALGRIND_MEMCHECK) $(BDIR)/debug/test -u
+	$(VALGRIND_MEMCHECK) $(BDIR)/debug/clang_test -u
 
 -include $(shell find $(BDIR)/ -name "*.d" 2> /dev/null)
 
@@ -237,6 +254,20 @@ $(BDIR)/debug/test.o: test/test.c | $(BDIR)/debug
 $(BDIR)/debug/seams.o: test/seams.c | $(BDIR)/debug
 	$(COMPILE.c.debug)
 
+$(BDIR)/debug/clang_test: $(BDIR)/debug/clang_seams.o \
+                          $(BDIR)/debug/clang_smtp.o  \
+                          $(BDIR)/debug/clang_test.o
+	$(LINK.c.clang) -lssl -lcrypto -lgcov -lubsan
+
+$(BDIR)/debug/clang_seams.o: test/seams.c | $(BDIR)/debug
+	$(COMPILE.c.clang)
+
+$(BDIR)/debug/clang_smtp.o: src/smtp.c | $(BDIR)/debug
+	$(COMPILE.c.clang)
+
+$(BDIR)/debug/clang_test.o: test/test.c | $(BDIR)/debug
+	$(COMPILE.c.clang) -Isrc/
+
 $(BDIR)/release/test_nossl: $(BDIR)/release/smtp_nossl.o \
                             $(BDIR)/release/test_nossl.o
 	$(LINK.c.release)
diff --git a/src/smtp.c b/src/smtp.c
index 5120eb0..45becc0 100644
--- a/src/smtp.c
+++ b/src/smtp.c
@@ -668,7 +668,8 @@ smtp_base64_encode(const char *const buf,
  * with -1 during the decoding process, then that indicates an invalid base64
  * character in the encoded data.
  */
-static char g_base64_decode_table[] = {
+static signed char
+g_base64_decode_table[] = {
   -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
@@ -702,7 +703,7 @@ smtp_base64_decode_block(const unsigned char *const buf,
                          unsigned char *const decode){
   int decode_block_len;
   size_t i;
-  char decode_table[4];
+  signed char decode_table[4];
   unsigned char outb[3];
 
   decode_block_len = 0;
@@ -711,7 +712,7 @@ smtp_base64_decode_block(const unsigned char *const buf,
       decode_table[i] = 0;
       continue;
     }
-    decode_table[i] = g_base64_decode_table[(unsigned char)buf[i]];
+    decode_table[i] = g_base64_decode_table[buf[i]];
     if(decode_table[i] < 0){
       return -1;
     }
@@ -2387,6 +2388,44 @@ smtp_attachment_validate_name(const char *const name){
 #define SMTP_FLAG_INVALID_MEMORY (enum smtp_flag)(0xFFFFFFFF)
 
 /**
+ * This error structure used for the single error case where we cannot
+ * initially allocate memory. This makes it easier to propagate any
+ * error codes when calling the other header functions because the
+ * caller will always get a valid SMTP structure returned.
+ */
+static struct smtp smtp_error = {
+  SMTP_FLAG_INVALID_MEMORY, /* flags                        */
+  0,                        /* sock                         */
+  {                         /* gdfd                         */
+    NULL,                   /* _buf                         */
+    0,                      /* _bufsz                       */
+    0,                      /* _buf_len                     */
+    0,                      /* delim                        */
+    NULL,                   /* line                         */
+    0,                      /* line_len                     */
+    NULL,                   /* getdelimfd_read              */
+    NULL                    /* user_data                    */
+  },                        /* gdfd                         */
+  NULL,                     /* header_list                  */
+  0,                        /* num_headers                  */
+  NULL,                     /* address_list                 */
+  0,                        /* num_address                  */
+  NULL,                     /* attachment_list              */
+  0,                        /* num_attachment               */
+  SMTP_STATUS_NOMEM,        /* smtp_status_code status_code */
+  0,                        /* timeout_sec                  */
+  0,                        /* tls_on                       */
+  NULL                      /* cafile                       */
+#ifdef SMTP_OPENSSL
+  ,
+  NULL,                     /* tls                          */
+  NULL,                     /* tls_ctx                      */
+  NULL                      /* tls_bio                      */
+#endif /* SMTP_OPENSSL */
+};
+
+
+/**
  * Open a connection to an SMTP server and return the context.
  *
  * After successfully connecting and performing a handshake with the
@@ -2425,18 +2464,9 @@ smtp_open(const char *const server,
           struct smtp **smtp){
   struct smtp *snew;
 
-  /*
-   * This error structure used for the single error case where we cannot
-   * initially allocate memory. This makes it easier to propagate any
-   * error codes when calling the other header functions because the
-   * caller will always get a valid SMTP structure returned.
-   */
-  static struct smtp smtp_error = {0};
-
   if((snew = calloc(1, sizeof(**smtp))) == NULL){
-    smtp_error.flags = SMTP_FLAG_INVALID_MEMORY;
     *smtp = &smtp_error;
-    return smtp_status_code_set(*smtp, SMTP_STATUS_NOMEM);
+    return smtp_status_code_get(*smtp);
   }
   *smtp = snew;