diff options
| author | Luc Van Oostenryck <luc.vanoostenryck@gmail.com> | 2017-07-04 21:40:13 +0200 |
|---|---|---|
| committer | Luc Van Oostenryck <luc.vanoostenryck@gmail.com> | 2017-07-31 17:25:51 +0200 |
| commit | d254b816c4b6b8a692507567ad9127ca9991596d (patch) | |
| tree | e538b707b12238bf345e8e98ca4c258ce64cc0ff /validation | |
| parent | ec3f72e981792a86a9e002471a06d61ecd5c6675 (diff) | |
| download | sparse-dev-d254b816c4b6b8a692507567ad9127ca9991596d.tar.gz | |
fix ptrlist corruption while killing unreachable BBs
In commit (51cfbc90a5 "fix: kill unreachable BBs after killing a child")
kill_unreachable_bbs() was called during simplification in order
to avoid creating fake cycles between phis and issuing bogus
"crazy programmer" warnings.
However, simplification is done via cse.c:clean_up_insns()
which is looping over all BBs while kill_unreachable_bbs()
loops over all BBs *and* can delete some of them which may
corrupt the looping in clean_up_insns().
Fix this by:
1) refuse to emit the "crazy programmer" warning if there
is a potential dead BB
2) move kill_unreachable_bbs() in the main cleanup loop
which will avoid nested ep->bbs loop.
Note: this solution is preferable to some others because
the "crazy programmer" condition happens very rarely.
It this thus better to delay this check than to call
kill_unreachable_bbs() preventively.
Note: the reproducer is one with very broken syntax but nothing
forbid the same situation to happen with a valid program.
Fixes: 51cfbc90a5e1462fcd624a1598ecd985a508a5d6
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
Diffstat (limited to 'validation')
| -rw-r--r-- | validation/crash-ptrlist.c | 23 | ||||
| -rw-r--r-- | validation/crazy02-not-so.c | 18 |
2 files changed, 41 insertions, 0 deletions
diff --git a/validation/crash-ptrlist.c b/validation/crash-ptrlist.c new file mode 100644 index 00000000..8e9b5cb5 --- /dev/null +++ b/validation/crash-ptrlist.c @@ -0,0 +1,23 @@ +a; +char b; +c() { + while () { + int *d; + while () { + char *e = &b; + if (a ?: (*d = f || *0) || g) { + if + ; + } else { + int h = 0; + if (j) { + char **i = &e; + if (0 ? 0 : 0 ?: (**i = 1 || 0 && 0)) h ?: (*e = i && &h + +/* + * check-name: crash ptrlist + * check-command: test-linearize $file + * + * check-error-ignore + * check-output-ignore + */ diff --git a/validation/crazy02-not-so.c b/validation/crazy02-not-so.c index fe713358..19ee2529 100644 --- a/validation/crazy02-not-so.c +++ b/validation/crazy02-not-so.c @@ -16,6 +16,24 @@ int foo(int *ptr, int i) return 1; } +int bar(int *ptr, int i) +{ + int *p; + + switch (i - i) { // will be optimized to 0 + case 0: + return 0; + case 1: // will be optimized away + // p is uninitialized + do { // will be an unreachable loop + *p++ = 123; + } while (--i); + break; + } + + return 1; +} + /* * check-name: crazy02-not-so.c * check-command: sparse -Wno-decl $file |
