From 11f47e3fff7ad51a8f8076e84abb216dfe17ef19 Mon Sep 17 00:00:00 2001 From: "Safey A.Halim" Date: Thu, 12 May 2011 07:32:10 +0000 Subject: [PATCH] Monkey supports bad memory access using Valgrind --- src/monkey/Makefile.am | 6 +- src/monkey/action_api.c | 96 +++++++++++++++++++++-------- src/monkey/bug_bad_memory_access | Bin 0 -> 9226 bytes src/monkey/bug_bad_memory_access.c | 16 +++++ src/monkey/gnunet-monkey.c | 12 +++- src/monkey/gnunet_monkey_action.h | 6 +- 6 files changed, 106 insertions(+), 30 deletions(-) create mode 100755 src/monkey/bug_bad_memory_access create mode 100644 src/monkey/bug_bad_memory_access.c diff --git a/src/monkey/Makefile.am b/src/monkey/Makefile.am index 44042dfdd..effa37bd4 100644 --- a/src/monkey/Makefile.am +++ b/src/monkey/Makefile.am @@ -40,7 +40,8 @@ bin_PROGRAMS = \ gnunet-service-monkey noinst_PROGRAMS = \ - bug_null_pointer_exception + bug_null_pointer_exception \ + bug_bad_memory_access gnunet_monkey_SOURCES = \ gdbmi.h \ @@ -80,6 +81,9 @@ gnunet_service_monkey_LDADD = \ bug_null_pointer_exception: gcc -g -O0 -o bug_null_pointer_exception bug_null_pointer_exception.c +bug_bad_memory_access: + gcc -g -O0 -o bug_bad_memory_access bug_bad_memory_access.c + check_PROGRAMS = \ test_monkey_edb #test_gnunet_monkey diff --git a/src/monkey/action_api.c b/src/monkey/action_api.c index 0412c7630..99809f82f 100644 --- a/src/monkey/action_api.c +++ b/src/monkey/action_api.c @@ -122,12 +122,6 @@ int GNUNET_MONKEY_ACTION_report_email(struct GNUNET_MONKEY_ACTION_Context* cntxt } - -int GNUNET_MONKEY_ACTION_rerun_with_valgrind() -{ - return GNUNET_OK; -} - static int iterateExpressions(void *cls, int numColumns, char **colValues, char **colNames) { struct Expression *expression; @@ -159,10 +153,10 @@ static int scopeEndCallback(void *cls, int numColumns, char **colValues, char ** static int analyzeSegmentationFault(struct GNUNET_MONKEY_ACTION_Context *cntxt) { - struct Expression *faultyExpression; + struct Expression *faultyExpression = NULL; struct Expression *tmp; int expressionLength = 0; - mi_wp *watchPoint; + //mi_wp *watchPoint; tmp = expressionListHead; while (NULL != tmp) { @@ -174,23 +168,40 @@ static int analyzeSegmentationFault(struct GNUNET_MONKEY_ACTION_Context *cntxt) tmp = tmp->next; } - /* Set watch points on the faulty-expression's subexpressions */ - tmp = expressionListHead; - while (NULL != tmp) { - if (tmp != faultyExpression) { - /* Only subexpressions are interesting */ - watchPoint = gmi_break_watch(cntxt->gdb_handle, wm_write, tmp->expressionSyntax); - if (!watchPoint) - { - printf("Error in setting watchpoint\n"); - return 1; - } - printf("Watchpoint %d for expression: %s\n", watchPoint->number, watchPoint->exp); - mi_free_wp(watchPoint); + if (NULL != faultyExpression) { + tmp = expressionListHead; + while (NULL != tmp) { + const char* eval; + if (tmp != faultyExpression) { + eval = gmi_data_evaluate_expression(cntxt->gdb_handle, tmp->expressionSyntax); + if (NULL != eval && strcmp(eval, "0x0") == 0) { + cntxt->gdb_null_variable = tmp->expressionSyntax; + return GNUNET_OK; + } + } + tmp = tmp->next; } - tmp = tmp->next; } - return GNUNET_OK; + /* Set watch points on the faulty-expression's subexpressions */ +// if (NULL != faultyExpression) { +// tmp = expressionListHead; +// while (NULL != tmp) { +// if (tmp != faultyExpression) { +// /* Only subexpressions are interesting */ +// watchPoint = gmi_break_watch(cntxt->gdb_handle, wm_write, tmp->expressionSyntax); +// if (!watchPoint) +// { +// printf("Error in setting watchpoint\n"); +// return 1; +// } +// printf("Watchpoint %d for expression: %s\n", watchPoint->number, watchPoint->exp); +// mi_free_wp(watchPoint); +// } +// tmp = tmp->next; +// } +// return GNUNET_OK; +// } + return GDB_STATE_ERROR; } @@ -219,13 +230,39 @@ int GNUNET_MONKEY_ACTION_inspect_expression_database(struct GNUNET_MONKEY_ACTION NULL); if (strcasecmp(cntxt->gdb_stop_reason->signal_meaning, "Segmentation fault") == 0) - analyzeSegmentationFault(cntxt); + ret = analyzeSegmentationFault(cntxt); GNUNET_MONKEY_EDB_disconnect(edbCntxt); + mi_disconnect(cntxt->gdb_handle); return ret; } +int GNUNET_MONKEY_ACTION_rerun_with_valgrind(struct GNUNET_MONKEY_ACTION_Context* cntxt) { + FILE* valgrindPipe; + int size; + const char* valgrindCommand; + cntxt->debug_mode = DEBUG_MODE_VALGRIND; + asprintf(&valgrindCommand, "valgrind --leak-check=yes %s", cntxt->binary_name); + valgrindPipe = popen(valgrindCommand, "r"); + if (NULL == valgrindPipe) { + GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Error in running Valgrind!\n"); + return GNUNET_NO; + } + + fscanf(valgrindPipe, "%d", &size); + + /* Read Valgrind stream */ + cntxt->valgrind_output = GNUNET_malloc(size); + fscanf(valgrindPipe, "%s", cntxt->valgrind_output); + if (0 != pclose(valgrindPipe)) { + GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Error while closing Valgrind pipe!\n"); + return GNUNET_NO; + } + return GNUNET_OK; +} + + int GNUNET_MONKEY_ACTION_rerun_with_gdb(struct GNUNET_MONKEY_ACTION_Context* cntxt) { cntxt->debug_mode = DEBUG_MODE_GDB; @@ -278,7 +315,7 @@ int GNUNET_MONKEY_ACTION_rerun_with_gdb(struct GNUNET_MONKEY_ACTION_Context* cnt } /* Here we should be stopped when the program crashes */ ret = wait_for_stop(cntxt->gdb_handle, cntxt); - if (ret != GDB_STATE_ERROR) + if (ret == GDB_STATE_ERROR) mi_disconnect(cntxt->gdb_handle); return ret; @@ -290,10 +327,15 @@ int GNUNET_MONKEY_ACTION_format_report(struct GNUNET_MONKEY_ACTION_Context* cntx switch (cntxt->debug_mode) { case DEBUG_MODE_GDB: GNUNET_asprintf(&(cntxt->debug_report), - "Bug detected in file:%s\nfunction:%s\nline:%d\nreason:%s\nreceived signal:%s\n%s\n", - cntxt->gdb_frames->file, cntxt->gdb_frames->func, cntxt->gdb_frames->line, mi_reason_enum_to_str(cntxt->gdb_stop_reason->reason), cntxt->gdb_stop_reason->signal_name, cntxt->gdb_stop_reason->signal_meaning); + "Bug detected in file:%s\nfunction:%s\nline:%d\nreason:%s\nreceived signal:%s\n%s\n Details:\n Expression:%s is NULL\n", + cntxt->gdb_frames->file, cntxt->gdb_frames->func, cntxt->gdb_frames->line, mi_reason_enum_to_str(cntxt->gdb_stop_reason->reason), + cntxt->gdb_stop_reason->signal_name, cntxt->gdb_stop_reason->signal_meaning, cntxt->gdb_null_variable); break; case DEBUG_MODE_VALGRIND: + GNUNET_asprintf(&(cntxt->debug_report), + "Bug detected in file:%s\nfunction:%s\nline:%d\nreason:%s\nreceived signal:%s\n%s\n Details:\n Memory Check from Valgrind:%s\n", + cntxt->gdb_frames->file, cntxt->gdb_frames->func, cntxt->gdb_frames->line, mi_reason_enum_to_str(cntxt->gdb_stop_reason->reason), + cntxt->gdb_stop_reason->signal_name, cntxt->gdb_stop_reason->signal_meaning, cntxt->valgrind_output); break; default: break; diff --git a/src/monkey/bug_bad_memory_access b/src/monkey/bug_bad_memory_access new file mode 100755 index 0000000000000000000000000000000000000000..ddd87c243eb229f0f8671e3c8547b1a33d4b439a GIT binary patch literal 9226 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 +#include + + +void badMemoryAccess() +{ + int *p = (int*) 0x4252352; + printf("Bad memory access now!\n"); + *p = 5; +} + +int main(int argc, char *argv[]) +{ + badMemoryAccess(); + return 0; +} diff --git a/src/monkey/gnunet-monkey.c b/src/monkey/gnunet-monkey.c index 7821936bf..030eb0774 100644 --- a/src/monkey/gnunet-monkey.c +++ b/src/monkey/gnunet-monkey.c @@ -77,6 +77,7 @@ run (void *cls, result = GNUNET_MONKEY_ACTION_rerun_with_gdb(cntxt); switch (result) { + int retVal; case GDB_STATE_ERROR: break; case GDB_STATE_EXIT_NORMALLY: @@ -85,10 +86,19 @@ run (void *cls, break; case GDB_STATE_STOPPED: /*FIXME: Expression Database should be inspected here (before writing the report) */ - if (GNUNET_OK != GNUNET_MONKEY_ACTION_inspect_expression_database(cntxt)) { + retVal = GNUNET_MONKEY_ACTION_inspect_expression_database(cntxt); + if (GNUNET_NO == retVal) { GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Error using Expression Database!\n"); ret = 1; break; + } else if (GDB_STATE_ERROR == retVal) { + /* GDB could not locate a NULL value expression, launch Valgrind */ + retVal = GNUNET_MONKEY_ACTION_rerun_with_valgrind(cntxt); + if (GNUNET_NO == retVal) { + GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Error using Valgrind!\n"); + ret = 1; + break; + } } if(GNUNET_OK != GNUNET_MONKEY_ACTION_format_report(cntxt)){ GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Error in generating debug report!\n"); diff --git a/src/monkey/gnunet_monkey_action.h b/src/monkey/gnunet_monkey_action.h index dd96a03a5..d8af8d712 100644 --- a/src/monkey/gnunet_monkey_action.h +++ b/src/monkey/gnunet_monkey_action.h @@ -63,14 +63,18 @@ struct GNUNET_MONKEY_ACTION_Context const char* gdb_in_use; mi_stop* gdb_stop_reason; mi_frames* gdb_frames; + const char* gdb_null_variable; + + /* Valgrind memcheck attributes */ + char* valgrind_output; }; int GNUNET_MONKEY_ACTION_report_file(struct GNUNET_MONKEY_ACTION_Context* cntxt, const char* dumpFileName); int GNUNET_MONKEY_ACTION_report_email(struct GNUNET_MONKEY_ACTION_Context* cntxt); -int GNUNET_MONKEY_ACTION_rerun_with_valgrind(void); int GNUNET_MONKEY_ACTION_inspect_expression_database(struct GNUNET_MONKEY_ACTION_Context* cntxt); int GNUNET_MONKEY_ACTION_rerun_with_gdb(struct GNUNET_MONKEY_ACTION_Context* cntxt); +int GNUNET_MONKEY_ACTION_rerun_with_valgrind(struct GNUNET_MONKEY_ACTION_Context* cntxt); int GNUNET_MONKEY_ACTION_format_report(struct GNUNET_MONKEY_ACTION_Context* cntxt); int GNUNET_MONKEY_ACTION_check_bug_redundancy(void); -- 2.25.1