From 042a1cdf09077210d49cff2dff2938ef8d62fc65 Mon Sep 17 00:00:00 2001 From: josch Date: Sun, 21 Sep 2014 00:03:20 +0200 Subject: [PATCH] Add valgrind tests and fix memleaks --- CMakeLists.txt | 5 ++- mfapi/apicalls/file_get_info.c | 3 ++ mfapi/apicalls/file_get_links.c | 3 ++ mfapi/apicalls/folder_create.c | 3 ++ mfapi/apicalls/folder_delete.c | 3 ++ mfapi/apicalls/folder_get_content.c | 2 + mfapi/apicalls/folder_get_info.c | 3 ++ mfapi/apicalls/user_get_info.c | 3 ++ mfapi/apicalls/user_session.c | 1 + mfshell/main.c | 34 ++++++++++----- mfshell/mfshell.c | 10 +++++ mfshell/mfshell.h | 2 + tests/indent.sh | 21 +++++++-- tests/iwyu.py | 14 +++++- tests/valgrind.sh | 20 +++++++++ valgrind.supp | 68 +++++++++++++++++++++++++++++ 16 files changed, 177 insertions(+), 18 deletions(-) create mode 100755 tests/valgrind.sh create mode 100644 valgrind.supp diff --git a/CMakeLists.txt b/CMakeLists.txt index 0f6a42c..856e299 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,5 +18,6 @@ target_link_libraries(mfshell curl ssl crypto jansson mfapi mfutils) enable_testing() -add_test(iwyu ../tests/iwyu.py) -add_test(indent ../tests/indent.sh) +add_test(iwyu ${CMAKE_SOURCE_DIR}/tests/iwyu.py ${CMAKE_BINARY_DIR}) +add_test(indent ${CMAKE_SOURCE_DIR}/tests/indent.sh ${CMAKE_SOURCE_DIR}) +add_test(valgrind ${CMAKE_SOURCE_DIR}/tests/valgrind.sh ${CMAKE_SOURCE_DIR} ${CMAKE_BINARY_DIR}) diff --git a/mfapi/apicalls/file_get_info.c b/mfapi/apicalls/file_get_info.c index f7acb47..e424e97 100644 --- a/mfapi/apicalls/file_get_info.c +++ b/mfapi/apicalls/file_get_info.c @@ -19,6 +19,7 @@ #include #include +#include #include #include "../../utils/http.h" @@ -58,6 +59,8 @@ int mfconn_api_file_get_info(mfconn * conn, mffile * file, char *quickkey) retval = http_get_buf(http, api_call, _decode_file_get_info, file); http_destroy(http); + free(api_call); + return retval; } diff --git a/mfapi/apicalls/file_get_links.c b/mfapi/apicalls/file_get_links.c index 5ac7e2f..a75c950 100644 --- a/mfapi/apicalls/file_get_links.c +++ b/mfapi/apicalls/file_get_links.c @@ -19,6 +19,7 @@ #include #include +#include #include #include "../../utils/http.h" @@ -58,6 +59,8 @@ int mfconn_api_file_get_links(mfconn * conn, mffile * file, char *quickkey) retval = http_get_buf(http, api_call, _decode_file_get_links, file); http_destroy(http); + free(api_call); + return retval; } diff --git a/mfapi/apicalls/folder_create.c b/mfapi/apicalls/folder_create.c index 7696f30..1b8dd5d 100644 --- a/mfapi/apicalls/folder_create.c +++ b/mfapi/apicalls/folder_create.c @@ -18,6 +18,7 @@ */ #include +#include #include #include "../../utils/http.h" @@ -63,5 +64,7 @@ int mfconn_api_folder_create(mfconn * conn, char *parent, char *name) retval = http_get_buf(http, api_call, NULL, NULL); http_destroy(http); + free(api_call); + return retval; } diff --git a/mfapi/apicalls/folder_delete.c b/mfapi/apicalls/folder_delete.c index 0826e6a..241e611 100644 --- a/mfapi/apicalls/folder_delete.c +++ b/mfapi/apicalls/folder_delete.c @@ -18,6 +18,7 @@ */ #include +#include #include #include "../../utils/http.h" @@ -47,5 +48,7 @@ int mfconn_api_folder_delete(mfconn * conn, const char *folderkey) retval = http_get_buf(http, api_call, NULL, NULL); http_destroy(http); + free(api_call); + return retval; } diff --git a/mfapi/apicalls/folder_get_content.c b/mfapi/apicalls/folder_get_content.c index f4f557b..2fb686b 100644 --- a/mfapi/apicalls/folder_get_content.c +++ b/mfapi/apicalls/folder_get_content.c @@ -75,6 +75,8 @@ mfconn_api_folder_get_content(mfconn * conn, int mode, mffolder * folder_curr) _decode_folder_get_content_files, NULL); http_destroy(http); + free(api_call); + return retval; } diff --git a/mfapi/apicalls/folder_get_info.c b/mfapi/apicalls/folder_get_info.c index 0e592bb..8f5c00a 100644 --- a/mfapi/apicalls/folder_get_info.c +++ b/mfapi/apicalls/folder_get_info.c @@ -19,6 +19,7 @@ #include #include +#include #include #include "../../utils/http.h" @@ -58,6 +59,8 @@ mfconn_api_folder_get_info(mfconn * conn, mffolder * folder, char *folderkey) retval = http_get_buf(http, api_call, _decode_folder_get_info, folder); http_destroy(http); + free(api_call); + return retval; } diff --git a/mfapi/apicalls/user_get_info.c b/mfapi/apicalls/user_get_info.c index 18ea5c4..359114e 100644 --- a/mfapi/apicalls/user_get_info.c +++ b/mfapi/apicalls/user_get_info.c @@ -19,6 +19,7 @@ #include #include +#include #include "../../utils/http.h" #include "../../utils/json.h" @@ -45,6 +46,8 @@ int mfconn_api_user_get_info(mfconn * conn) retval = http_get_buf(http, api_call, _decode_user_get_info, NULL); http_destroy(http); + free(api_call); + return retval; } diff --git a/mfapi/apicalls/user_session.c b/mfapi/apicalls/user_session.c index 6193cef..db211a7 100644 --- a/mfapi/apicalls/user_session.c +++ b/mfapi/apicalls/user_session.c @@ -69,6 +69,7 @@ mfconn_api_user_get_session_token(mfconn * conn, char *server, "&token_version=2" "&response_format=json", username, password, user_signature); + free(user_signature); http = http_create(); retval = diff --git a/mfshell/main.c b/mfshell/main.c index 5f1152a..86dc771 100644 --- a/mfshell/main.c +++ b/mfshell/main.c @@ -27,9 +27,9 @@ #include "mfshell.h" -static void mfshell_run(mfshell * mfshell); +static void mfshell_run(mfshell * shell); -static void mfshell_parse_commands(mfshell * mfshell, char *command); +static void mfshell_parse_commands(mfshell * shell, char *command); void print_help(char *cmd) { @@ -119,7 +119,7 @@ parse_argv(int argc, char **argv, char **username, int main(int argc, char **argv) { - mfshell *mfshell; + mfshell *shell; char *server = "www.mediafire.com"; char *username = NULL; char *password = NULL; @@ -129,22 +129,32 @@ int main(int argc, char **argv) parse_argv(argc, argv, &username, &password, &server, &command); - mfshell = mfshell_create(35860, - "2c6dq0gb2sr8rgsue5a347lzpjnaay46yjazjcjg", - server); + shell = mfshell_create(35860, "2c6dq0gb2sr8rgsue5a347lzpjnaay46yjazjcjg", + server); if (command == NULL) { // begin shell mode - mfshell_run(mfshell); + mfshell_run(shell); } else { // interpret command - mfshell_parse_commands(mfshell, command); + mfshell_parse_commands(shell, command); } + mfshell_destroy(shell); + + if (server != NULL && strcmp("www.mediafire.com", server) != 0) + free(server); + if (username != NULL) + free(username); + if (password != NULL) + free(password); + if (command != NULL) + free(command); + return 0; } -static void mfshell_parse_commands(mfshell * mfshell, char *command) +static void mfshell_parse_commands(mfshell * shell, char *command) { char *next; int ret; @@ -177,12 +187,12 @@ static void mfshell_parse_commands(mfshell * mfshell, char *command) fprintf(stderr, "Need more than zero arguments\n"); exit(1); } - mfshell_exec(mfshell, p.we_wordc, p.we_wordv); + mfshell_exec(shell, p.we_wordc, p.we_wordv); wordfree(&p); } } -static void mfshell_run(mfshell * mfshell) +static void mfshell_run(mfshell * shell) { char *cmd = NULL; size_t len; @@ -212,7 +222,7 @@ static void mfshell_run(mfshell * mfshell) continue; } - retval = mfshell_exec_shell_command(mfshell, cmd); + retval = mfshell_exec_shell_command(shell, cmd); free(cmd); cmd = NULL; } diff --git a/mfshell/mfshell.c b/mfshell/mfshell.c index ef11e84..59c1fae 100644 --- a/mfshell/mfshell.c +++ b/mfshell/mfshell.c @@ -142,3 +142,13 @@ int mfshell_exec_shell_command(mfshell * shell, char *command) return 0; } + +void mfshell_destroy(mfshell * shell) +{ + free(shell->app_key); + free(shell->server); + free(shell->local_working_dir); + folder_free(shell->folder_curr); + mfconn_destroy(shell->conn); + free(shell); +} diff --git a/mfshell/mfshell.h b/mfshell/mfshell.h index 0f9e084..a7f7701 100644 --- a/mfshell/mfshell.h +++ b/mfshell/mfshell.h @@ -61,4 +61,6 @@ int mfshell_exec(mfshell * mfshell, int argc, char **argv); int mfshell_exec_shell_command(mfshell * mfshell, char *command); +void mfshell_destroy(mfshell * shell); + #endif diff --git a/tests/indent.sh b/tests/indent.sh index 37d0cc5..1e9d972 100755 --- a/tests/indent.sh +++ b/tests/indent.sh @@ -1,12 +1,27 @@ #!/bin/sh +case $# in + 0) + source_dir="." + ;; + 1) + source_dir=$1 + ;; + *) + echo "usage: $0 [source_dir]" + exit 1 + ;; +esac + ret=0 -find .. -name "*.c" -o -name "*.h" | while read f; do +find "$source_dir" -name "*.c" -o -name "*.h" | while read f; do case $f in - ../*/CMakeFiles/*) + ${source_dir}/*/CMakeFiles/*) + ;; + ${source_dir}/CMakeFiles/*) ;; *) - INDENT_PROFILE=../.indent.pro indent -st $f | diff -u $f - + INDENT_PROFILE="${source_dir}/.indent.pro" indent -st "$f" | diff -u "$f" - ret=$((ret+$?)) ;; esac diff --git a/tests/iwyu.py b/tests/iwyu.py index 43cb23f..8145c8a 100755 --- a/tests/iwyu.py +++ b/tests/iwyu.py @@ -5,8 +5,20 @@ from __future__ import print_function import json import subprocess import shlex +import sys +import os -with open("compile_commands.json", "r") as f: +if len(sys.argv) == 1: + build_dir = "." +elif len(sys.argv) == 2: + build_dir = sys.argv[1] +else: + print("usage: %s [build_dir]"%sys.argv[0]) + exit(1) + +compile_commands = os.path.join(build_dir, "compile_commands.json") + +with open(compile_commands, "r") as f: tunits = json.load(f) result = 0 diff --git a/tests/valgrind.sh b/tests/valgrind.sh new file mode 100755 index 0000000..44d20c9 --- /dev/null +++ b/tests/valgrind.sh @@ -0,0 +1,20 @@ +#!/bin/sh + +case $# in + 0) + source_dir="." + binary_dir="." + ;; + 2) + source_dir=$1 + binary_dir=$2 + ;; + *) + echo "usage: $0 [source_dir] [binary_dir]" + exit 1 + ;; +esac + +cmd="valgrind --suppressions="${source_dir}/valgrind.supp" --fullpath-after="$source_dir" --tool=memcheck --leak-check=yes --show-reachable=yes --num-callers=20 --track-fds=yes --track-origins=yes" + +$cmd "${binary_dir}/mfshell" -c "help; whoami" diff --git a/valgrind.supp b/valgrind.supp new file mode 100644 index 0000000..c63204e --- /dev/null +++ b/valgrind.supp @@ -0,0 +1,68 @@ +{ + glibc #1 + Memcheck:Value8 + ... + fun:dl_main + fun:_dl_sysdep_start + fun:_dl_start + obj:*/ld-2.*.so + ... +} +{ + glibc #2 + Memcheck:Cond + ... + fun:dl_main + fun:_dl_sysdep_start + fun:_dl_start + obj:*/ld-2.*.so + ... +} +{ + glibc #3 + Memcheck:Param + sendmsg(mmsg[0].msg_hdr) + fun:sendmmsg + fun:__libc_res_nsend + fun:__libc_res_nquery + fun:__libc_res_nquerydomain + fun:__libc_res_nsearch + fun:_nss_dns_gethostbyname4_r + fun:gaih_inet + fun:getaddrinfo + ... + fun:start_thread + fun:clone +} +{ + Since we can never safely uninitialize SSL, allow this + Memcheck:Leak + ... + fun:SSL_library_init + fun:main +} +{ + gnutls #1 + Memcheck:Leak + ... + fun:gnutls_global_init + obj:* + fun:call_init.part.0 + fun:_dl_init + ... +} +{ + gnutls #2 + Memcheck:Cond + fun:gnutls_session_get_data + ... + fun:curl_multi_perform + fun:curl_easy_perform + fun:http_post_buf + fun:mfconn_api_user_get_session_token + fun:mfconn_create + fun:mfshell_cmd_auth + fun:mfshell_exec + fun:mfshell_parse_commands + fun:main +}