From fbc0be170f446a315009d04c6945dc2938c85205 Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Tue, 23 May 2017 01:01:08 +0300 Subject: [PATCH] Workaround 'array compared to 0', 'untrusted loop bound' false defects (Cherry-pick commit 36038e1 from 'master' branch.) * dyn_load.c [SOLARISDL && !USE_PROC_FOR_LIBRARIES] (GC_FirstDLOpenedLinkMap): Wrap access to dynStructureAddr (which value obtained from a weak symbol) into COVERT_DATAFLOW() in comparison to 0. * dyn_load.c [HAVE_DL_ITERATE_PHDR && !DL_ITERATE_PHDR_STRONG] (GC_register_main_static_data): Wrap access to dl_iterate_phdr weak symbol into COVERT_DATAFLOW() in comparison to 0. * dyn_load.c [HAVE_DL_ITERATE_PHDR] (GC_FirstDLOpenedLinkMap): Wrap access to _DYNAMIC weak symbol into COVERT_DATAFLOW() in comparison to 0. * include/private/gc_priv.h (TRUSTED_STRING): Pass the argument through COVERT_DATAFLOW. * include/private/gcconfig.h (COVERT_DATAFLOW): New macro. * os_dep.c [SEARCH_FOR_DATA_START] (GC_init_linux_data_start): Wrap access to __data_start and GC_data_start into COVERT_DATAFLOW() in comparison to 0. * tests/disclaim_bench.c: Update comment for include gc_priv.h. * tests/disclaim_bench.c (main): Pass the integer value obtained from command-line argument (and which is used as a loop boundary) through COVERT_DATAFLOW(). * tests/test_cpp.cc (main): Likewise. --- dyn_load.c | 6 +++--- include/private/gc_priv.h | 2 +- include/private/gcconfig.h | 12 ++++++++++++ os_dep.c | 4 ++-- tests/disclaim_bench.c | 4 ++-- tests/test_cpp.cc | 6 +----- 6 files changed, 21 insertions(+), 13 deletions(-) diff --git a/dyn_load.c b/dyn_load.c index 124f6848..8813e03b 100644 --- a/dyn_load.c +++ b/dyn_load.c @@ -185,7 +185,7 @@ GC_FirstDLOpenedLinkMap(void) dynStructureAddr = &_DYNAMIC; # endif - if (dynStructureAddr == 0) { + if (0 == COVERT_DATAFLOW(dynStructureAddr)) { /* _DYNAMIC symbol not resolved. */ return(0); } @@ -564,7 +564,7 @@ GC_INNER GC_bool GC_register_main_static_data(void) /* zero (otherwise a compiler might issue a warning). */ return FALSE; # else - return (dl_iterate_phdr == 0); /* implicit conversion to function ptr */ + return 0 == COVERT_DATAFLOW(dl_iterate_phdr); # endif } @@ -694,7 +694,7 @@ GC_FirstDLOpenedLinkMap(void) { static struct link_map *cachedResult = 0; - if (0 == (ptr_t)_DYNAMIC) { + if (0 == COVERT_DATAFLOW(_DYNAMIC)) { /* _DYNAMIC symbol not resolved. */ return(0); } diff --git a/include/private/gc_priv.h b/include/private/gc_priv.h index 4afd8eca..f750a3db 100644 --- a/include/private/gc_priv.h +++ b/include/private/gc_priv.h @@ -601,7 +601,7 @@ GC_EXTERN GC_warn_proc GC_current_warn_proc; /* A tagging macro (for a code static analyzer) to indicate that the */ /* string obtained from an untrusted source (e.g., argv[], getenv) is */ /* safe to use in a vulnerable operation (e.g., open, exec). */ -#define TRUSTED_STRING(s) (s) +#define TRUSTED_STRING(s) (char*)COVERT_DATAFLOW(s) /* Get environment entry */ #ifdef GC_READ_ENV_FILE diff --git a/include/private/gcconfig.h b/include/private/gcconfig.h index 12f0e011..77bc00af 100644 --- a/include/private/gcconfig.h +++ b/include/private/gcconfig.h @@ -32,6 +32,18 @@ # include /* For size_t etc. */ # endif +#ifdef LINT2 + /* A macro (based on a tricky expression) to prevent false warnings */ + /* like "Array compared to 0", "Comparison of identical expressions", */ + /* "Untrusted loop bound" output by some static code analysis tools. */ + /* The argument should not be a literal value. The result is */ + /* converted to word type. (Actually, GC_word is used instead of */ + /* word type as the latter might be undefined at the place of use.) */ +# define COVERT_DATAFLOW(w) (~(GC_word)(w)^(~(GC_word)0)) +#else +# define COVERT_DATAFLOW(w) ((GC_word)(w)) +#endif + /* Machine dependent parameters. Some tuning parameters can be found */ /* near the top of gc_private.h. */ diff --git a/os_dep.c b/os_dep.c index 960826bb..84f9e8b0 100644 --- a/os_dep.c +++ b/os_dep.c @@ -439,12 +439,12 @@ GC_INNER char * GC_get_maps(void) # endif } else # endif - /* else */ if ((ptr_t)__data_start != 0) { + /* else */ if (COVERT_DATAFLOW(__data_start) != 0) { GC_data_start = (ptr_t)(__data_start); } else { GC_data_start = (ptr_t)(data_start); } - if (GC_data_start != NULL) { + if (COVERT_DATAFLOW(GC_data_start) != 0) { if ((word)GC_data_start > (word)data_end) ABORT_ARG2("Wrong __data_start/_end pair", ": %p .. %p", (void *)GC_data_start, (void *)data_end); diff --git a/tests/disclaim_bench.c b/tests/disclaim_bench.c index 7ae1f3e5..cf952324 100644 --- a/tests/disclaim_bench.c +++ b/tests/disclaim_bench.c @@ -24,7 +24,7 @@ /* Include gc_priv.h is done after including GC public headers, so */ /* that GC_BUILD has no effect on the public prototypes. */ -#include "private/gc_priv.h" /* for CLOCK_TYPE and GC_random */ +#include "private/gc_priv.h" /* for CLOCK_TYPE, COVERT_DATAFLOW, GC_random */ #ifdef LINT2 # undef rand @@ -112,7 +112,7 @@ int main(int argc, char **argv) return 1; } if (argc == 2) { - model_min = model_max = atoi(argv[1]); + model_min = model_max = (int)COVERT_DATAFLOW(atoi(argv[1])); if (model_min < 0 || model_max > 2) exit(2); } diff --git a/tests/test_cpp.cc b/tests/test_cpp.cc index 55c7778b..4e912ede 100644 --- a/tests/test_cpp.cc +++ b/tests/test_cpp.cc @@ -274,11 +274,7 @@ void* Undisguise( GC_word i ) { x = 0; # endif if (argc != 2 - || (n = atoi(argv[1])) <= 0 -# ifdef LINT2 - || n >= (int)(~0U >> 1) - 1 -# endif - ) { + || (n = (int)COVERT_DATAFLOW(atoi(argv[1]))) <= 0) { GC_printf("usage: test_cpp number-of-iterations\n" "Assuming 10 iters\n"); n = 10; -- 2.40.0