build: add option for sanitizers and valgrind (#109)
* build: add support for sanitzers over cmake
* refactor: random cleanups
* fix: use-of-uninitialized-value
* chore: add valgrind also to cmake
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 4762954..645e8e0 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -38,6 +38,49 @@
option(COSE_C_INCLUDE_SIGN "Include COSE_SIGN" ON)
option(COSE_C_INCLUDE_SIGN1 "Include COSE_SIGN1" ON)
option(COSE_C_INCLUDE_COUNTERSIGN "Include COSE_COUNTERSIGN" OFF)
+option(COSE_C_VALGRIND_MEMORY_CHECK "use Valgrind to check memory, \
+ run `ctest -D ExperimentalMemCheck` then after build to run tests with valgrind" OFF)
+
+if(COSE_C_VALGRIND_MEMORY_CHECK)
+ find_program(MEMORYCHECK_COMMAND valgrind)
+ if(NOT MEMORYCHECK_COMMAND)
+ message(FATAL_ERROR "valgrind not found.")
+ endif()
+ set(MEMORYCHECK_COMMAND_OPTIONS "--trace-children=yes --leak-check=full")
+ set(MEMORYCHECK_SUPPRESSIONS_FILE "${PROJECT_SOURCE_DIR}/valgrind_suppress.txt")
+endif()
+
+set(COSE_C_USE_SANITIZER
+ "none"
+ CACHE
+ STRING
+ " \
+ Name of the sanitizer which the user whats to use \
+ This behaviour is the same is turning on one the sanitizer flags below \
+ This option is a convenience option \
+ ")
+set_property(CACHE COSE_C_USE_SANITIZER PROPERTY STRINGS none address memory leak undefined)
+
+set(COSE_C_USE_ADDRESS_SANITIZER OFF)
+set(COSE_C_USE_MEMORY_SANITIZER OFF)
+set(COSE_C_USE_LEAK_SANITIZER OFF)
+set(COSE_C_USE_UNDEFINED_SANITIZER OFF)
+
+if(COSE_C_USE_SANITIZER STREQUAL "address")
+ set(COSE_C_USE_ADDRESS_SANITIZER ON)
+endif()
+
+if(COSE_C_USE_SANITIZER STREQUAL "memory")
+ set(COSE_C_USE_MEMORY_SANITIZER ON)
+endif()
+
+if(COSE_C_USE_SANITIZER STREQUAL "leak")
+ set(COSE_C_USE_LEAK_SANITIZER ON)
+endif()
+
+if(COSE_C_USE_SANITIZER STREQUAL "undefined")
+ set(COSE_C_USE_UNDEFINED_SANITIZER ON)
+endif()
# Set the output of the libraries and executables.
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
@@ -127,7 +170,7 @@
endif()
###############################################################################
-# DEPENDENCIES
+# STATIC ANALYSIS
###############################################################################
if(COSE_C_RUN_CLANG_TIDY)
@@ -140,6 +183,8 @@
endif()
endif(COSE_C_RUN_CLANG_TIDY)
+include(sanitizers)
+
###############################################################################
# DEPENDENCIES
###############################################################################
@@ -271,6 +316,12 @@
message(STATUS "CMAKE_C_COMPILER:................${CMAKE_C_COMPILER}")
message(STATUS "CMAKE_CXX_COMPILER:..............${CMAKE_CXX_COMPILER}")
message(STATUS "CLANG_TIDY_EXE:..................${CLANG_TIDY_EXE}")
+message(STATUS "COSE_C_USE_SANITIZER:............${COSE_C_USE_SANITIZER}")
+message(STATUS "COSE_C_USE_ADDRESS_SANITIZER:....${COSE_C_USE_ADDRESS_SANITIZER}")
+message(STATUS "COSE_C_USE_MEMORY_SANITIZER:.....${COSE_C_USE_MEMORY_SANITIZER}")
+message(STATUS "COSE_C_USE_LEAK_SANITIZER:.......${COSE_C_USE_LEAK_SANITIZER}")
+message(STATUS "COSE_C_USE_UNDEFINED_SANITIZER:..${COSE_C_USE_UNDEFINED_SANITIZER}")
+message(STATUS "COSE_C_VALGRIND_MEMORY_CHECK:....${COSE_C_VALGRIND_MEMORY_CHECK}")
message(STATUS "project_cn_cbor_SOURCE_DIR:......${project_cn_cbor_SOURCE_DIR}")
message(STATUS "project_cn_cbor_BINARY_DIR:......${project_cn_cbor_BINARY_DIR}")
message(STATUS "project_mbedtls_SOURCE_DIR:......${project_mbedtls_SOURCE_DIR}")
diff --git a/cmake/sanitizers.cmake b/cmake/sanitizers.cmake
new file mode 100644
index 0000000..89269fc
--- /dev/null
+++ b/cmake/sanitizers.cmake
@@ -0,0 +1,38 @@
+if(COSE_C_USE_ADDRESS_SANITIZER)
+ set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -fno-omit-frame-pointer -fsanitize=address -g")
+ set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fno-omit-frame-pointer -fsanitize=address -g")
+ set(CMAKE_LINKER_FLAGS_DEBUG "${CMAKE_LINKER_FLAGS_DEBUG} -fno-omit-frame-pointer -fsanitize=address ")
+ set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address")
+ set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -fsanitize=address")
+endif(COSE_C_USE_ADDRESS_SANITIZER)
+
+if(COSE_C_USE_LEAK_SANITIZER)
+ set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -fno-omit-frame-pointer -fsanitize=leak -g")
+ set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fno-omit-frame-pointer -fsanitize=leak -g")
+ set(CMAKE_LINKER_FLAGS_DEBUG "${CMAKE_LINKER_FLAGS_DEBUG} -fno-omit-frame-pointer -fsanitize=leak")
+ set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=leak ")
+ set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -fsanitize=leak ")
+endif(COSE_C_USE_LEAK_SANITIZER)
+
+if(COSE_C_USE_MEMORY_SANITIZER)
+ # NOTE: memory sanitizer can only run on x86_64 linux https://github.com/google/sanitizers/wiki/MemorySanitizer
+ # and only works with clang, no gcc support
+
+ if(NOT CMAKE_C_COMPILER_ID MATCHES "Clang")
+ message(FATAL_ERROR "COSE_C_USE_MEMORY_SANITIZER is ON, but this option is only supported with clang compiler")
+ endif()
+
+ set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -fno-omit-frame-pointer -fsanitize=memory -g")
+ set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fno-omit-frame-pointer -fsanitize=memory -g")
+ set(CMAKE_LINKER_FLAGS_DEBUG "${CMAKE_LINKER_FLAGS_DEBUG} -fno-omit-frame-pointer -fsanitize=memory ")
+ set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=memory")
+ set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -fsanitize=memory")
+endif(COSE_C_USE_MEMORY_SANITIZER)
+
+if(COSE_C_USE_UNDEFINED_SANITIZER)
+ set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -fno-omit-frame-pointer -fsanitize=undefined -g")
+ set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fno-omit-frame-pointer -fsanitize=undefined -g")
+ set(CMAKE_LINKER_FLAGS_DEBUG "${CMAKE_LINKER_FLAGS_DEBUG} -fno-omit-frame-pointer -fsanitize=undefined")
+ set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=undefined")
+ set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -fsanitize=undefined ")
+endif(COSE_C_USE_UNDEFINED_SANITIZER)
diff --git a/dumper/dumper.c b/dumper/dumper.c
index fea6500..aa17ad8 100644
--- a/dumper/dumper.c
+++ b/dumper/dumper.c
@@ -235,9 +235,7 @@
void Indent(FILE* fp, int depth)
{
- int i;
-
- for (i = 0; i < depth; i++) {
+ for (int i = 0; i < depth; i++) {
WrapPrintF(fp, " ");
}
}
@@ -250,10 +248,9 @@
void DumpBytes(FILE* fp, const cn_cbor* cbor)
{
- int i;
- int fText = true;
+ bool fText = true;
- for (i = 0; i < cbor->length; i++) {
+ for (int i = 0; i < cbor->length; i++) {
if ((cbor->v.bytes[i] < 32) || (cbor->v.bytes[i] > 126) ||
(cbor->v.bytes[i] == '\'')) {
fText = false;
@@ -262,13 +259,13 @@
if (fText && (cbor->length > 0)) {
WrapPrintF(fp, "'");
- for (i = 0; i < cbor->length; i++) {
+ for (int i = 0; i < cbor->length; i++) {
WrapPrintF(fp, "%c", cbor->v.bytes[i]);
}
WrapPrintF(fp, "'");
} else {
WrapPrintF(fp, "h'");
- for (i = 0; i < cbor->length; i++) {
+ for (int i = 0; i < cbor->length; i++) {
WrapPrintF(fp, "%02x", cbor->v.bytes[i]);
}
WrapPrintF(fp, "'");
@@ -511,7 +508,6 @@
int main(int argc, char** argv)
{
- int i;
FILE* in = NULL;
FILE* out = NULL;
byte* pb = NULL;
@@ -521,7 +517,7 @@
int forXML = false;
FOO* root = NULL;
- for (i = 1; i < argc; i++) {
+ for (int i = 1; i < argc; i++) {
if ((argv[i][0] == '-') || (argv[i][0] == '/')) {
if (strcmp(&argv[i][1], "someoption") == 0) {
} else if (strcmp(&argv[i][1], "xml=yes") == 0) {
diff --git a/src/openssl.c b/src/openssl.c
index a050b6a..a377f9c 100644
--- a/src/openssl.c
+++ b/src/openssl.c
@@ -1012,9 +1012,8 @@
HMAC_CTX *ctx = NULL;
const EVP_MD *pmd = NULL;
byte *rgbOut = NULL;
- unsigned int cbOut;
+ unsigned int cbOut = 0 ;
bool f = false;
- unsigned int i;
#ifdef USE_CBOR_CONTEXT
cn_cbor_context *context = &pcose->m_message.m_allocContext;
#endif
@@ -1052,7 +1051,7 @@
if (cn->length > (int)cbOut) {
return false;
}
- for (i = 0; i < (unsigned int)TSize / 8; i++) {
+ for (unsigned int i = 0; i < (unsigned int)TSize / 8; i++) {
f |= (cn->v.bytes[i] != rgbOut[i]);
}
diff --git a/test/json.c b/test/json.c
index 0eb426d..80dda58 100644
--- a/test/json.c
+++ b/test/json.c
@@ -21,12 +21,11 @@
{
char ch;
int ib2;
- cn_cbor *node = NULL;
cn_cbor *parent = NULL;
cn_cbor *root = NULL;
for (; ib < cch; ib++) {
- node = NULL;
+ cn_cbor *node = NULL;
ch = rgch[ib];
switch (ch) {
case '{':
diff --git a/test/test.c b/test/test.c
index ce712fa..bedc63e 100644
--- a/test/test.c
+++ b/test/test.c
@@ -872,7 +872,7 @@
#endif
}
-void RunMemoryTest(const char* szFileName)
+static void RunMemoryTest(const char* szFileName)
{
#ifdef USE_CBOR_CONTEXT
unsigned int iFail;
@@ -1218,11 +1218,9 @@
return true;
}
-void RunFileTest(const char* szFileName)
+static void RunFileTest(const char* szFileName)
{
- const cn_cbor* pControl = NULL;
-
- pControl = ParseJson(szFileName);
+ const cn_cbor* pControl = ParseJson(szFileName);
//
// If we are given a file name, then process the file name