diff options
author | David Malcolm <dmalcolm@redhat.com> | 2020-01-21 12:42:36 -0500 |
---|---|---|
committer | David Malcolm <dmalcolm@redhat.com> | 2020-01-21 18:58:31 -0500 |
commit | 4f01e5778689977c9569477947b8062d8d866667 (patch) | |
tree | ab213e6c9fc028c38992299801ee2921bae87cc1 /gcc | |
parent | c77074d05691053ee7347d9e44ab89b3adb23fb1 (diff) | |
download | gcc-4f01e5778689977c9569477947b8062d8d866667.zip gcc-4f01e5778689977c9569477947b8062d8d866667.tar.gz gcc-4f01e5778689977c9569477947b8062d8d866667.tar.bz2 |
analyzer: fix qsort issue with array_region keys (PR 93352)
PR analyzer/93352 reports a qsort failure
"comparator not anti-symmetric: -2147483648, -2147483648)"
within the analyzer on code involving an array access of [0x7fffffff + 1].
The issue is that array_region (which uses int for keys into known
values in the array) uses subtraction to implement int_cmp for sorting
the keys, which isn't going to work for boundary values.
Potentially a wider type should be used, but for now this patch fixes
the ICE by using explicit comparisons rather than subtraction to
implement the qsort callback.
gcc/analyzer/ChangeLog:
PR analyzer/93352
* region-model.cc (int_cmp): Rename to...
(array_region::key_cmp): ...this, using key_t rather than int.
Rewrite in terms of comparisons rather than subtraction to
ensure qsort is anti-symmetric when handling extreme values.
(array_region::walk_for_canonicalization): Update for above
renaming.
* region-model.h (array_region::key_cmp): New decl.
gcc/testsuite/ChangeLog:
PR analyzer/93352
* gcc.dg/analyzer/pr93352.c: New test.
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/analyzer/ChangeLog | 11 | ||||
-rw-r--r-- | gcc/analyzer/region-model.cc | 19 | ||||
-rw-r--r-- | gcc/analyzer/region-model.h | 2 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/analyzer/pr93352.c | 12 |
5 files changed, 42 insertions, 7 deletions
diff --git a/gcc/analyzer/ChangeLog b/gcc/analyzer/ChangeLog index 3e6e21b..b49f43b 100644 --- a/gcc/analyzer/ChangeLog +++ b/gcc/analyzer/ChangeLog @@ -1,3 +1,14 @@ +2020-01-21 David Malcolm <dmalcolm@redhat.com> + + PR analyzer/93352 + * region-model.cc (int_cmp): Rename to... + (array_region::key_cmp): ...this, using key_t rather than int. + Rewrite in terms of comparisons rather than subtraction to + ensure qsort is anti-symmetric when handling extreme values. + (array_region::walk_for_canonicalization): Update for above + renaming. + * region-model.h (array_region::key_cmp): New decl. + 2020-01-17 David Malcolm <dmalcolm@redhat.com> PR analyzer/93290 diff --git a/gcc/analyzer/region-model.cc b/gcc/analyzer/region-model.cc index 1e0be31..9474c67 100644 --- a/gcc/analyzer/region-model.cc +++ b/gcc/analyzer/region-model.cc @@ -2387,15 +2387,20 @@ array_region::get_key_for_child_region (region_id child_rid, key_t *out) const return false; } -/* qsort comparator for int. */ +/* qsort comparator for array_region's keys. */ -static int -int_cmp (const void *p1, const void *p2) +int +array_region::key_cmp (const void *p1, const void *p2) { - int i1 = *(const int *)p1; - int i2 = *(const int *)p2; + key_t i1 = *(const key_t *)p1; + key_t i2 = *(const key_t *)p2; - return i1 - i2; + if (i1 > i2) + return 1; + else if (i1 < i2) + return -1; + else + return 0; } /* Implementation of region::walk_for_canonicalization vfunc for @@ -2412,7 +2417,7 @@ array_region::walk_for_canonicalization (canonicalization *c) const int key_a = (*iter).first; keys.quick_push (key_a); } - keys.qsort (int_cmp); + keys.qsort (key_cmp); unsigned i; int key; diff --git a/gcc/analyzer/region-model.h b/gcc/analyzer/region-model.h index eea808e..c9c8265 100644 --- a/gcc/analyzer/region-model.h +++ b/gcc/analyzer/region-model.h @@ -1319,6 +1319,8 @@ public: static key_t key_from_constant (tree cst); private: + static int key_cmp (const void *, const void *); + /* Mapping from tree to child region. */ map_t m_map; }; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 2fffb91b..9681453 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2020-01-21 David Malcolm <dmalcolm@redhat.com> + + PR analyzer/93352 + * gcc.dg/analyzer/pr93352.c: New test. + 2020-01-22 Hans-Peter Nilsson <hp@axis.com> * gcc.target/cris/asm-v8.S, gcc.target/cris/inasm-v8.c, diff --git a/gcc/testsuite/gcc.dg/analyzer/pr93352.c b/gcc/testsuite/gcc.dg/analyzer/pr93352.c new file mode 100644 index 0000000..ccb96d0 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/pr93352.c @@ -0,0 +1,12 @@ +/* { dg-additional-options "-Wno-overflow" } */ + +struct yc { + int c0; + char di[]; +}; + +void +qt (struct yc *ab) +{ + ab->di[0x7fffffff + 1] = ab->di[0]; +} |