Age | Commit message (Collapse) | Author | Files | Lines |
|
|
|
No functional change intended.
gcc/analyzer/ChangeLog:
* analyzer.cc: Include "make-unique.h". Convert "to_json"
functions to use std::unique_ptr.
* call-string.cc: Likewise.
* constraint-manager.cc: Likewise.
* diagnostic-manager.cc: Likewise.
* engine.cc: Likewise.
* program-point.cc: Likewise.
* program-state.cc: Likewise.
* ranges.cc: Likewise.
* region-model.cc: Likewise.
* region.cc: Likewise.
* svalue.cc: Likewise.
* sm.cc: Likewise.
* store.cc: Likewise.
* supergraph.cc: Likewise.
* analyzer.h: Convert "to_json" functions to return
std::unique_ptr.
* call-string.h: Likewise.
* constraint-manager.h: Likewise.
(bounded_range::set_json_attr): Pass "obj" by reference.
* diagnostic-manager.h: Convert "to_json" functions to return
std::unique_ptr.
* exploded-graph.h: Likewise.
* program-point.h: Likewise.
* program-state.h: Likewise.
* ranges.h: Likewise.
* region-model.h: Likewise.
* region.h: Likewise.
* sm.h: Likewise.
* store.h: Likewise.
* supergraph.h: Likewise.
* svalue.h: Likewise.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
I've tried to build stage3 with
-Wleading-whitespace=blanks -Wtrailing-whitespace=blank -Wno-error=leading-whitespace=blanks -Wno-error=trailing-whitespace=blank
added to STRICT_WARN and that expectably resulted in about
2744 unique trailing whitespace warnings and 124837 leading whitespace
warnings when excluding *.md files (which obviously is in big part a
generator issue). Others from that are generator related, I think those
need to be solved later.
The following patch just fixes up the easy case (trailing whitespace),
which could be easily automated:
for i in `find . -name \*.h -o -name \*.cc -o -name \*.c | xargs grep -l '[ ]$' | grep -v testsuite/`; do sed -i -e 's/[ ]*$//' $i; done
I've excluded files which I knew are obviously generated or go FE.
Is there anything else we'd want to avoid the changes?
Due to patch size, I've split it between gcc/ part (this patch)
and rest (include/, libiberty/, libgcc/, libcpp/, libstdc++-v3/).
2024-10-24 Jakub Jelinek <jakub@redhat.com>
gcc/
* lra-assigns.cc: Remove trailing whitespace.
* symtab.cc: Likewise.
* stmt.cc: Likewise.
* cgraphbuild.cc: Likewise.
* cfgcleanup.cc: Likewise.
* loop-init.cc: Likewise.
* df-problems.cc: Likewise.
* diagnostic-macro-unwinding.cc: Likewise.
* langhooks.h: Likewise.
* except.cc: Likewise.
* tree-vect-loop.cc: Likewise.
* coverage.cc: Likewise.
* hash-table.cc: Likewise.
* ggc-page.cc: Likewise.
* gimple-ssa-strength-reduction.cc: Likewise.
* tree-parloops.cc: Likewise.
* internal-fn.cc: Likewise.
* ipa-split.cc: Likewise.
* calls.cc: Likewise.
* reorg.cc: Likewise.
* sbitmap.h: Likewise.
* omp-offload.cc: Likewise.
* cfgrtl.cc: Likewise.
* reginfo.cc: Likewise.
* gengtype.h: Likewise.
* omp-general.h: Likewise.
* ipa-comdats.cc: Likewise.
* gimple-range-edge.h: Likewise.
* tree-ssa-structalias.cc: Likewise.
* target.def: Likewise.
* basic-block.h: Likewise.
* graphite-isl-ast-to-gimple.cc: Likewise.
* auto-profile.cc: Likewise.
* optabs.cc: Likewise.
* gengtype-lex.l: Likewise.
* optabs.def: Likewise.
* ira-build.cc: Likewise.
* ira.cc: Likewise.
* function.h: Likewise.
* tree-ssa-propagate.cc: Likewise.
* gcov-io.cc: Likewise.
* builtin-types.def: Likewise.
* ddg.cc: Likewise.
* lra-spills.cc: Likewise.
* cfg.cc: Likewise.
* bitmap.cc: Likewise.
* gimple-range-gori.h: Likewise.
* tree-ssa-loop-im.cc: Likewise.
* cfghooks.h: Likewise.
* genmatch.cc: Likewise.
* explow.cc: Likewise.
* lto-streamer-in.cc: Likewise.
* graphite-scop-detection.cc: Likewise.
* ipa-prop.cc: Likewise.
* gcc.cc: Likewise.
* vec.h: Likewise.
* cfgexpand.cc: Likewise.
* config/alpha/vms.h: Likewise.
* config/alpha/alpha.cc: Likewise.
* config/alpha/driver-alpha.cc: Likewise.
* config/alpha/elf.h: Likewise.
* config/iq2000/iq2000.h: Likewise.
* config/iq2000/iq2000.cc: Likewise.
* config/pa/pa-64.h: Likewise.
* config/pa/som.h: Likewise.
* config/pa/pa.cc: Likewise.
* config/pa/pa.h: Likewise.
* config/pa/pa32-regs.h: Likewise.
* config/c6x/c6x.cc: Likewise.
* config/openbsd-stdint.h: Likewise.
* config/elfos.h: Likewise.
* config/lm32/lm32.cc: Likewise.
* config/lm32/lm32.h: Likewise.
* config/lm32/lm32-protos.h: Likewise.
* config/darwin-c.cc: Likewise.
* config/rx/rx.cc: Likewise.
* config/host-darwin.h: Likewise.
* config/netbsd.h: Likewise.
* config/ia64/ia64.cc: Likewise.
* config/ia64/freebsd.h: Likewise.
* config/avr/avr-c.cc: Likewise.
* config/avr/avr.cc: Likewise.
* config/avr/avr-arch.h: Likewise.
* config/avr/avr.h: Likewise.
* config/avr/stdfix.h: Likewise.
* config/avr/gen-avr-mmcu-specs.cc: Likewise.
* config/avr/avr-log.cc: Likewise.
* config/avr/elf.h: Likewise.
* config/avr/gen-avr-mmcu-texi.cc: Likewise.
* config/avr/avr-devices.cc: Likewise.
* config/nvptx/nvptx.cc: Likewise.
* config/vx-common.h: Likewise.
* config/sol2.cc: Likewise.
* config/rl78/rl78.cc: Likewise.
* config/cris/cris.cc: Likewise.
* config/arm/symbian.h: Likewise.
* config/arm/unknown-elf.h: Likewise.
* config/arm/linux-eabi.h: Likewise.
* config/arm/arm.cc: Likewise.
* config/arm/arm-mve-builtins.h: Likewise.
* config/arm/bpabi.h: Likewise.
* config/arm/vxworks.h: Likewise.
* config/arm/arm.h: Likewise.
* config/arm/aout.h: Likewise.
* config/arm/elf.h: Likewise.
* config/host-linux.cc: Likewise.
* config/sh/sh_treg_combine.cc: Likewise.
* config/sh/vxworks.h: Likewise.
* config/sh/elf.h: Likewise.
* config/sh/netbsd-elf.h: Likewise.
* config/sh/sh.cc: Likewise.
* config/sh/embed-elf.h: Likewise.
* config/sh/sh.h: Likewise.
* config/darwin-driver.cc: Likewise.
* config/m32c/m32c.cc: Likewise.
* config/frv/frv.cc: Likewise.
* config/openbsd.h: Likewise.
* config/aarch64/aarch64-protos.h: Likewise.
* config/aarch64/aarch64-builtins.cc: Likewise.
* config/aarch64/aarch64-cost-tables.h: Likewise.
* config/aarch64/aarch64.cc: Likewise.
* config/bfin/bfin.cc: Likewise.
* config/bfin/bfin.h: Likewise.
* config/bfin/bfin-protos.h: Likewise.
* config/i386/gmm_malloc.h: Likewise.
* config/i386/djgpp.h: Likewise.
* config/i386/sol2.h: Likewise.
* config/i386/stringop.def: Likewise.
* config/i386/i386-features.cc: Likewise.
* config/i386/openbsdelf.h: Likewise.
* config/i386/cpuid.h: Likewise.
* config/i386/i386.h: Likewise.
* config/i386/smmintrin.h: Likewise.
* config/i386/avx10_2-512convertintrin.h: Likewise.
* config/i386/i386-options.cc: Likewise.
* config/i386/i386-opts.h: Likewise.
* config/i386/i386-expand.cc: Likewise.
* config/i386/avx512dqintrin.h: Likewise.
* config/i386/wmmintrin.h: Likewise.
* config/i386/gnu-user.h: Likewise.
* config/i386/host-mingw32.cc: Likewise.
* config/i386/avx10_2bf16intrin.h: Likewise.
* config/i386/cygwin.h: Likewise.
* config/i386/driver-i386.cc: Likewise.
* config/i386/biarch64.h: Likewise.
* config/i386/host-cygwin.cc: Likewise.
* config/i386/cygming.h: Likewise.
* config/i386/i386-builtins.cc: Likewise.
* config/i386/avx10_2convertintrin.h: Likewise.
* config/i386/i386.cc: Likewise.
* config/i386/gas.h: Likewise.
* config/i386/freebsd.h: Likewise.
* config/mingw/winnt-cxx.cc: Likewise.
* config/mingw/winnt.cc: Likewise.
* config/h8300/h8300.cc: Likewise.
* config/host-solaris.cc: Likewise.
* config/m32r/m32r.h: Likewise.
* config/m32r/m32r.cc: Likewise.
* config/darwin.h: Likewise.
* config/sparc/linux64.h: Likewise.
* config/sparc/sparc-protos.h: Likewise.
* config/sparc/sysv4.h: Likewise.
* config/sparc/sparc.h: Likewise.
* config/sparc/linux.h: Likewise.
* config/sparc/freebsd.h: Likewise.
* config/sparc/sparc.cc: Likewise.
* config/gcn/gcn-run.cc: Likewise.
* config/gcn/gcn.cc: Likewise.
* config/gcn/gcn-tree.cc: Likewise.
* config/kopensolaris-gnu.h: Likewise.
* config/nios2/nios2.h: Likewise.
* config/nios2/elf.h: Likewise.
* config/nios2/nios2.cc: Likewise.
* config/host-netbsd.cc: Likewise.
* config/rtems.h: Likewise.
* config/pdp11/pdp11.cc: Likewise.
* config/pdp11/pdp11.h: Likewise.
* config/mn10300/mn10300.cc: Likewise.
* config/mn10300/linux.h: Likewise.
* config/moxie/moxie.h: Likewise.
* config/moxie/moxie.cc: Likewise.
* config/rs6000/aix71.h: Likewise.
* config/rs6000/vec_types.h: Likewise.
* config/rs6000/xcoff.h: Likewise.
* config/rs6000/rs6000.cc: Likewise.
* config/rs6000/rs6000-internal.h: Likewise.
* config/rs6000/rs6000-p8swap.cc: Likewise.
* config/rs6000/rs6000-c.cc: Likewise.
* config/rs6000/aix.h: Likewise.
* config/rs6000/rs6000-logue.cc: Likewise.
* config/rs6000/rs6000-string.cc: Likewise.
* config/rs6000/rs6000-call.cc: Likewise.
* config/rs6000/ppu_intrinsics.h: Likewise.
* config/rs6000/altivec.h: Likewise.
* config/rs6000/darwin.h: Likewise.
* config/rs6000/host-darwin.cc: Likewise.
* config/rs6000/freebsd64.h: Likewise.
* config/rs6000/spu2vmx.h: Likewise.
* config/rs6000/linux.h: Likewise.
* config/rs6000/si2vmx.h: Likewise.
* config/rs6000/driver-rs6000.cc: Likewise.
* config/rs6000/freebsd.h: Likewise.
* config/vxworksae.h: Likewise.
* config/mips/frame-header-opt.cc: Likewise.
* config/mips/mips.h: Likewise.
* config/mips/mips.cc: Likewise.
* config/mips/sde.h: Likewise.
* config/darwin-protos.h: Likewise.
* config/mcore/mcore-elf.h: Likewise.
* config/mcore/mcore.h: Likewise.
* config/mcore/mcore.cc: Likewise.
* config/epiphany/epiphany.cc: Likewise.
* config/fr30/fr30.h: Likewise.
* config/fr30/fr30.cc: Likewise.
* config/riscv/riscv-vector-builtins-shapes.cc: Likewise.
* config/riscv/riscv-vector-builtins-bases.cc: Likewise.
* config/visium/visium.h: Likewise.
* config/mmix/mmix.cc: Likewise.
* config/v850/v850.cc: Likewise.
* config/v850/v850-c.cc: Likewise.
* config/v850/v850.h: Likewise.
* config/stormy16/stormy16.cc: Likewise.
* config/stormy16/stormy16-protos.h: Likewise.
* config/stormy16/stormy16.h: Likewise.
* config/arc/arc.cc: Likewise.
* config/vxworks.cc: Likewise.
* config/microblaze/microblaze-c.cc: Likewise.
* config/microblaze/microblaze-protos.h: Likewise.
* config/microblaze/microblaze.h: Likewise.
* config/microblaze/microblaze.cc: Likewise.
* config/freebsd-spec.h: Likewise.
* config/m68k/m68kelf.h: Likewise.
* config/m68k/m68k.cc: Likewise.
* config/m68k/netbsd-elf.h: Likewise.
* config/m68k/linux.h: Likewise.
* config/freebsd.h: Likewise.
* config/host-openbsd.cc: Likewise.
* regcprop.cc: Likewise.
* dumpfile.cc: Likewise.
* combine.cc: Likewise.
* tree-ssa-forwprop.cc: Likewise.
* ipa-profile.cc: Likewise.
* hw-doloop.cc: Likewise.
* opts.cc: Likewise.
* gcc-ar.cc: Likewise.
* tree-cfg.cc: Likewise.
* incpath.cc: Likewise.
* tree-ssa-sccvn.cc: Likewise.
* function.cc: Likewise.
* genattrtab.cc: Likewise.
* rtl.def: Likewise.
* genchecksum.cc: Likewise.
* profile.cc: Likewise.
* df-core.cc: Likewise.
* tree-pretty-print.cc: Likewise.
* tree.h: Likewise.
* plugin.cc: Likewise.
* tree-ssa-loop-ch.cc: Likewise.
* emit-rtl.cc: Likewise.
* haifa-sched.cc: Likewise.
* gimple-range-edge.cc: Likewise.
* range-op.cc: Likewise.
* tree-ssa-ccp.cc: Likewise.
* dwarf2cfi.cc: Likewise.
* recog.cc: Likewise.
* vtable-verify.cc: Likewise.
* system.h: Likewise.
* regrename.cc: Likewise.
* tree-ssa-dom.cc: Likewise.
* loop-unroll.cc: Likewise.
* lra-constraints.cc: Likewise.
* pretty-print.cc: Likewise.
* ifcvt.cc: Likewise.
* ipa.cc: Likewise.
* alloc-pool.h: Likewise.
* collect2.cc: Likewise.
* pointer-query.cc: Likewise.
* cfgloop.cc: Likewise.
* toplev.cc: Likewise.
* sese.cc: Likewise.
* gengtype.cc: Likewise.
* gimplify-me.cc: Likewise.
* double-int.cc: Likewise.
* bb-reorder.cc: Likewise.
* dwarf2out.cc: Likewise.
* tree-ssa-loop-ivcanon.cc: Likewise.
* tree-ssa-reassoc.cc: Likewise.
* cgraph.cc: Likewise.
* sel-sched.cc: Likewise.
* attribs.cc: Likewise.
* expr.cc: Likewise.
* tree-ssa-scopedtables.h: Likewise.
* gimple-range-cache.cc: Likewise.
* ipa-pure-const.cc: Likewise.
* tree-inline.cc: Likewise.
* genhooks.cc: Likewise.
* gimple-range-phi.h: Likewise.
* shrink-wrap.cc: Likewise.
* tree.cc: Likewise.
* gimple.cc: Likewise.
* backend.h: Likewise.
* opts-common.cc: Likewise.
* cfg-flags.def: Likewise.
* gcse-common.cc: Likewise.
* tree-ssa-scopedtables.cc: Likewise.
* ccmp.cc: Likewise.
* builtins.def: Likewise.
* builtin-attrs.def: Likewise.
* postreload.cc: Likewise.
* sched-deps.cc: Likewise.
* ipa-inline-transform.cc: Likewise.
* tree-vect-generic.cc: Likewise.
* ipa-polymorphic-call.cc: Likewise.
* builtins.cc: Likewise.
* sel-sched-ir.cc: Likewise.
* trans-mem.cc: Likewise.
* ipa-visibility.cc: Likewise.
* cgraph.h: Likewise.
* tree-ssa-phiopt.cc: Likewise.
* genopinit.cc: Likewise.
* ipa-inline.cc: Likewise.
* omp-low.cc: Likewise.
* ipa-utils.cc: Likewise.
* tree-ssa-math-opts.cc: Likewise.
* tree-ssa-ifcombine.cc: Likewise.
* gimple-range.cc: Likewise.
* ipa-fnsummary.cc: Likewise.
* ira-color.cc: Likewise.
* value-prof.cc: Likewise.
* varasm.cc: Likewise.
* ipa-icf.cc: Likewise.
* ira-emit.cc: Likewise.
* lto-streamer.h: Likewise.
* lto-wrapper.cc: Likewise.
* regs.h: Likewise.
* gengtype-parse.cc: Likewise.
* alias.cc: Likewise.
* lto-streamer.cc: Likewise.
* real.h: Likewise.
* wide-int.h: Likewise.
* targhooks.cc: Likewise.
* gimple-ssa-warn-access.cc: Likewise.
* real.cc: Likewise.
* ipa-reference.cc: Likewise.
* bitmap.h: Likewise.
* ginclude/float.h: Likewise.
* ginclude/stddef.h: Likewise.
* ginclude/stdarg.h: Likewise.
* ginclude/stdatomic.h: Likewise.
* optabs.h: Likewise.
* sel-sched-ir.h: Likewise.
* convert.cc: Likewise.
* cgraphunit.cc: Likewise.
* lra-remat.cc: Likewise.
* tree-if-conv.cc: Likewise.
* gcov-dump.cc: Likewise.
* tree-predcom.cc: Likewise.
* dominance.cc: Likewise.
* gimple-range-cache.h: Likewise.
* ipa-devirt.cc: Likewise.
* rtl.h: Likewise.
* ubsan.cc: Likewise.
* tree-ssa.cc: Likewise.
* ssa.h: Likewise.
* cse.cc: Likewise.
* jump.cc: Likewise.
* hwint.h: Likewise.
* caller-save.cc: Likewise.
* coretypes.h: Likewise.
* ipa-fnsummary.h: Likewise.
* tree-ssa-strlen.cc: Likewise.
* modulo-sched.cc: Likewise.
* cgraphclones.cc: Likewise.
* lto-cgraph.cc: Likewise.
* hw-doloop.h: Likewise.
* data-streamer.h: Likewise.
* compare-elim.cc: Likewise.
* profile-count.h: Likewise.
* tree-vect-loop-manip.cc: Likewise.
* ree.cc: Likewise.
* reload.cc: Likewise.
* tree-ssa-loop-split.cc: Likewise.
* tree-into-ssa.cc: Likewise.
* gcse.cc: Likewise.
* cfgloopmanip.cc: Likewise.
* df.h: Likewise.
* fold-const.cc: Likewise.
* wide-int.cc: Likewise.
* gengtype-state.cc: Likewise.
* sanitizer.def: Likewise.
* tree-ssa-sink.cc: Likewise.
* target-hooks-macros.h: Likewise.
* tree-ssa-pre.cc: Likewise.
* gimple-pretty-print.cc: Likewise.
* ipa-utils.h: Likewise.
* tree-outof-ssa.cc: Likewise.
* tree-ssa-coalesce.cc: Likewise.
* gimple-match.h: Likewise.
* tree-ssa-loop-niter.cc: Likewise.
* tree-loop-distribution.cc: Likewise.
* tree-emutls.cc: Likewise.
* tree-eh.cc: Likewise.
* varpool.cc: Likewise.
* ssa-iterators.h: Likewise.
* asan.cc: Likewise.
* reload1.cc: Likewise.
* cfgloopanal.cc: Likewise.
* tree-vectorizer.cc: Likewise.
* simplify-rtx.cc: Likewise.
* opts-global.cc: Likewise.
* gimple-ssa-store-merging.cc: Likewise.
* expmed.cc: Likewise.
* tree-ssa-loop-prefetch.cc: Likewise.
* tree-ssa-dse.h: Likewise.
* tree-vect-stmts.cc: Likewise.
* gimple-fold.cc: Likewise.
* lra-coalesce.cc: Likewise.
* data-streamer-out.cc: Likewise.
* diagnostic.cc: Likewise.
* tree-ssa-alias.cc: Likewise.
* tree-vect-patterns.cc: Likewise.
* common/common-target.def: Likewise.
* common/config/rx/rx-common.cc: Likewise.
* common/config/msp430/msp430-common.cc: Likewise.
* common/config/avr/avr-common.cc: Likewise.
* common/config/i386/i386-common.cc: Likewise.
* common/config/pdp11/pdp11-common.cc: Likewise.
* common/config/rs6000/rs6000-common.cc: Likewise.
* common/config/mcore/mcore-common.cc: Likewise.
* graphite.cc: Likewise.
* gimple-low.cc: Likewise.
* genmodes.cc: Likewise.
* gimple-loop-jam.cc: Likewise.
* lto-streamer-out.cc: Likewise.
* predict.cc: Likewise.
* omp-expand.cc: Likewise.
* gimple-array-bounds.cc: Likewise.
* predict.def: Likewise.
* opts.h: Likewise.
* tree-stdarg.cc: Likewise.
* gimplify.cc: Likewise.
* ira-lives.cc: Likewise.
* loop-doloop.cc: Likewise.
* lra.cc: Likewise.
* gimple-iterator.h: Likewise.
* tree-sra.cc: Likewise.
gcc/fortran/
* trans-openmp.cc: Remove trailing whitespace.
* trans-common.cc: Likewise.
* match.h: Likewise.
* scanner.cc: Likewise.
* gfortranspec.cc: Likewise.
* io.cc: Likewise.
* iso-c-binding.def: Likewise.
* iso-fortran-env.def: Likewise.
* types.def: Likewise.
* openmp.cc: Likewise.
* f95-lang.cc: Likewise.
gcc/analyzer/
* state-purge.cc: Remove trailing whitespace.
* region-model.h: Likewise.
* region-model.cc: Likewise.
* program-point.cc: Likewise.
* exploded-graph.h: Likewise.
* program-state.cc: Likewise.
* supergraph.cc: Likewise.
gcc/c-family/
* c-ubsan.cc: Remove trailing whitespace.
* stub-objc.cc: Likewise.
* c-pragma.cc: Likewise.
* c-ppoutput.cc: Likewise.
* c-indentation.cc: Likewise.
* c-ada-spec.cc: Likewise.
* c-opts.cc: Likewise.
* c-common.cc: Likewise.
* c-format.cc: Likewise.
* c-omp.cc: Likewise.
* c-objc.h: Likewise.
* c-cppbuiltin.cc: Likewise.
* c-attribs.cc: Likewise.
* c-target.def: Likewise.
* c-common.h: Likewise.
gcc/c/
* c-typeck.cc: Remove trailing whitespace.
* gimple-parser.cc: Likewise.
* c-parser.cc: Likewise.
* c-decl.cc: Likewise.
gcc/cp/
* vtable-class-hierarchy.cc: Remove trailing whitespace.
* typeck2.cc: Likewise.
* decl.cc: Likewise.
* init.cc: Likewise.
* semantics.cc: Likewise.
* module.cc: Likewise.
* rtti.cc: Likewise.
* cxx-pretty-print.cc: Likewise.
* cvt.cc: Likewise.
* mangle.cc: Likewise.
* name-lookup.h: Likewise.
* coroutines.cc: Likewise.
* error.cc: Likewise.
* lambda.cc: Likewise.
* tree.cc: Likewise.
* g++spec.cc: Likewise.
* decl2.cc: Likewise.
* cp-tree.h: Likewise.
* parser.cc: Likewise.
* pt.cc: Likewise.
* call.cc: Likewise.
* lex.cc: Likewise.
* cp-lang.cc: Likewise.
* cp-tree.def: Likewise.
* constexpr.cc: Likewise.
* typeck.cc: Likewise.
* name-lookup.cc: Likewise.
* optimize.cc: Likewise.
* search.cc: Likewise.
* mapper-client.cc: Likewise.
* ptree.cc: Likewise.
* class.cc: Likewise.
gcc/jit/
* docs/examples/tut04-toyvm/toyvm.cc: Remove trailing whitespace.
gcc/lto/
* lto-object.cc: Remove trailing whitespace.
* lto-symtab.cc: Likewise.
* lto-partition.cc: Likewise.
* lang-specs.h: Likewise.
* lto-lang.cc: Likewise.
gcc/objc/
* objc-encoding.cc: Remove trailing whitespace.
* objc-map.h: Likewise.
* objc-next-runtime-abi-01.cc: Likewise.
* objc-act.cc: Likewise.
* objc-map.cc: Likewise.
gcc/objcp/
* objcp-decl.cc: Remove trailing whitespace.
* objcp-lang.cc: Likewise.
* objcp-decl.h: Likewise.
gcc/rust/
* util/optional.h: Remove trailing whitespace.
* util/expected.h: Likewise.
* util/rust-unicode-data.h: Likewise.
gcc/m2/
* mc-boot/GFpuIO.cc: Remove trailing whitespace.
* mc-boot/GFIO.cc: Likewise.
* mc-boot/GFormatStrings.cc: Likewise.
* mc-boot/GCmdArgs.cc: Likewise.
* mc-boot/GDebug.h: Likewise.
* mc-boot/GM2Dependent.cc: Likewise.
* mc-boot/GRTint.cc: Likewise.
* mc-boot/GDebug.cc: Likewise.
* mc-boot/GmcError.cc: Likewise.
* mc-boot/Gmcp4.cc: Likewise.
* mc-boot/GM2RTS.cc: Likewise.
* mc-boot/GIO.cc: Likewise.
* mc-boot/Gmcp5.cc: Likewise.
* mc-boot/GDynamicStrings.cc: Likewise.
* mc-boot/Gmcp1.cc: Likewise.
* mc-boot/GFormatStrings.h: Likewise.
* mc-boot/Gmcp2.cc: Likewise.
* mc-boot/Gmcp3.cc: Likewise.
* pge-boot/GFIO.cc: Likewise.
* pge-boot/GDebug.h: Likewise.
* pge-boot/GM2Dependent.cc: Likewise.
* pge-boot/GDebug.cc: Likewise.
* pge-boot/GM2RTS.cc: Likewise.
* pge-boot/GSymbolKey.cc: Likewise.
* pge-boot/GIO.cc: Likewise.
* pge-boot/GIndexing.cc: Likewise.
* pge-boot/GDynamicStrings.cc: Likewise.
* pge-boot/GFormatStrings.h: Likewise.
gcc/go/
* go-gcc.cc: Remove trailing whitespace.
* gospec.cc: Likewise.
|
|
gcc/analyzer/ChangeLog:
PR analyzer/106203
* checker-event.h: Include "analyzer/event-loc-info.h".
(struct event_loc_info): Move to its own header file.
* diagnostic-manager.cc
(diagnostic_manager::emit_saved_diagnostic): Move creation of
event_loc_info here from add_final_event, and if we have a
stmt_finder, call its update_event_loc_info method.
* engine.cc (leak_stmt_finder::update_event_loc_info): New.
(exploded_node::detect_leaks): Likewise.
(exploded_node::detect_leaks): Pass nullptr as call_stmt arg to
region_model::pop_frame.
* event-loc-info.h: New file, with content taken from
checker-event.h.
* exploded-graph.h (stmt_finder::update_event_loc_info): New pure
virtual function.
* infinite-loop.cc (infinite_loop_diagnostic::add_final_event):
Update for change to vfunc signature.
* infinite-recursion.cc
(infinite_recursion_diagnostic::add_final_event): Likewise.
* pending-diagnostic.cc (pending_diagnostic::add_final_event):
Pass in the event_loc_info from the caller, rather than generating
it from a gimple stmt and enode.
* pending-diagnostic.h (pending_diagnostic::add_final_event):
Likewise.
* region-model.cc (region_model::on_longjmp): Pass nullptr as
call_stmt arg to region_model::pop_frame.
(region_model::update_for_return_gcall): Likewise, but pass
call_stmt.
(class caller_context): New.
(region_model::pop_frame): Add "call_stmt" argument. Use it
and the frame_region with a caller_context when setting
result_dst_reg's value so that any diagnostic is reported at the
call stmt in the caller.
(selftest::test_stack_frames): Pass nullptr as call_stmt arg to
region_model::pop_frame.
(selftest::test_alloca): Likewise.
* region-model.h (region_model::pop_frame): Add "call_stmt"
argument.
gcc/testsuite/ChangeLog:
PR analyzer/106203
* c-c++-common/analyzer/allocation-size-1.c (test_9): Remove
xfail.
* c-c++-common/analyzer/allocation-size-2.c (test_8): Likewise.
* gcc.dg/analyzer/allocation-size-multiline-4.c: New test.
* gcc.dg/plugin/analyzer_cpython_plugin.c
(refcnt_stmt_finder::update_event_loc_info): New.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
PR analyzer/114159 reports an ICE inside playback of call summaries
for very low values of --param=analyzer-max-svalue-depth=VAL.
Root cause is that call_summary_edge_info's ctor tries to evaluate
the function ptr of a gimple call stmt and assumes it gets a function *,
but with low values of --param=analyzer-max-svalue-depth=VAL we get
back an UNKNOWN svalue, rather than a pointer to a specific function.
Fix by adding a new call_info ctor that passes a specific
const function & from the call_summary_edge_info, rather than trying
to compute the function.
In doing so, I noticed that the analyzer was using "function *" despite
not modifying functions, and was sloppy about can-be-null versus
must-be-non-null function pointers, so I "constified" the function, and
converted the many places where the function must be non-null to be
"const function &".
gcc/analyzer/ChangeLog:
PR analyzer/114159
* analyzer.cc: Include "tree-dfa.h".
(get_ssa_default_def): New decl.
* analyzer.h (get_ssa_default_def): New.
* call-info.cc (call_info::call_info): New ctor taking an explicit
called_fn.
* call-info.h (call_info::call_info): Likewise.
* call-summary.cc (call_summary_replay::call_summary_replay):
Convert param from function * to const function &.
* call-summary.h (call_summary_replay::call_summary_replay):
Likewise.
* checker-event.h (state_change_event::get_dest_function):
Constify return value.
* engine.cc (point_and_state::validate): Update for conversion to
const function &.
(exploded_node::on_stmt): Likewise.
(call_summary_edge_info::call_summary_edge_info): Likewise.
Pass in called_fn to call_info ctor.
(exploded_node::replay_call_summaries): Update for conversion to
const function &. Convert per_function_data from * to &.
(exploded_node::replay_call_summary): Update for conversion to
const function &.
(exploded_graph::add_function_entry): Likewise.
(toplevel_function_p): Likewise.
(add_tainted_args_callback): Likewise.
(exploded_graph::build_initial_worklist): Likewise.
(exploded_graph::maybe_create_dynamic_call): Likewise.
(maybe_update_for_edge): Likewise.
(exploded_graph::on_escaped_function): Likewise.
* exploded-graph.h (exploded_node::replay_call_summaries):
Likewise.
(exploded_node::replay_call_summary): Likewise.
(exploded_graph::add_function_entry): Likewise.
* program-point.cc (function_point::from_function_entry):
Likewise.
(program_point::from_function_entry): Likewise.
* program-point.h (function_point::from_function_entry): Likewise.
(program_point::from_function_entry): Likewise.
* program-state.cc (program_state::push_frame): Likewise.
(program_state::get_current_function): Constify return type.
* program-state.h (program_state::push_frame): Update for
conversion to const function &.
(program_state::get_current_function): Likewise.
* region-model-manager.cc
(region_model_manager::get_frame_region): Likewise.
* region-model-manager.h
(region_model_manager::get_frame_region): Likewise.
* region-model.cc (region_model::called_from_main_p): Likewise.
(region_model::update_for_gcall): Likewise.
(region_model::push_frame): Likewise.
(region_model::get_current_function): Constify return type.
(region_model::pop_frame): Update for conversion to
const function &.
(selftest::test_stack_frames): Likewise.
(selftest::test_get_representative_path_var): Likewise.
(selftest::test_state_merging): Likewise.
(selftest::test_alloca): Likewise.
* region-model.h (region_model::push_frame): Likewise.
(region_model::get_current_function): Likewise.
* region.cc (frame_region::dump_to_pp): Likewise.
(frame_region::get_region_for_local): Likewise.
* region.h (class frame_region): Likewise.
* sm-signal.cc (signal_unsafe_call::describe_state_change):
Likewise.
(update_model_for_signal_handler): Likewise.
(signal_delivery_edge_info_t::update_model): Likewise.
(register_signal_handler::impl_transition): Likewise.
* state-purge.cc (class gimple_op_visitor): Likewise.
(state_purge_map::state_purge_map): Likewise.
(state_purge_map::get_or_create_data_for_decl): Likewise.
(state_purge_per_ssa_name::state_purge_per_ssa_name): Likewise.
(state_purge_per_ssa_name::add_to_worklist): Likewise.
(state_purge_per_ssa_name::process_point): Likewise.
(state_purge_per_decl::add_to_worklist): Likewise.
(state_purge_annotator::print_needed): Likewise.
* state-purge.h
(state_purge_map::get_or_create_data_for_decl): Likewise.
(class state_purge_per_tree): Likewise.
(class state_purge_per_ssa_name): Likewise.
(class state_purge_per_decl): Likewise.
* supergraph.cc (supergraph::dump_dot_to_pp): Likewise.
* supergraph.h
(supergraph::get_node_for_function_entry): Likewise.
(supergraph::get_node_for_function_exit): Likewise.
gcc/ChangeLog:
PR analyzer/114159
* function.cc (function_name): Make param const.
* function.h (function_name): Likewise.
gcc/testsuite/ChangeLog:
PR analyzer/114159
* c-c++-common/analyzer/call-summaries-pr114159.c: New test.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
|
|
This patch implements a new analyzer warning: -Wanalyzer-infinite-loop.
It works by examining the exploded graph once the latter has been
fully built. It attempts to detect cycles in the exploded graph in
which:
- no externally visible work occurs
- no escape is possible from the cycle once it has been entered
- the program state is "sufficiently concrete" at each step:
- no unknown activity could be occurring
- the worklist was fully drained for each enode in the cycle
i.e. every enode in the cycle is processed
For example, it correctly complains about this bogus "for" loop:
int sum = 0;
for (struct node *iter = n; iter; iter->next)
sum += n->val;
return sum;
like this:
infinite-loop-linked-list.c: In function ‘for_loop_noop_next’:
infinite-loop-linked-list.c:110:31: warning: infinite loop [CWE-835] [-Wanalyzer-infinite-loop]
110 | for (struct node *iter = n; iter; iter->next)
| ^~~~
‘for_loop_noop_next’: events 1-5
|
| 110 | for (struct node *iter = n; iter; iter->next)
| | ^~~~
| | |
| | (1) infinite loop here
| | (2) when ‘iter’ is non-NULL: always following ‘true’ branch...
| | (5) ...to here
| 111 | sum += n->val;
| | ~~~~~~~~~~~~~
| | | |
| | | (3) ...to here
| | (4) looping back...
|
gcc/ChangeLog:
PR analyzer/106147
* Makefile.in (ANALYZER_OBJS): Add analyzer/infinite-loop.o.
* doc/invoke.texi: Add -fdump-analyzer-infinite-loop and
-Wanalyzer-infinite-loop. Add missing CWE link for
-Wanalyzer-infinite-recursion.
* timevar.def (TV_ANALYZER_INFINITE_LOOPS): New.
gcc/analyzer/ChangeLog:
PR analyzer/106147
* analyzer.opt (Wanalyzer-infinite-loop): New option.
(fdump-analyzer-infinite-loop): New option.
* checker-event.h (start_cfg_edge_event::get_desc): Drop "final".
(start_cfg_edge_event::maybe_describe_condition): Convert from
private to protected.
* checker-path.h (checker_path::get_logger): New.
* diagnostic-manager.cc (process_worklist_item): Update for
new context param of maybe_update_for_edge.
* engine.cc
(impl_region_model_context::impl_region_model_context): Add
out_could_have_done_work param to both ctors and use it to
initialize mm_out_could_have_done_work.
(impl_region_model_context::maybe_did_work): New vfunc
implementation.
(exploded_node::on_stmt): Add out_could_have_done_work param and
pass to ctxt ctor.
(exploded_node::on_stmt_pre): Treat setjmp and longjmp as "doing
work".
(exploded_node::on_longjmp): Likewise.
(exploded_edge::exploded_edge): Add "could_do_work" param and use
it to initialize m_could_do_work_p.
(exploded_edge::dump_dot_label): Add result of could_do_work_p.
(exploded_graph::add_function_entry): Mark edge as doing no work.
(exploded_graph::add_edge): Add "could_do_work" param and pass to
exploded_edge ctor.
(add_tainted_args_callback): Treat as doing no work.
(exploded_graph::process_worklist): Likewise when merging nodes.
(maybe_process_run_of_before_supernode_enodes::item): Likewise.
(exploded_graph::maybe_create_dynamic_call): Likewise.
(exploded_graph::process_node): Likewise for phi nodes.
Pass in a "could_have_done_work" bool when handling stmts and use
when creating edges. Assume work is done at bifurcation.
(exploded_path::feasible_p): Update for new context param of
maybe_update_for_edge.
(feasibility_state::feasibility_state): New ctor.
(feasibility_state::operator=): New.
(feasibility_state::maybe_update_for_edge): Add ctxt param and use
it. Fix missing newline when logging state.
(impl_run_checkers): Call exploded_graph::detect_infinite_loops.
* exploded-graph.h
(impl_region_model_context::impl_region_model_context): Add
out_could_have_done_work param to both ctors.
(impl_region_model_context::maybe_did_work): New decl.
(impl_region_model_context::checking_for_infinite_loop_p): New.
(impl_region_model_context::on_unusable_in_infinite_loop): New.
(impl_region_model_context::m_out_could_have_done_work): New
field.
(exploded_node::on_stmt): Add "out_could_have_done_work" param.
(exploded_edge::exploded_edge): Add "could_do_work" param.
(exploded_edge::could_do_work_p): New accessor.
(exploded_edge::m_could_do_work_p): New field.
(exploded_graph::add_edge): Add "could_do_work" param.
(exploded_graph::detect_infinite_loops): New decl.
(feasibility_state::feasibility_state): New ctor.
(feasibility_state::operator=): New decl.
(feasibility_state::maybe_update_for_edge): Add ctxt param.
* infinite-loop.cc: New file.
* program-state.cc (program_state::on_edge): Log the rejected
constraint when region_model::maybe_update_for_edge fails.
* region-model.cc (region_model::on_assignment): Treat any writes
other than to the stack as "doing work".
(region_model::on_stmt_pre): Treat all asm stmts as "doing work".
(region_model::on_call_post): Likewise for all calls to functions
with unknown side effects.
(region_model::handle_phi): Add svals_changing_meaning param.
Mark widening svalue in phi nodes as changing meaning.
(unusable_in_infinite_loop_constraint_p): New.
(region_model::add_constraint): If we're checking for an infinite
loop, bail out on unusable svalues, or if we don't have a definite
true/false for the constraint.
(region_model::update_for_phis): Gather all svalues changing
meaning in phi nodes, and purge constraints involving them.
(region_model::replay_call_summary): Treat all call summaries as
doing work.
(region_model::can_merge_with_p): Purge constraints involving
svalues that change meaning.
(model_merger::on_widening_reuse): New.
(test_iteration_1): Likewise.
(selftest::test_iteration_1): Remove assertion that model6 "knows"
that i < 157.
* region-model.h (region_model::handle_phi): Add
svals_changing_meaning param
(region_model_context::maybe_did_work): New pure virtual func.
(region_model_context::checking_for_infinite_loop_p): Likewise.
(region_model_context::on_unusable_in_infinite_loop): Likewise.
(noop_region_model_context::maybe_did_work): Implement.
(noop_region_model_context::checking_for_infinite_loop_p):
Likewise.
(noop_region_model_context::on_unusable_in_infinite_loop):
Likewise.
(region_model_context_decorator::maybe_did_work): Implement.
(region_model_context_decorator::checking_for_infinite_loop_p):
Likewise.
(region_model_context_decorator::on_unusable_in_infinite_loop):
Likewise.
(model_merger::on_widening_reuse): New decl.
(model_merger::m_svals_changing_meaning): New field.
* sm-signal.cc (register_signal_handler::impl_transition): Assume
the edge "does work".
* supergraph.cc (supernode::get_start_location): Use CFG edge's
goto_locus if available.
(supernode::get_end_location): Likewise.
(cfg_superedge::dump_label_to_pp): Dump edges with a "goto_locus"
* supergraph.h (cfg_superedge::get_goto_locus): New.
* svalue.cc (svalue::can_merge_p): Call on_widening_reuse for
widening values.
(involvement_visitor::visit_widening_svalue): New.
(svalue::involves_p): Update assertion to allow widening svalues.
gcc/testsuite/ChangeLog:
PR analyzer/106147
* c-c++-common/analyzer/gzio-2.c: Add dg-warning for infinite
loop, marked as xfail.
* c-c++-common/analyzer/infinite-loop-2.c: New test.
* c-c++-common/analyzer/infinite-loop-4.c: New test.
* c-c++-common/analyzer/infinite-loop-crc32c.c: New test.
* c-c++-common/analyzer/infinite-loop-doom-d_main-IdentifyVersion.c:
New test.
* c-c++-common/analyzer/infinite-loop-doom-v_video.c: New test.
* c-c++-common/analyzer/infinite-loop-g_error.c: New test.
* c-c++-common/analyzer/infinite-loop-linked-list.c: New test.
* c-c++-common/analyzer/infinite-recursion-inlining.c: Add
dg-warning directives for infinite loop.
* c-c++-common/analyzer/inlining-4-multiline.c: Update expected
paths for event 5 having a location.
* gcc.dg/analyzer/boxed-malloc-1.c: Add dg-warning for infinite
loop.
* gcc.dg/analyzer/data-model-20.c: Likewise. Add comment about
suspect code, and create...
* gcc.dg/analyzer/data-model-20a.c: ...this new test by cleaning
it up.
* gcc.dg/analyzer/edges-1.c: Add a placeholder statement to avoid
the "...to here" from the if stmt occurring at the "while", and
thus being treated as a bogus event.
* gcc.dg/analyzer/explode-2a.c: Add dg-warning for infinite loop.
* gcc.dg/analyzer/infinite-loop-1.c: New test.
* gcc.dg/analyzer/malloc-1.c: Add dg-warning for infinite loop.
* gcc.dg/analyzer/out-of-bounds-coreutils.c: Add TODO.
* gcc.dg/analyzer/paths-4.c: Add dg-warning for infinite loop.
* gcc.dg/analyzer/pr103892.c: Likewise.
* gcc.dg/analyzer/pr93546.c: Likewise.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
gcc/analyzer/ChangeLog:
* diagnostic-manager.cc (process_worklist_item): Use
std::unique_ptr rather than plain rejected_constraint *.
* engine.cc (exploded_path::feasible_p): Likewise.
(feasibility_state::maybe_update_for_edge): Likewise.
* exploded-graph.h (feasibility_problem::feasibility_problem):
Likewise.
(feasibility_problem::~feasibility_problem): Delete.
(feasibility_problem::m_rc): Use std::unique_ptr.
(feasibility_state::maybe_update_for_edge): Likewise.
* feasible-graph.cc (feasible_graph::add_feasibility_problem):
Likewise.
* feasible-graph.h (class infeasible_node): Likewise.
(feasible_graph::add_feasibility_problem): Likewise.
* region-model.cc (region_model::add_constraint): Likewise.
(region_model::maybe_update_for_edge): Likewise.
(region_model::apply_constraints_for_gcond): Likewise.
(region_model::apply_constraints_for_gswitch): Likewise.
(region_model::apply_constraints_for_exception): Likewise.
* region-model.h (class region_model): Likewise for decls.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
This patch introduces initial support for reference count checking of
PyObjects in relation to the Python/C API for the CPython plugin.
Additionally, the core analyzer underwent several modifications to
accommodate this feature. These include:
- Introducing support for callbacks at the end of
region_model::pop_frame. This is our current point of validation for
the reference count of PyObjects.
- An added optional custom stmt_finder parameter to
region_model_context::warn. This aids in emitting a diagnostic
concerning the reference count, especially when the stmt_finder is
NULL, which is currently the case during region_model::pop_frame.
The current diagnostic we emit relating to the reference count
appears as follows:
rc3.c:23:10: warning: expected ‘item’ to have reference count: ‘1’ but
ob_refcnt field is: ‘2’
23 | return list;
| ^~~~
‘create_py_object’: events 1-4
|
| 4 | PyObject* item = PyLong_FromLong(3);
| | ^~~~~~~~~~~~~~~~~~
| | |
| | (1) when ‘PyLong_FromLong’ succeeds
| 5 | PyObject* list = PyList_New(1);
| | ~~~~~~~~~~~~~
| | |
| | (2) when ‘PyList_New’ succeeds
|......
| 14 | PyList_Append(list, item);
| | ~~~~~~~~~~~~~~~~~~~~~~~~~
| | |
| | (3) when ‘PyList_Append’ succeeds, moving buffer
|......
| 23 | return list;
| | ~~~~
| | |
| | (4) here
|
This is a WIP in several ways:
- Currently, functions returning PyObject * are assumed to always
produce a new reference.
- The validation of reference count is only for PyObjects created within
a function body. Verifying reference counts for PyObjects passed as
parameters is not supported in this patch.
gcc/analyzer/ChangeLog:
PR analyzer/107646
* engine.cc (impl_region_model_context::warn): New optional
parameter.
* exploded-graph.h (class impl_region_model_context): Likewise.
* region-model.cc (region_model::pop_frame): New callback
feature for region_model::pop_frame.
* region-model.h (struct append_regions_cb_data): Likewise.
(class region_model): Likewise.
(class region_model_context): New optional parameter.
(class region_model_context_decorator): Likewise.
gcc/testsuite/ChangeLog:
PR analyzer/107646
* gcc.dg/plugin/analyzer_cpython_plugin.c: Implements reference
count checking for PyObjects.
* gcc.dg/plugin/cpython-plugin-test-2.c: Moved to...
* gcc.dg/plugin/cpython-plugin-test-PyList_Append.c: ...here
(and added more tests).
* gcc.dg/plugin/cpython-plugin-test-1.c: Moved to...
* gcc.dg/plugin/cpython-plugin-test-no-Python-h.c: ...here (and
added more tests).
* gcc.dg/plugin/plugin.exp: New tests.
* gcc.dg/plugin/cpython-plugin-test-PyList_New.c: New test.
* gcc.dg/plugin/cpython-plugin-test-PyLong_FromLong.c: New test.
Signed-off-by: Eric Feng <ef2648@columbia.edu>
|
|
gcc/analyzer/ChangeLog:
* diagnostic-manager.cc (saved_diagnostic::add_event): New.
(saved_diagnostic::add_any_saved_events): New.
(diagnostic_manager::add_event): New.
(dedupe_winners::emit_best): New.
(diagnostic_manager::emit_saved_diagnostic): Make "sd" param
non-const. Call saved_diagnostic::add_any_saved_events.
* diagnostic-manager.h (saved_diagnostic::add_event): New decl.
(saved_diagnostic::add_any_saved_events): New decl.
(saved_diagnostic::m_saved_events): New field.
(diagnostic_manager::add_event): New decl.
(diagnostic_manager::emit_saved_diagnostic): Make "sd" param
non-const.
* engine.cc (impl_region_model_context::add_event): New.
* exploded-graph.h (impl_region_model_context::add_event): New decl.
* region-model.cc
(noop_region_model_context::add_event): New.
(region_model_context_decorator::add_event): New.
* region-model.h (region_model_context::add_event): New vfunc.
(noop_region_model_context::add_event): New decl.
(region_model_context_decorator::add_event): New decl.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
This patch updates poisoned_value_diagnostic so that, where possible,
it checks to see if the value is still poisoned along the execution
path seen during feasibility analysis, rather than just that seen
in the exploded graph.
Integration testing shows this reduction in the number of
false positives:
-Wanalyzer-use-of-uninitialized-value: 191 -> 153 (-38)
where the changes happen in:
coreutils-9.1: 34 -> 20 (-14)
qemu-7.2.0: 78 -> 54 (-24)
gcc/analyzer/ChangeLog:
PR analyzer/108664
PR analyzer/108666
PR analyzer/108725
* diagnostic-manager.cc (epath_finder::get_best_epath): Add
"target_stmt" param.
(epath_finder::explore_feasible_paths): Likewise.
(epath_finder::process_worklist_item): Likewise.
(saved_diagnostic::calc_best_epath): Pass m_stmt to
epath_finder::get_best_epath.
* engine.cc (feasibility_state::maybe_update_for_edge): Move
per-stmt logic to...
(feasibility_state::update_for_stmt): ...this new function.
* exploded-graph.h (feasibility_state::update_for_stmt): New decl.
* feasible-graph.cc (feasible_node::get_state_at_stmt): New.
* feasible-graph.h: Include "analyzer/exploded-graph.h".
(feasible_node::get_state_at_stmt): New decl.
* infinite-recursion.cc
(infinite_recursion_diagnostic::check_valid_fpath_p): Update for
vfunc signature change.
* pending-diagnostic.h (pending_diagnostic::check_valid_fpath_p):
Convert first param to a reference. Add stmt param.
* region-model.cc: Include "analyzer/feasible-graph.h".
(poisoned_value_diagnostic::poisoned_value_diagnostic): Add
"check_expr" param.
(poisoned_value_diagnostic::check_valid_fpath_p): New.
(poisoned_value_diagnostic::m_check_expr): New field.
(region_model::check_for_poison): Attempt to supply a check_expr
to the diagnostic
(region_model::deref_rvalue): Add NULL for new check_expr param
of poisoned_value_diagnostic.
(region_model::get_or_create_region_for_heap_alloc): Don't reuse
regions that are marked as TOUCHED.
gcc/testsuite/ChangeLog:
PR analyzer/108664
PR analyzer/108666
PR analyzer/108725
* gcc.dg/analyzer/coreutils-cksum-pr108664.c: New test.
* gcc.dg/analyzer/coreutils-sum-pr108666.c: New test.
* gcc.dg/analyzer/torture/uninit-pr108725.c: New test.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
|
|
This patch generalizes the analyzer's file descriptor state machine
so that it tracks the states of sockets.
It adds two new warnings relating to misuses of socket APIs:
* -Wanalyzer-fd-phase-mismatch (e.g. calling 'accept' on a socket
before calling 'listen' on it)
* -Wanalyzer-fd-type-mismatch (e.g. using a stream socket operation
on a datagram socket)
gcc/analyzer/ChangeLog:
PR analyzer/106140
* analyzer-language.cc (on_finish_translation_unit): Stash named
constants "SOCK_STREAM" and "SOCK_DGRAM".
* analyzer.opt (Wanalyzer-fd-phase-mismatch): New.
(Wanalyzer-fd-type-mismatch): New.
* engine.cc (impl_region_model_context::get_state_map_by_name):
Add "out_sm_context" param. Allow out_sm_idx to be NULL.
* exploded-graph.h
(impl_region_model_context::get_state_map_by_name):
Add "out_sm_context" param.
* region-model-impl-calls.cc (region_model::impl_call_accept): New.
(region_model::impl_call_bind): New.
(region_model::impl_call_connect): New.
(region_model::impl_call_listen): New.
(region_model::impl_call_socket): New.
* region-model.cc (region_model::on_call_pre): Special-case
"bind".
(region_model::on_call_post): Special-case "accept", "bind",
"connect", "listen", and "socket".
* region-model.h (region_model::impl_call_accept): New decl.
(region_model::impl_call_bind): New decl.
(region_model::impl_call_connect): New decl.
(region_model::impl_call_listen): New decl.
(region_model::impl_call_socket): New decl.
(region_model::on_socket): New decl.
(region_model::on_bind): New decl.
(region_model::on_listen): New decl.
(region_model::on_accept): New decl.
(region_model::on_connect): New decl.
(region_model::add_constraint): Make public.
(region_model::check_for_poison): Make public.
(region_model_context::get_state_map_by_name): Add out_sm_context param.
(region_model_context::get_fd_map): Likewise.
(region_model_context::get_malloc_map): Likewise.
(region_model_context::get_taint_map): Likewise.
(noop_region_model_context::get_state_map_by_name): Likewise.
(region_model_context_decorator::get_state_map_by_name): Likewise.
* sm-fd.cc: Include "analyzer/supergraph.h" and
"analyzer/analyzer-language.h".
(enum expected_phase): New enum.
(fd_state_machine::m_new_datagram_socket): New.
(fd_state_machine::m_new_stream_socket): New.
(fd_state_machine::m_new_unknown_socket): New.
(fd_state_machine::m_bound_datagram_socket): New.
(fd_state_machine::m_bound_stream_socket): New.
(fd_state_machine::m_bound_unknown_socket): New.
(fd_state_machine::m_listening_stream_socket): New.
(fd_state_machine::m_m_connected_stream_socket): New.
(fd_state_machine::m_SOCK_STREAM): New.
(fd_state_machine::m_SOCK_DGRAM): New.
(fd_diagnostic::describe_state_change): Handle socket states.
(fd_diagnostic::get_meaning_for_state_change): Likewise.
(class fd_phase_mismatch): New.
(enum expected_type): New enum.
(class fd_type_mismatch): New.
(fd_state_machine::fd_state_machine): Initialize new states and
stashed named constants.
(fd_state_machine::is_socket_fd_p): New.
(fd_state_machine::is_datagram_socket_fd_p): New.
(fd_state_machine::is_stream_socket_fd_p): New.
(fd_state_machine::on_close): Handle the socket states.
(fd_state_machine::check_for_open_fd): Complain about fncalls on
sockets in the wrong phase. Support socket FDs.
(add_constraint_ge_zero): New.
(fd_state_machine::get_state_for_socket_type): New.
(fd_state_machine::on_socket): New.
(fd_state_machine::check_for_socket_fd): New.
(fd_state_machine::check_for_new_socket_fd): New.
(fd_state_machine::on_bind): New.
(fd_state_machine::on_listen): New.
(fd_state_machine::on_accept): New.
(fd_state_machine::on_connect): New.
(fd_state_machine::can_purge_p): Don't purge socket values.
(get_fd_state): New.
(region_model::mark_as_valid_fd): Use get_fd_state.
(region_model::on_socket): New.
(region_model::on_bind): New.
(region_model::on_listen): New.
(region_model::on_accept): New.
(region_model::on_connect): New.
* sm-fd.dot: Update to reflect sm-fd.cc changes.
gcc/ChangeLog:
PR analyzer/106140
* doc/invoke.texi (Static Analyzer Options): Add
-Wanalyzer-fd-phase-mismatch and -Wanalyzer-fd-type-mismatch. Add
"socket", "bind", "listen", "accept", and "connect" to the list of
functions known to the analyzer.
gcc/testsuite/ChangeLog:
PR analyzer/106140
* gcc.dg/analyzer/fd-accept.c: New test.
* gcc.dg/analyzer/fd-bind.c: New test.
* gcc.dg/analyzer/fd-connect.c: New test.
* gcc.dg/analyzer/fd-datagram-socket.c: New test.
* gcc.dg/analyzer/fd-glibc-byte-stream-connection-server.c: New test.
* gcc.dg/analyzer/fd-glibc-byte-stream-socket.c: New test.
* gcc.dg/analyzer/fd-glibc-datagram-client.c: New test.
* gcc.dg/analyzer/fd-glibc-datagram-socket.c: New test.
* gcc.dg/analyzer/fd-glibc-make_named_socket.h: New test.
* gcc.dg/analyzer/fd-listen.c: New test.
* gcc.dg/analyzer/fd-manpage-getaddrinfo-client.c: New test.
* gcc.dg/analyzer/fd-mappage-getaddrinfo-server.c: New test.
* gcc.dg/analyzer/fd-socket-meaning.c: New test.
* gcc.dg/analyzer/fd-socket-misuse.c: New test.
* gcc.dg/analyzer/fd-stream-socket-active-open.c: New test.
* gcc.dg/analyzer/fd-stream-socket-passive-open.c: New test.
* gcc.dg/analyzer/fd-stream-socket.c: New test.
* gcc.dg/analyzer/fd-symbolic-socket.c: New test.
* gcc.dg/analyzer/pr104369-1.c: Add -Wno-analyzer-too-complex and
-Wno-analyzer-fd-leak to options.
* gcc.dg/analyzer/pr104369-2.c: Add -Wno-analyzer-fd-leak to
options.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
This patch adds a new -Wanalyzer-infinite-recursion warning to
-fanalyzer, which complains about certain cases of infinite recursion.
Specifically, when it detects recursion during its symbolic execution
of the user's code, it compares the state of memory to that at the
previous level of recursion, and if nothing appears to have effectively
changed, it issues a warning.
Unlike the middle-end warning -Winfinite-recursion (added by Martin
Sebor in GCC 12; r12-5483-g30ba058f77eedf), the analyzer warning
complains if there exists an interprocedural path in which recursion
occurs in which memory has not changed, whereas -Winfinite-recursion
complains if *every* intraprocedural path through the function leads to
a self-call.
Hence the warnings complement each other: there's some overlap, but each
also catches issues that the other misses.
For example, the new warning complains about a guarded recursion in
which the guard is passed unchanged:
void test_guarded (int flag)
{
if (flag)
test_guarded (flag);
}
t.c: In function 'test_guarded':
t.c:4:5: warning: infinite recursion [CWE-674] [-Wanalyzer-infinite-recursion]
4 | test_guarded (flag);
| ^~~~~~~~~~~~~~~~~~~
'test_guarded': events 1-4
|
| 1 | void test_guarded (int flag)
| | ^~~~~~~~~~~~
| | |
| | (1) initial entry to 'test_guarded'
| 2 | {
| 3 | if (flag)
| | ~
| | |
| | (2) following 'true' branch (when 'flag != 0')...
| 4 | test_guarded (flag);
| | ~~~~~~~~~~~~~~~~~~~
| | |
| | (3) ...to here
| | (4) calling 'test_guarded' from 'test_guarded'
|
+--> 'test_guarded': events 5-6
|
| 1 | void test_guarded (int flag)
| | ^~~~~~~~~~~~
| | |
| | (5) recursive entry to 'test_guarded'; previously entered at (1)
| | (6) apparently infinite recursion
|
whereas the existing warning doesn't complain, since when "flag" is
false the function doesn't recurse.
The new warning doesn't trigger for e.g.:
void test_param_variant (int depth)
{
if (depth > 0)
test_param_variant (depth - 1);
}
on the grounds that "depth" is changing, and appears to be a variant
that enforces termination of the recursion.
gcc/ChangeLog:
PR analyzer/106147
* Makefile.in (ANALYZER_OBJS): Add analyzer/infinite-recursion.o.
gcc/analyzer/ChangeLog:
PR analyzer/106147
* analyzer.opt (Wanalyzer-infinite-recursion): New.
* call-string.cc (call_string::count_occurrences_of_function):
New.
* call-string.h (call_string::count_occurrences_of_function): New
decl.
* checker-path.cc (function_entry_event::function_entry_event):
New ctor.
(checker_path::add_final_event): Delete.
* checker-path.h (function_entry_event::function_entry_event): New
ctor.
(function_entry_event::get_desc): Drop "final".
(checker_path::add_final_event): Delete.
* diagnostic-manager.cc
(diagnostic_manager::emit_saved_diagnostic): Create the final
event via a new pending_diagnostic::add_final_event vfunc, rather
than checker_path::add_final_event.
(diagnostic_manager::add_events_for_eedge): Create function entry
events via a new pending_diagnostic::add_function_entry_event
vfunc.
* engine.cc (exploded_graph::process_node): When creating a new
PK_BEFORE_SUPERNODE node, call
exploded_graph::detect_infinite_recursion on it after adding the
in-edge.
* exploded-graph.h (exploded_graph::detect_infinite_recursion):
New decl.
(exploded_graph::find_previous_entry_to): New decl.
* infinite-recursion.cc: New file.
* pending-diagnostic.cc
(pending_diagnostic::add_function_entry_event): New.
(pending_diagnostic::add_final_event): New.
* pending-diagnostic.h
(pending_diagnostic::add_function_entry_event): New vfunc.
(pending_diagnostic::add_final_event): New vfunc.
gcc/ChangeLog:
PR analyzer/106147
* doc/gcc/gcc-command-options/options-that-control-static-analysis.rst:
Add -Wanalyzer-infinite-recursion.
* doc/gcc/gcc-command-options/options-to-request-or-suppress-warnings.rst
(-Winfinite-recursion): Mention -Wanalyzer-infinite-recursion.
gcc/testsuite/ChangeLog:
PR analyzer/106147
* g++.dg/analyzer/infinite-recursion-1.C: New test.
* g++.dg/analyzer/infinite-recursion-2.C: New test, copied from
g++.dg/warn/Winfinite-recursion-2.C.
* g++.dg/analyzer/infinite-recursion-3.C: New test, adapted from
g++.dg/warn/Winfinite-recursion-3.C.
* gcc.dg/analyzer/infinite-recursion-2.c: New test.
* gcc.dg/analyzer/infinite-recursion-3.c: New test.
* gcc.dg/analyzer/infinite-recursion-4-limited-buggy.c: New test.
* gcc.dg/analyzer/infinite-recursion-4-limited.c: New test.
* gcc.dg/analyzer/infinite-recursion-4-unlimited-buggy.c: New test.
* gcc.dg/analyzer/infinite-recursion-4-unlimited.c: New test.
* gcc.dg/analyzer/infinite-recursion-5.c: New test, adapted from
gcc.dg/Winfinite-recursion.c.
* gcc.dg/analyzer/infinite-recursion-alloca.c: New test.
* gcc.dg/analyzer/infinite-recursion-inlining.c: New test.
* gcc.dg/analyzer/infinite-recursion-multiline-1.c: New test.
* gcc.dg/analyzer/infinite-recursion-multiline-2.c: New test.
* gcc.dg/analyzer/infinite-recursion-variadic.c: New test.
* gcc.dg/analyzer/infinite-recursion.c: Add dg-warning directives
where infinite recursions occur.
* gcc.dg/analyzer/malloc-ipa-12.c: Likewise.
* gcc.dg/analyzer/pr105365.c: Likewise.
* gcc.dg/analyzer/pr105366.c: Likewise.
* gcc.dg/analyzer/pr97029.c: Likewise.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
This patch implements a new -Wanalyzer-deref-before-check within
-fanalyzer. It complains about code paths in which a pointer is checked
for NULL after it has already been dereferenced.
For example, for the testcase in PR 77432 the diagnostic emits:
deref-before-check-1.c: In function 'test_from_pr77432':
deref-before-check-1.c:6:8: warning: check of 'a' for NULL after already dereferencing it [-Wanalyzer-deref-before-check]
6 | if (a)
| ^
'test_from_pr77432': events 1-2
|
| 5 | int b = *a;
| | ^
| | |
| | (1) pointer 'a' is dereferenced here
| 6 | if (a)
| | ~
| | |
| | (2) pointer 'a' is checked for NULL here but it was already dereferenced at (1)
|
and in PR 77425 we had an instance of this hidden behind a
macro, which the diagnostic complains about as follows:
deref-before-check-pr77425.c: In function 'get_odr_type':
deref-before-check-pr77425.c:35:10: warning: check of 'odr_types_ptr' for NULL after already dereferencing it [-Wanalyzer-deref-before-check]
35 | if (odr_types_ptr)
| ^
'get_odr_type': events 1-3
|
| 27 | if (cond)
| | ^
| | |
| | (1) following 'false' branch...
|......
| 31 | else if (other_cond)
| | ~~~~~~~~~~~
| | ||
| | |(2) ...to here
| | (3) following 'true' branch...
|
'get_odr_type': event 4
|
| 11 | #define odr_types (*odr_types_ptr)
| | ~^~~~~~~~~~~~~~~
| | |
| | (4) ...to here
deref-before-check-pr77425.c:33:7: note: in expansion of macro 'odr_types'
| 33 | odr_types[val->id] = 0;
| | ^~~~~~~~~
|
'get_odr_type': event 5
|
| 11 | #define odr_types (*odr_types_ptr)
| | ~^~~~~~~~~~~~~~~
| | |
| | (5) pointer 'odr_types_ptr' is dereferenced here
deref-before-check-pr77425.c:33:7: note: in expansion of macro 'odr_types'
| 33 | odr_types[val->id] = 0;
| | ^~~~~~~~~
|
'get_odr_type': event 6
|
| 35 | if (odr_types_ptr)
| | ^
| | |
| | (6) pointer 'odr_types_ptr' is checked for NULL here but it was already dereferenced at (5)
|
gcc/analyzer/ChangeLog:
PR analyzer/99671
* analyzer.opt (Wanalyzer-deref-before-check): New warning.
* diagnostic-manager.cc
(null_assignment_sm_context::set_next_state): Only add state
change events for transition to "null" state.
(null_assignment_sm_context::is_transition_to_null): New.
* engine.cc (impl_region_model_context::on_pop_frame): New.
* exploded-graph.h (impl_region_model_context::on_pop_frame): New
decl.
* program-state.cc (sm_state_map::clear_any_state): New.
(sm_state_map::can_merge_with_p): New.
(program_state::can_merge_with_p): Replace requirement that
sm-states be equal in favor of an attempt to merge them.
* program-state.h (sm_state_map::clear_any_state): New decl.
(sm_state_map::can_merge_with_p): New decl.
* region-model.cc (region_model::eval_condition): Make const.
(region_model::pop_frame): Call ctxt->on_pop_frame.
* region-model.h (region_model::eval_condition): Make const.
(region_model_context::on_pop_frame): New vfunc.
(noop_region_model_context::on_pop_frame): New.
(region_model_context_decorator::on_pop_frame): New.
* sm-malloc.cc (enum resource_state): Add RS_ASSUMED_NON_NULL.
(allocation_state::dump_to_pp): Drop "final".
(struct assumed_non_null_state): New subclass.
(malloc_state_machine::m_assumed_non_null): New.
(assumed_non_null_p): New.
(class deref_before_check): New.
(assumed_non_null_state::dump_to_pp): New.
(malloc_state_machine::get_or_create_assumed_non_null_state_for_frame):
New.
(malloc_state_machine::maybe_assume_non_null): New.
(malloc_state_machine::on_stmt): Transition from start state to
"assumed-non-null" state for pointers passed to
__attribute__((nonnull)) arguments, and for pointers explicitly
dereferenced. Call maybe_complain_about_deref_before_check for
pointers explicitly compared against NULL.
(malloc_state_machine::maybe_complain_about_deref_before_check):
New.
(malloc_state_machine::on_deallocator_call): Also transition
"assumed-non-null" states to "freed".
(malloc_state_machine::on_pop_frame): New.
(malloc_state_machine::maybe_get_merged_states_nonequal): New.
* sm-malloc.dot: Update for changes to sm-malloc.cc.
* sm.h (state_machine::on_pop_frame): New.
(state_machine::maybe_get_merged_state): New.
(state_machine::maybe_get_merged_states_nonequal): New.
gcc/ChangeLog:
* doc/gcc/gcc-command-options/options-that-control-static-analysis.rst:
Add -Wanalyzer-deref-before-check.
gcc/testsuite/ChangeLog:
* gcc.dg/analyzer/deref-before-check-1.c: New test.
* gcc.dg/analyzer/deref-before-check-2.c: New test.
* gcc.dg/analyzer/deref-before-check-pr77425.c: New test.
* gcc.dg/analyzer/malloc-1.c (test_51): New test.
gcc/ChangeLog:
PR analyzer/99671
* tristate.h (tristate::is_unknown): New.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
gcc/analyzer/ChangeLog:
* analysis-plan.cc: Define INCLUDE_MEMORY before including
system.h.
* analyzer-pass.cc: Likewise.
* analyzer-selftests.cc: Likewise.
* analyzer.cc: Likewise.
* analyzer.h: Use std::unique_ptr in bifurcation code.
* call-string.cc: Define INCLUDE_MEMORY before including system.h.
* complexity.cc: Likewise.
* engine.cc: Use std::unique_ptr in bifurcation code.
* exploded-graph.h: Likewise.
* known-function-manager.cc: Define INCLUDE_MEMORY before
including system.h.
* region-model-impl-calls.cc: Use std::unique_ptr in bifurcation
code.
* region-model.cc: Likewise.
* region-model.h: Likewise.
* supergraph.cc: Define INCLUDE_MEMORY before including system.h.
gcc/testsuite/ChangeLog:
* gcc.dg/plugin/analyzer_kernel_plugin.c: Include "make-unique.h".
Use std::unique_ptr in bifurcation code.
* gcc.dg/plugin/analyzer_known_fns_plugin.c: Likewise.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
gcc/analyzer/ChangeLog:
* diagnostic-manager.cc: Include "make-unique.h".
Use std::unique_ptr for feasibility_problems and exploded_path.
Delete explicit saved_diagnostic dtor.
* diagnostic-manager.h: Likewise.
* engine.cc: Likewise.
* exploded-graph.h: Likewise.
* feasible-graph.cc: Likewise.
* feasible-graph.h: Likewise.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
gcc/analyzer/ChangeLog:
* checker-path.cc (rewind_event::rewind_event): Update for usage of
std::unique_ptr on custom_edge_info.
* engine.cc (exploded_node::on_longjmp): Likewise.
(exploded_edge::exploded_edge): Likewise.
(exploded_edge::~exploded_edge): Delete.
(exploded_graph::add_function_entry): Update for usage of
std::unique_ptr on custom_edge_info.
(exploded_graph::add_edge): Likewise.
(add_tainted_args_callback): Likewise.
(exploded_graph::maybe_create_dynamic_call): Likewise.
(exploded_graph::process_node): Likewise.
* exploded-graph.h (exploded_edge::~exploded_edge): Delete.
(exploded_edge::m_custom_info): Use std::unique_ptr.
(exploded_edge::add_edge): Likewise.
* sm-signal.cc (register_signal_handler::impl_transition): Use
make_unique.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
gcc/analyzer/ChangeLog:
* diagnostic-manager.cc (saved_diagnostic::saved_diagnostic): Make
stmt_finder const.
(saved_diagnostic::~saved_diagnostic): Remove explicit delete of
m_stmt_finder.
(diagnostic_manager::add_diagnostic): Make stmt_finder const.
* diagnostic-manager.h (saved_diagnostic::saved_diagnostic):
Likewise.
(saved_diagnostic::m_stmt_finder): Convert to std::unique_ptr.
(diagnostic_manager::add_diagnostic): Make stmt_finder const.
* engine.cc (impl_sm_context::impl_sm_context): Likewise.
(impl_sm_context::m_stmt_finder): Likewise.
(leak_stmt_finder::clone): Convert return type to std::unique_ptr.
* exploded-graph.h (stmt_finder::clone): Likewise.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
gcc/analyzer/ChangeLog:
* call-info.cc: Add define of INCLUDE_MEMORY.
* call-summary.cc: Likewise.
* checker-path.cc: Likewise.
* constraint-manager.cc: Likewise.
* diagnostic-manager.cc: Likewise.
(saved_diagnostic::saved_diagnostic): Use std::unique_ptr for
param d and field m_d.
(saved_diagnostic::~saved_diagnostic): Remove explicit delete of m_d.
(saved_diagnostic::add_note): Use std::unique_ptr for
param pn.
(saved_diagnostic::get_pending_diagnostic): Update for conversion
of m_sd.m_d to unique_ptr.
(diagnostic_manager::add_diagnostic): Use std::unique_ptr for
param d. Remove explicit deletion.
(diagnostic_manager::add_note): Use std::unique_ptr for param pn.
(diagnostic_manager::emit_saved_diagnostic): Update for conversion
of m_sd.m_d to unique_ptr.
(null_assignment_sm_context::warn): Use std::unique_ptr for
param d. Remove explicit deletion.
* diagnostic-manager.h (saved_diagnostic::saved_diagnostic): Use
std::unique_ptr for param d.
(saved_diagnostic::add_note): Likewise for param pn.
(saved_diagnostic::m_d): Likewise.
(diagnostic_manager::add_diagnostic): Use std::unique_ptr for
param d.
(diagnostic_manager::add_note): Use std::unique_ptr for param pn.
* engine.cc: Include "make-unique.h".
(impl_region_model_context::warn): Update to use std::unique_ptr
for param, removing explicit deletion.
(impl_region_model_context::add_note): Likewise.
(impl_sm_context::warn): Update to use std::unique_ptr
for param.
(impl_region_model_context::on_state_leak): Likewise for result of
on_leak.
(exploded_node::on_longjmp): Use make_unique when creating
pending_diagnostic.
(exploded_graph::process_node): Likewise.
* exploded-graph.h (impl_region_model_context::warn): Update to
use std::unique_ptr for param.
(impl_region_model_context::add_note): Likewise.
* feasible-graph.cc: Add define of INCLUDE_MEMORY.
* pending-diagnostic.cc: Likewise.
* pending-diagnostic.h: Include analyzer.sm.h"
* program-point.cc: Add define of INCLUDE_MEMORY.
* program-state.cc: Likewise.
* region-model-asm.cc: Likewise.
* region-model-impl-calls.cc: Likewise. Include "make-unique.h".
(region_model::impl_call_putenv): Use make_unique when creating
pending_diagnostic.
* region-model-manager.cc: Add define of INCLUDE_MEMORY.
* region-model-reachability.cc: Likewise.
* region-model.cc: Likewise. Include "make-unique.h".
(region_model::get_gassign_result): Use make_unique when creating
pending_diagnostic.
(region_model::check_for_poison): Likewise.
(region_model::on_stmt_pre): Likewise.
(region_model::check_symbolic_bounds): Likewise.
(region_model::check_region_bounds): Likewise.
(annotating_ctxt: make_note): Use std::unique_ptr for result.
(region_model::deref_rvalue): Use make_unique when creating
pending_diagnostic.
(region_model::check_for_writable_region): Likewise.
(region_model::check_region_size): Likewise.
(region_model::check_dynamic_size_for_floats): Likewise.
(region_model::maybe_complain_about_infoleak): Likewise.
(noop_region_model_context::add_note): Use std::unique_ptr for
param. Remove explicit deletion.
* region-model.h: Include "analyzer/pending-diagnostic.h".
(region_model_context::warn): Convert param to std::unique_ptr.
(region_model_context::add_note): Likewise.
(noop_region_model_context::warn): Likewise.
(noop_region_model_context::add_note): Likewise.
(region_model_context_decorator::warn): Likewise.
(region_model_context_decorator::add_note): Likewise.
(note_adding_context::warn): Likewise.
(note_adding_context::make_note): Likewise for return type.
(test_region_model_context::warn): Convert param to
std::unique_ptr.
* region.cc: Add define of INCLUDE_MEMORY.
* sm-fd.cc: Likewise. Include "make-unique.h".
(fd_state_machine::check_for_fd_attrs): Use make_unique when
creating pending_diagnostics.
(fd_state_machine::on_open): Likewise.
(fd_state_machine::on_creat): Likewise.
(fd_state_machine::check_for_dup): Likewise.
(fd_state_machine::on_close): Likewise.
(fd_state_machine::check_for_open_fd): Likewise.
(fd_state_machine::on_leak): Likewise, converting return type to
std::unique_ptr.
* sm-file.cc: Add define of INCLUDE_MEMORY. Include
"make-unique.h".
(fileptr_state_machine::on_stmt): Use make_unique when creating
pending_diagnostic.
(fileptr_state_machine::on_leak): Likewise, converting return type
to std::unique_ptr.
* sm-malloc.cc: Add define of INCLUDE_MEMORY. Include
"make-unique.h".
(malloc_state_machine::on_stmt): Use make_unique when creating
pending_diagnostic.
(malloc_state_machine::handle_free_of_non_heap): Likewise.
(malloc_state_machine::on_deallocator_call): Likewise.
(malloc_state_machine::on_realloc_call): Likewise.
(malloc_state_machine::on_leak): Likewise, converting return type
to std::unique_ptr.
* sm-pattern-test.cc: Add define of INCLUDE_MEMORY. Include
"make-unique.h".
(pattern_test_state_machine::on_condition): Use make_unique when
creating pending_diagnostic.
* sm-sensitive.cc: Add define of INCLUDE_MEMORY. Include
"make-unique.h".
(sensitive_state_machine::warn_for_any_exposure): Use make_unique
when creating pending_diagnostic.
* sm-signal.cc: Add define of INCLUDE_MEMORY. Include
"make-unique.h".
(signal_state_machine::on_stmt): Use make_unique when creating
pending_diagnostic.
* sm-taint.cc: Add define of INCLUDE_MEMORY. Include
"make-unique.h".
(taint_state_machine::check_for_tainted_size_arg): Use make_unique
when creating pending_diagnostic.
(taint_state_machine::check_for_tainted_divisor): Likewise.
(region_model::check_region_for_taint): Likewise.
(region_model::check_dynamic_size_for_taint): Likewise.
* sm.cc: Add define of INCLUDE_MEMORY. Include
"analyzer/pending-diagnostic.h".
(state_machine::on_leak): Move here from sm.h, changing return
type to std::unique_ptr.
* sm.h (state_machine::on_leak): Change return type to
std::unique_ptr. Move defn of base impl to sm.cc
(sm_context::warn): Convert param d to std_unique_ptr.
* state-purge.cc: Add define of INCLUDE_MEMORY.
* store.cc: Likewise.
* svalue.cc: Likewise.
* trimmed-graph.cc: Likewise.
* varargs.cc: Likewise. Include "make-unique.h".
(va_list_state_machine::check_for_ended_va_list): Use make_unique
when creating pending_diagnostic.
(va_list_state_machine::on_leak): Likewise, converting return type
to std::unique_ptr.
(region_model::impl_call_va_arg): Use make_unique when creating
pending_diagnostic.
gcc/testsuite/ChangeLog:
* gcc.dg/plugin/analyzer_gil_plugin.c: Add define of
INCLUDE_MEMORY. Include "make-unique.h".
(gil_state_machine::check_for_pyobject_in_call): Use make_unique
when creating pending_diagnostic.
(gil_state_machine::on_stmt): Likewise.
(gil_state_machine::check_for_pyobject_usage_without_gil): Likewise.
* gcc.dg/plugin/analyzer_kernel_plugin.c: : Add define of
INCLUDE_MEMORY.
* gcc.dg/plugin/analyzer_known_fns_plugin.c: Likewise.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
gcc/analyzer/ChangeLog:
* engine.cc (impl_region_model_context::get_malloc_map): Replace
with...
(impl_region_model_context::get_state_map_by_name): ...this.
(impl_region_model_context::get_fd_map): Delete.
(impl_region_model_context::get_taint_map): Delete.
* exploded-graph.h (impl_region_model_context::get_fd_map):
Delete.
(impl_region_model_context::get_malloc_map): Delete.
(impl_region_model_context::get_taint_map): Delete.
(impl_region_model_context::get_state_map_by_name): New.
* region-model.h (region_model_context::get_state_map_by_name):
New vfunc.
(region_model_context::get_fd_map): Convert from vfunc to
function.
(region_model_context::get_malloc_map): Likewise.
(region_model_context::get_taint_map): Likewise.
(noop_region_model_context::get_state_map_by_name): New.
(noop_region_model_context::get_fd_map): Delete.
(noop_region_model_context::get_malloc_map): Delete.
(noop_region_model_context::get_taint_map): Delete.
(region_model_context_decorator::get_state_map_by_name): New.
(region_model_context_decorator::get_fd_map): Delete.
(region_model_context_decorator::get_malloc_map): Delete.
(region_model_context_decorator::get_taint_map): Delete.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
gcc/analyzer/ChangeLog:
PR analyzer/106300
* engine.cc (impl_region_model_context::get_fd_map): New.
* exploded-graph.h (impl_region_model_context::get_fd_map): New
decl.
* region-model-impl-calls.cc (region_model::impl_call_pipe): New.
* region-model.cc (region_model::update_for_int_cst_return): New,
based on...
(region_model::update_for_zero_return): ...this. Reimplement in
terms of the former.
(region_model::on_call_pre): Handle "pipe" and "pipe2".
(region_model::on_call_post): Likewise.
* region-model.h (region_model::impl_call_pipe): New decl.
(region_model::update_for_int_cst_return): New decl.
(region_model::mark_as_valid_fd): New decl.
(region_model_context::get_fd_map): New pure virtual fn.
(noop_region_model_context::get_fd_map): New.
(region_model_context_decorator::get_fd_map): New.
* sm-fd.cc: Include "analyzer/program-state.h".
(fd_state_machine::describe_state_change): Handle transitions from
start state to valid states.
(fd_state_machine::mark_as_valid_fd): New.
(fd_state_machine::on_stmt): Add missing return for "creat".
(region_model::mark_as_valid_fd): New.
gcc/ChangeLog:
PR analyzer/106300
* doc/invoke.texi (Static Analyzer Options): Add "pipe" and
"pipe2" to the list of functions the analyzer has hardcoded
knowledge of.
gcc/testsuite/ChangeLog:
PR analyzer/106300
* gcc.dg/analyzer/pipe-1.c: New test.
* gcc.dg/analyzer/pipe-glibc.c: New test.
* gcc.dg/analyzer/pipe-manpages.c: New test.
* gcc.dg/analyzer/pipe2-1.c: New test.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
Fixes:
gcc/analyzer/call-summary.h:103:13: warning: private field 'm_called_fn' is not used [-Wunused-private-field]
gcc/analyzer/engine.cc:1631:24: warning: unused parameter 'uncertainty' [-Wunused-parameter]
gcc/analyzer/ChangeLog:
* call-summary.cc (call_summary_replay::call_summary_replay):
Remove unused variable and arguments.
* call-summary.h: Likewise.
* engine.cc (exploded_node::on_stmt): Likewise.
(exploded_node::replay_call_summaries): Likewise.
(exploded_node::replay_call_summary): Likewise.
* exploded-graph.h (class exploded_node): Likewise.
|
|
With -fanalyzer-call-summaries the analyzer canl attempt to summarize
the effects of some function calls at their call site, rather than
simulate the call directly, which can avoid big slowdowns during
analysis.
Previously, this summarization was extremely simplistic: no attempt
was made to update sm-state, and region_model::update_for_call_summary
would simply set the return value of the function to UNKNOWN, and assume
the function had no side effects.
This patch implements less simplistic summarizations: it tracks each
possible return enode from the called function, and attempts to generate
a successor enode from the callsite for each that have compatible
conditions, mapping state changes in the summary to state changes
at the callsite. It also implements the beginnings of heuristics for
generating user-facing descriptions of a summary e.g.
"when 'foo' returns NULL"
versus:
"when 'foo' returns a heap-allocated buffer"
This still has some bugs, but much more accurately tracks the effects
of a call, and so is an improvement; it should only have an effect
when -fanalyzer-call-summaries is enabled.
As before, -fanalyzer-call-summaries is disabled by default in
analyzer.opt (but enabled by default in the test suite).
gcc/ChangeLog:
PR analyzer/107072
* Makefile.in (ANALYZER_OBJS): Add analyzer/call-summary.o.
gcc/analyzer/ChangeLog:
PR analyzer/107072
* analyzer-logging.h: Include "diagnostic-core.h".
* analyzer.h: Include "function.h".
(class call_summary): New forward decl.
(class call_summary_replay): New forward decl.
(struct per_function_data): New forward decl.
(struct interesting_t): New forward decl.
(custom_edge_info::update_state): New vfunc.
* call-info.cc (custom_edge_info::update_state): New.
* call-summary.cc: New file.
* call-summary.h: New file.
* constraint-manager.cc: Include "analyzer/call-summary.h".
(class replay_fact_visitor): New.
(constraint_manager::replay_call_summary): New.
* constraint-manager.h (constraint_manager::replay_call_summary):
New.
* engine.cc: Include "analyzer/call-summary.h".
(exploded_node::on_stmt): Handle call summaries.
(class call_summary_edge_info): New.
(exploded_node::replay_call_summaries): New.
(exploded_node::replay_call_summary): New.
(per_function_data::~per_function_data): New.
(per_function_data::add_call_summary): Move here from header and
reimplement.
(exploded_graph::process_node): Call update_state rather than
update_model when handling bifurcation
(viz_callgraph_node::dump_dot): Use a regular label rather
than an HTML table; add summaries to dump.
* exploded-graph.h: Include "alloc-pool.h", "fibonacci_heap.h",
"supergraph.h", "sbitmap.h", "shortest-paths.h", "analyzer/sm.h",
"analyzer/program-state.h", and "analyzer/diagnostic-manager.h".
(exploded_node::replay_call_summaries): New decl.
(exploded_node::replay_call_summary): New decl.
(per_function_data::~per_function_data): New decl.
(per_function_data::add_call_summary): Move implemention from
header.
(per_function_data::m_summaries): Update type of element.
* known-function-manager.h: Include "analyzer/analyzer-logging.h".
* program-point.h: Include "pretty-print.h" and
"analyzer/call-string.h".
* program-state.cc: Include "analyzer/call-summary.h".
(sm_state_map::replay_call_summary): New.
(program_state::replay_call_summary): New.
* program-state.h (sm_state_map::replay_call_summary): New decl.
(program_state::replay_call_summary): New decl.
* region-model-manager.cc
(region_model_manager::get_or_create_asm_output_svalue): New
overload.
* region-model-manager.h
(region_model_manager::get_or_create_asm_output_svalue): New
overload decl.
* region-model.cc: Include "analyzer/call-summary.h".
(region_model::maybe_update_for_edge): Remove call to
region_model::update_for_call_summary on
SUPEREDGE_INTRAPROCEDURAL_CALL.
(region_model::update_for_call_summary): Delete.
(region_model::replay_call_summary): New.
* region-model.h (region_model::replay_call_summary): New decl.
(region_model::update_for_call_summary): Delete decl.
* store.cc: Include "analyzer/call-summary.h".
(store::replay_call_summary): New.
(store::replay_call_summary_cluster): New.
* store.h: Include "tristate.h".
(is_a_helper <const ana::concrete_binding *>::test): New.
(store::replay_call_summary): New decl.
(store::replay_call_summary_cluster): New decl.
* supergraph.cc (get_ultimate_function_for_cgraph_edge): Remove
"static" from decl.
(supergraph_call_edge): Make stmt param const.
* supergraph.h: Include "ordered-hash-map.h", "cfg.h",
"basic-block.h", "gimple.h", "gimple-iterator.h", and "digraph.h".
(supergraph_call_edge): Make stmt param const.
(get_ultimate_function_for_cgraph_edge): New decl.
* svalue.cc (compound_svalue::compound_svalue): Assert that we're
not nesting compound_svalues.
* svalue.h: Include "json.h", "analyzer/store.h", and
"analyzer/program-point.h".
(asm_output_svalue::get_num_outputs): New accessor.
gcc/testsuite/ChangeLog:
PR analyzer/107072
* gcc.dg/analyzer/call-summaries-2.c: New test.
* gcc.dg/analyzer/call-summaries-3.c: New test.
* gcc.dg/analyzer/call-summaries-asm-x86.c: New test.
* gcc.dg/analyzer/call-summaries-malloc.c: New test.
* gcc.dg/analyzer/call-summaries-pr107072.c: New test.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
PR analyzer/106321 reports false positives from
-Wanalyzer-tainted-array-index on switch statements, seen e.g.
in the Linux kernel in drivers/vfio/pci/vfio_pci_core.c, where
vfio_pci_core_ioctl has:
| 744 | switch (info.index) {
| | ~~~~~~ ~~~~~~~~~~
| | | |
| | | (8) ...to here
| | (9) following ‘case 0 ... 5:’ branch...
|......
| 751 | case VFIO_PCI_BAR0_REGION_INDEX ... VFIO_PCI_BAR5_REGION_INDEX:
| | ~~~~
| | |
| | (10) ...to here
and then a false complaint about "use of attacker-controlled value
‘info.index’ in array lookup without upper-bounds checking", where
info.index has clearly had its bounds checked by the switch/case.
It turns out that when I rewrote switch handling for the analyzer in
r12-3101-g8ca7fa84a3af35, I removed notifications to state machines
about the constraints on cases.
This patch fixes that oversight by adding a new on_bounded_ranges vfunc
for region_model_context, called on switch statement edges, which calls
a new state_machine vfunc. It implements it for the "taint" state
machine, so that it updates the "has bounds" flags at out-edges for
switch statements, based on whether the bounds from the edge appear to
actually constrain the switch index.
gcc/analyzer/ChangeLog:
PR analyzer/106321
* constraint-manager.h (bounded_ranges::get_count): New.
(bounded_ranges::get_range): New.
* engine.cc (impl_region_model_context::on_bounded_ranges): New.
* exploded-graph.h (impl_region_model_context::on_bounded_ranges):
New decl.
* region-model.cc (region_model::apply_constraints_for_gswitch):
Potentially call ctxt->on_bounded_ranges.
* region-model.h (region_model_context::on_bounded_ranges): New
vfunc.
(noop_region_model_context::on_bounded_ranges): New.
(region_model_context_decorator::on_bounded_ranges): New.
* sm-taint.cc: Include "analyzer/constraint-manager.h".
(taint_state_machine::on_bounded_ranges): New.
* sm.h (state_machine::on_bounded_ranges): New.
gcc/testsuite/ChangeLog:
PR analyzer/106321
* gcc.dg/analyzer/torture/taint-read-index-2.c: Add test coverage
for switch statements.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
ana::call_string is a wrapper around an auto_vec of callsites, leading
to non-trivial copying when copying around call_string instances, e.g.
in ana::program_point.
This patch consolidates call_string instances within the
region_model_manager: it now owns the root/empty call_string, and
each call_string instance tracks its children, lazily creating them on
demand, so that the call_string instances form a tree-like hierarchy in
memory. Doing this requires passing the region_model_manager to the
various program_point factory methods, so that they can get at the root
call_string.
Instances of call_string become immutable (apart from their internal
cache for looking up their children); operations that previously
modified them now return the call_string for the result of the
operation.
I wasn't able to observe any performance impact of this, but it
simplifies call_string and program_point management, and thus I hope
will make it easier to improve call summarization. In particular,
region_model_manager::log_stats will now print a hierarchical dump of
all the call_string instances used in the analysis (in -fdump-analyzer
and -fdump-analyzer-stderr).
gcc/analyzer/ChangeLog:
* call-string.cc: Add includes of "analyzer/analyzer.h"
and "analyzer/analyzer-logging.h".
(call_string::call_string): Delete copy ctor.
(call_string::operator=): Delete.
(call_string::operator==): Delete.
(call_string::hash): Delete.
(call_string::push_call): Make const, returning the resulting
call_string.
(call_string::pop): Delete.
(call_string::cmp_ptr_ptr): New.
(call_string::validate): Assert that m_parent is non-NULL, or
m_elements is empty.
(call_string::call_string): Move default ctor here from
call-string.h and reimplement. Add ctor taking a parent
and an element.
(call_string::~call_string): New.
(call_string::recursive_log): New.
* call-string.h (call_string::call_string): Move default ctor's
defn to call-string.cc. Delete copy ctor. Add ctor taking a
parent and an element.
(call_string::operator=): Delete.
(call_string::operator==): Delete.
(call_string::hash): Delete.
(call_string::push_call): Make const, returning the resulting
call_string.
(call_string::pop): Delete decl.
(call_string::get_parent): New.
(call_string::cmp_ptr_ptr): New decl.
(call_string::get_top_of_stack): New.
(struct call_string::hashmap_traits_t): New.
(class call_string): Add friend class region_model_manager. Add
DISABLE_COPY_AND_ASSIGN.
(call_string::~call_string): New decl.
(call_string::recursive_log): New decl.
(call_string::m_parent): New field.
(call_string::m_children): New field.
* constraint-manager.cc (selftest::test_many_constants): Pass
model manager to program_point::origin.
* engine.cc (exploded_graph::exploded_graph): Likewise.
(exploded_graph::add_function_entry): Likewise for
program_point::from_function_entry.
(add_tainted_args_callback): Likewise.
(exploded_graph::maybe_process_run_of_before_supernode_enodes):
Update for change to program_point.get_call_string.
(exploded_graph::process_node): Likewise.
(class function_call_string_cluster): Convert m_cs from a
call_string to a const call_string &.
(struct function_call_string): Likewise.
(pod_hash_traits<function_call_string>::hash): Use pointer_hash
for m_cs.
(pod_hash_traits<function_call_string>::equal): Update for change
to m_cs.
(root_cluster::add_node): Update for change to
function_call_string.
(viz_callgraph_node::dump_dot): Update for change to call_string.
* exploded-graph.h (per_call_string_data::m_key): Convert to a
reference.
(struct eg_call_string_hash_map_traits): Delete.
(exploded_graph::call_string_data_map_t): Remove traits class.
* program-point.cc: Move include of "analyzer/call-string.h" to
after "analyzer/analyzer-logging.h".
(program_point::print): Update for conversion of m_call_string to
a pointer.
(program_point::to_json): Likewise.
(program_point::push_to_call_stack): Update for immutability of
call strings.
(program_point::pop_from_call_stack): Likewise.
(program_point::hash): Use pointer hashing for m_call_string.
(program_point::get_function_at_depth): Update for change to
m_call_string.
(program_point::validate): Update for changes to call_string.
(program_point::on_edge): Likewise.
(program_point::origin): Move here from call-string.h. Add
region_model_manager param and use it to get empty call string.
(program_point::from_function_entry): Likewise.
(selftest::test_function_point_ordering): Likewise.
(selftest::test_function_point_ordering): Likewise.
* program-point.h (program_point::program_point): Update for
change to m_call_string.
(program_point::get_call_string): Likewise.
(program_point::get_stack_depth): Likewise.
(program_point::origin): Add region_model_manager param, and move
defn to call-string.cc.
(program_point::from_function_entry): Likewise.
(program_point::empty): Drop call_string.
(program_point::deleted): Likewise.
(program_point::program_point): New private ctor.
(program_point::m_call_string): Convert from call_string to const
call_string *.
* program-state.cc (selftest::test_program_state_merging): Update
for call_string changes.
(selftest::test_program_state_merging_2): Likewise.
* region-model-manager.cc
(region_model_manager::region_model_manager): Construct
m_empty_call_string.
(region_model_manager::log_stats): Log the call strings.
* region-model.cc (assert_region_models_merge): Pass the
region_model_manager when creating program_point instances.
(selftest::test_state_merging): Likewise.
(selftest::test_constraint_merging): Likewise.
(selftest::test_widening_constraints): Likewise.
(selftest::test_iteration_1): Likewise.
* region-model.h (region_model_manager::get_empty_call_string):
New.
(region_model_manager::m_empty_call_string): New.
* sm-signal.cc (register_signal_handler::impl_transition): Update
for changes to call_string.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
As of GCC 11 onwards we have required a C++11 compiler, such as GCC 4.8
or later. On the assumption that any such compiler correctly implements
"final" and "override", this patch updates the source tree to stop using
the FINAL and OVERRIDE macros from ansidecl.h, in favor of simply using
"final" and "override" directly.
libcpp/ChangeLog:
* lex.cc: Replace uses of "FINAL" and "OVERRIDE" with "final" and
"override".
gcc/analyzer/ChangeLog:
* analyzer-pass.cc: Replace uses of "FINAL" and "OVERRIDE" with
"final" and "override".
* call-info.h: Likewise.
* checker-path.h: Likewise.
* constraint-manager.cc: Likewise.
* diagnostic-manager.cc: Likewise.
* engine.cc: Likewise.
* exploded-graph.h: Likewise.
* feasible-graph.h: Likewise.
* pending-diagnostic.h: Likewise.
* region-model-impl-calls.cc: Likewise.
* region-model.cc: Likewise.
* region-model.h: Likewise.
* region.h: Likewise.
* sm-file.cc: Likewise.
* sm-malloc.cc: Likewise.
* sm-pattern-test.cc: Likewise.
* sm-sensitive.cc: Likewise.
* sm-signal.cc: Likewise.
* sm-taint.cc: Likewise.
* state-purge.h: Likewise.
* store.cc: Likewise.
* store.h: Likewise.
* supergraph.h: Likewise.
* svalue.h: Likewise.
* trimmed-graph.h: Likewise.
* varargs.cc: Likewise.
gcc/c-family/ChangeLog:
* c-format.cc: Replace uses of "FINAL" and "OVERRIDE" with "final"
and "override".
* c-pretty-print.h: Likewise.
gcc/cp/ChangeLog:
* cxx-pretty-print.h: Replace uses of "FINAL" and "OVERRIDE" with
"final" and "override".
* error.cc: Likewise.
gcc/jit/ChangeLog:
* jit-playback.h: Replace uses of "FINAL" and "OVERRIDE" with
"final" and "override".
* jit-recording.cc: Likewise.
* jit-recording.h: Likewise.
gcc/ChangeLog:
* config/aarch64/aarch64-sve-builtins-base.cc: Replace uses of
"FINAL" and "OVERRIDE" with "final" and "override".
* config/aarch64/aarch64-sve-builtins-functions.h: Likewise.
* config/aarch64/aarch64-sve-builtins-shapes.cc: Likewise.
* config/aarch64/aarch64-sve-builtins-sve2.cc: Likewise.
* diagnostic-path.h: Likewise.
* digraph.cc: Likewise.
* gcc-rich-location.h: Likewise.
* gimple-array-bounds.cc: Likewise.
* gimple-loop-versioning.cc: Likewise.
* gimple-range-cache.cc: Likewise.
* gimple-range-cache.h: Likewise.
* gimple-range-fold.cc: Likewise.
* gimple-range-fold.h: Likewise.
* gimple-range-tests.cc: Likewise.
* gimple-range.h: Likewise.
* gimple-ssa-evrp.cc: Likewise.
* input.cc: Likewise.
* json.h: Likewise.
* read-rtl-function.cc: Likewise.
* tree-complex.cc: Likewise.
* tree-diagnostic-path.cc: Likewise.
* tree-ssa-ccp.cc: Likewise.
* tree-ssa-copy.cc: Likewise.
* tree-vrp.cc: Likewise.
* value-query.h: Likewise.
* vr-values.h: Likewise.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
I found this extension to -fdump-analyzer-feasibility very helpful when
debugging PR analyzer/105285.
gcc/analyzer/ChangeLog:
* diagnostic-manager.cc (epath_finder::process_worklist_item):
Call dump_feasible_path when a path that reaches the the target
enode is found.
(epath_finder::dump_feasible_path): New.
* engine.cc (feasibility_state::dump_to_pp): New.
* exploded-graph.h (feasibility_state::dump_to_pp): New decl.
* feasible-graph.cc (feasible_graph::dump_feasible_path): New.
* feasible-graph.h (feasible_graph::dump_feasible_path): New
decls.
* program-point.cc (function_point::print): Fix missing trailing
newlines.
* program-point.h (program_point::print_source_line): Remove
unimplemented decl.
gcc/ChangeLog:
* doc/invoke.texi (-fdump-analyzer-feasibility): Mention the
fpath.txt output.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
The previous patch extended
-Wanalyzer-write-to-const
-Wanalyzer-write-to-string-literal
to make use of __attribute__ ((access, ....), but the results could be
inscrutable.
This patch adds notes to such diagnostics to give the user a reason for
why the analyzer is complaining.
Example output:
test.c: In function 'main':
test.c:15:13: warning: write to string literal [-Wanalyzer-write-to-string-literal]
15 | if (getrandom((char *)test, sizeof(buf), GRND_RANDOM))
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
'main': event 1
|
| 15 | if (getrandom((char *)test, sizeof(buf), GRND_RANDOM))
| | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| | |
| | (1) write to string literal here
|
test.c:3:5: note: parameter 1 of 'getrandom' marked with attribute 'access (write_only, 1, 2)'
3 | int getrandom (void *__buffer, size_t __length,
| ^~~~~~~~~
Unfortunately we don't have location information for the attributes
themselves, just the function declaration, and there doesn't seem to be
a good way of getting at the location of the individual parameters from
the middle end (the C and C++ FEs both have get_fndecl_argument_location,
but the implementations are different).
gcc/analyzer/ChangeLog:
PR analyzer/104793
* analyzer.h (class pending_note): New forward decl.
* diagnostic-manager.cc (saved_diagnostic::saved_diagnostic):
Initialize m_notes.
(saved_diagnostic::operator==): Compare m_notes.
(saved_diagnostic::add_note): New.
(saved_diagnostic::emit_any_notes): New.
(diagnostic_manager::add_note): New.
(diagnostic_manager::emit_saved_diagnostic): Call emit_any_notes
after emitting the warning.
* diagnostic-manager.h (saved_diagnostic::add_note): New decl.
(saved_diagnostic::emit_any_notes): New decl.
(saved_diagnostic::m_notes): New field.
(diagnostic_manager::add_note): New decl.
* engine.cc (impl_region_model_context::add_note): New.
* exploded-graph.h (impl_region_model_context::add_note): New
decl.
* pending-diagnostic.h (class pending_note): New.
(class pending_note_subclass): New template.
* region-model.cc (class reason_attr_access): New.
(check_external_function_for_access_attr): Add class
annotating_ctxt and use it when checking region.
(noop_region_model_context::add_note): New.
* region-model.h (region_model_context::add_note): New vfunc.
(noop_region_model_context::add_note): New decl.
(class region_model_context_decorator): New.
(class note_adding_context): New.
gcc/testsuite/ChangeLog:
PR analyzer/104793
* gcc.dg/analyzer/write-to-const-2.c: Add dg-message directives
for expected notes.
* gcc.dg/analyzer/write-to-function-1.c: Likewise.
* gcc.dg/analyzer/write-to-string-literal-2.c: Likewise.
* gcc.dg/analyzer/write-to-string-literal-3.c: Likewise.
* gcc.dg/analyzer/write-to-string-literal-4.c: Likewise.
* gcc.dg/analyzer/write-to-string-literal-5.c: New test.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
There is false positive from -Wanalyzer-use-of-uninitialized-value on
gcc.dg/analyzer/pr102692.c here:
‘fix_overlays_before’: events 1-3
|
| 75 | while (tail
| | ~~~~
| 76 | && (tem = make_lisp_ptr (tail, 5),
| | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| | |
| | (1) following ‘false’ branch (when ‘tail’ is NULL)...
| 77 | (end = marker_position (XOVERLAY (tem)->end)) >= pos))
| | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|......
| 82 | if (!tail || end < prev || !tail->next)
| | ~~~~~ ~~~~~~~~~~
| | | |
| | | (3) use of uninitialized value ‘end’ here
| | (2) ...to here
|
The issue is that inner || of the conditionals have been folded within the
frontend from a chain of control flow:
5 │ if (tail == 0B) goto <D.1986>; else goto <D.1988>;
6 │ <D.1988>:
7 │ if (end < prev) goto <D.1986>; else goto <D.1989>;
8 │ <D.1989>:
9 │ _1 = tail->next;
10 │ if (_1 == 0B) goto <D.1986>; else goto <D.1987>;
11 │ <D.1986>:
to an OR expr (and then to a bitwise-or by the gimplifier):
5 │ _1 = tail == 0B;
6 │ _2 = end < prev;
7 │ _3 = _1 | _2;
8 │ if (_3 != 0) goto <D.1986>; else goto <D.1988>;
9 │ <D.1988>:
10 │ _4 = tail->next;
11 │ if (_4 == 0B) goto <D.1986>; else goto <D.1987>;
This happens for sufficiently simple conditionals in fold_truth_andor.
In particular, the (end < prev) is short-circuited without optimization,
but is evaluated with optimization, leading to the false positive.
Given how early this folding occurs, it seems the simplest fix is to
try to detect places where this optimization appears to have happened,
and suppress uninit warnings within the statement that would have
been short-circuited.
gcc/analyzer/ChangeLog:
PR analyzer/102692
* exploded-graph.h (impl_region_model_context::get_stmt): New.
* region-model.cc: Include "gimple-ssa.h", "tree-phinodes.h",
"tree-ssa-operands.h", and "ssa-iterators.h".
(within_short_circuited_stmt_p): New.
(region_model::check_for_poison): Don't warn about uninit values
if within_short_circuited_stmt_p.
* region-model.h (region_model_context::get_stmt): New vfunc.
(noop_region_model_context::get_stmt): New.
gcc/testsuite/ChangeLog:
PR analyzer/102692
* gcc.dg/analyzer/pr102692-2.c: New test.
* gcc.dg/analyzer/pr102692.c: Remove xfail. Remove -O2 from
options and move to...
* gcc.dg/analyzer/torture/pr102692.c: ...here.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
|
|
The initial commit of the analyzer in GCC 10 had a single warning,
-Wanalyzer-tainted-array-index
and required manually enabling the taint checker with
-fanalyzer-checker=taint (due to scaling issues).
This patch extends the taint detection to add four new taint-based
warnings:
-Wanalyzer-tainted-allocation-size
for e.g. attacker-controlled malloc/alloca
-Wanalyzer-tainted-divisor
for detecting where an attacker can inject a divide-by-zero
-Wanalyzer-tainted-offset
for attacker-controlled pointer offsets
-Wanalyzer-tainted-size
for e.g. attacker-controlled memset
and rewords all the warnings to talk about "attacker-controlled" values
rather than "tainted" values.
Unfortunately I haven't yet addressed the scaling issues, so all of
these still require -fanalyzer-checker=taint (in addition to -fanalyzer).
gcc/analyzer/ChangeLog:
* analyzer.opt (Wanalyzer-tainted-allocation-size): New.
(Wanalyzer-tainted-divisor): New.
(Wanalyzer-tainted-offset): New.
(Wanalyzer-tainted-size): New.
* engine.cc (impl_region_model_context::get_taint_map): New.
* exploded-graph.h (impl_region_model_context::get_taint_map):
New decl.
* program-state.cc (sm_state_map::get_state): Call
alt_get_inherited_state.
(sm_state_map::impl_set_state): Modify states within
compound svalues.
(program_state::impl_call_analyzer_dump_state): Undo casts.
(selftest::test_program_state_1): Update for new context param of
create_region_for_heap_alloc.
(selftest::test_program_state_merging): Likewise.
* region-model-impl-calls.cc (region_model::impl_call_alloca):
Likewise.
(region_model::impl_call_calloc): Likewise.
(region_model::impl_call_malloc): Likewise.
(region_model::impl_call_operator_new): Likewise.
(region_model::impl_call_realloc): Likewise.
* region-model.cc (region_model::check_region_access): Call
check_region_for_taint.
(region_model::get_representative_path_var_1): Handle binops.
(region_model::create_region_for_heap_alloc): Add "ctxt" param and
pass it to set_dynamic_extents.
(region_model::create_region_for_alloca): Likewise.
(region_model::set_dynamic_extents): Add "ctxt" param and use it
to call check_dynamic_size_for_taint.
(selftest::test_state_merging): Update for new context param of
create_region_for_heap_alloc.
(selftest::test_malloc_constraints): Likewise.
(selftest::test_malloc): Likewise.
(selftest::test_alloca): Likewise for create_region_for_alloca.
* region-model.h (region_model::create_region_for_heap_alloc): Add
"ctxt" param.
(region_model::create_region_for_alloca): Likewise.
(region_model::set_dynamic_extents): Likewise.
(region_model::check_dynamic_size_for_taint): New decl.
(region_model::check_region_for_taint): New decl.
(region_model_context::get_taint_map): New vfunc.
(noop_region_model_context::get_taint_map): New.
* sm-taint.cc: Remove include of "diagnostic-event-id.h"; add
includes of "gimple-iterator.h", "tristate.h", "selftest.h",
"ordered-hash-map.h", "cgraph.h", "cfg.h", "digraph.h",
"analyzer/supergraph.h", "analyzer/call-string.h",
"analyzer/program-point.h", "analyzer/store.h",
"analyzer/region-model.h", and "analyzer/program-state.h".
(enum bounds): Move to top of file.
(class taint_diagnostic): New.
(class tainted_array_index): Convert to subclass of taint_diagnostic.
(tainted_array_index::emit): Add CWE-129. Reword warning to use
"attacker-controlled" rather than "tainted".
(tainted_array_index::describe_state_change): Move to
taint_diagnostic::describe_state_change.
(tainted_array_index::describe_final_event): Reword to use
"attacker-controlled" rather than "tainted".
(class tainted_offset): New.
(class tainted_size): New.
(class tainted_divisor): New.
(class tainted_allocation_size): New.
(taint_state_machine::alt_get_inherited_state): New.
(taint_state_machine::on_stmt): In assignment handling, remove
ARRAY_REF handling in favor of check_region_for_taint. Add
detection of tainted divisors.
(taint_state_machine::get_taint): New.
(taint_state_machine::combine_states): New.
(region_model::check_region_for_taint): New.
(region_model::check_dynamic_size_for_taint): New.
* sm.h (state_machine::alt_get_inherited_state): New.
gcc/ChangeLog:
* doc/invoke.texi (Static Analyzer Options): Add
-Wno-analyzer-tainted-allocation-size,
-Wno-analyzer-tainted-divisor, -Wno-analyzer-tainted-offset, and
-Wno-analyzer-tainted-size to list. Add
-Wanalyzer-tainted-allocation-size, -Wanalyzer-tainted-divisor,
-Wanalyzer-tainted-offset, and -Wanalyzer-tainted-size to list
of options effectively enabled by -fanalyzer.
(-Wanalyzer-tainted-allocation-size): New.
(-Wanalyzer-tainted-array-index): Tweak wording; add link to CWE.
(-Wanalyzer-tainted-divisor): New.
(-Wanalyzer-tainted-offset): New.
(-Wanalyzer-tainted-size): New.
gcc/testsuite/ChangeLog:
* gcc.dg/analyzer/pr93382.c: Tweak expected wording.
* gcc.dg/analyzer/taint-alloc-1.c: New test.
* gcc.dg/analyzer/taint-alloc-2.c: New test.
* gcc.dg/analyzer/taint-divisor-1.c: New test.
* gcc.dg/analyzer/taint-1.c: Rename to...
* gcc.dg/analyzer/taint-read-index-1.c: ...this. Tweak expected
wording. Mark some events as xfail.
* gcc.dg/analyzer/taint-read-offset-1.c: New test.
* gcc.dg/analyzer/taint-size-1.c: New test.
* gcc.dg/analyzer/taint-write-index-1.c: New test.
* gcc.dg/analyzer/taint-write-offset-1.c: New test.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
Most of the state-management code in the analyzer involves
modifying state objects in-place, which implies a single outcome.
(I originally implemented in-place modification because I wanted
to avoid having to create copies of state objects, and it's now
very difficult to change this aspect of the analyzer's design)
However, there are various special-cases such as "realloc" for which
it's best to split the state into multiple outcomes.
This patch adds a mechanism for "bifurcating" the analysis in places
where there isn't a split in the CFG, and uses it to implement realloc,
in this case treating it as having 3 possible outcomes:
- failure, returning NULL
- success, growing the buffer in-place without moving it
- success, allocating a new buffer, copying the content of the old
buffer to it, and freeing the old buffer.
gcc/ChangeLog:
PR analyzer/99260
* Makefile.in (ANALYZER_OBJS): Add analyzer/call-info.o.
gcc/analyzer/ChangeLog:
PR analyzer/99260
* analyzer.h (class custom_edge_info): New class, adapted from
exploded_edge::custom_info_t. Make member functions const.
Make update_model return bool, converting edge param from
reference to a pointer, and adding a ctxt param.
(class path_context): New class.
* call-info.cc: New file.
* call-info.h: New file.
* engine.cc: Include "analyzer/call-info.h" and <memory>.
(impl_region_model_context::impl_region_model_context): Update for
new m_path_ctxt field.
(impl_region_model_context::bifurcate): New.
(impl_region_model_context::terminate_path): New.
(impl_region_model_context::get_malloc_map): New.
(impl_sm_context::impl_sm_context): Update for new m_path_ctxt
field.
(impl_sm_context::get_fndecl_for_call): Likewise.
(impl_sm_context::set_next_state): Likewise.
(impl_sm_context::warn): Likewise.
(impl_sm_context::is_zero_assignment): Likewise.
(impl_sm_context::get_path_context): New.
(impl_sm_context::m_path_ctxt): New.
(impl_region_model_context::on_condition): Update for new
path_ctxt param. Handle m_enode_for_diag being NULL.
(impl_region_model_context::on_phi): Update for new path_ctxt
param.
(exploded_node::on_stmt): Add path_ctxt param, updating ctor calls
to use it as necessary. Use it to bail out after sm-handling,
if needed.
(exploded_node::detect_leaks): Update for new path_ctxt param.
(dynamic_call_info_t::update_model): Update for conversion of
exploded_edge::custom_info_t to custom_edge_info.
(dynamic_call_info_t::add_events_to_path): Likewise.
(rewind_info_t::update_model): Likewise.
(rewind_info_t::add_events_to_path): Likewise.
(exploded_edge::exploded_edge): Likewise.
(exploded_graph::add_edge): Likewise.
(exploded_graph::maybe_process_run_of_before_supernode_enodes):
Update for new path_ctxt param.
(class impl_path_context): New.
(exploded_graph::process_node): Update for new path_ctxt param.
Create an impl_path_context and pass it to exploded_node::on_stmt.
Use it to terminate iterating stmts if terminate_path is called
on it. After processing a run of stmts, query path_ctxt to
potentially terminate the analysis path, and/or to "bifurcate" the
analysis into multiple additional paths.
(feasibility_state::maybe_update_for_edge): Update for new
update_model ctxt param.
* exploded-graph.h
(impl_region_model_context::impl_region_model_context): Add
path_ctxt param.
(impl_region_model_context::bifurcate): New.
(impl_region_model_context::terminate_path): New
(impl_region_model_context::get_ext_state): New.
(impl_region_model_context::get_malloc_map): New.
(impl_region_model_context::m_path_ctxt): New field.
(exploded_node::on_stmt): Add path_ctxt param.
(class exploded_edge::custom_info_t): Move to analyzer.h, renaming
to custom_edge_info, and making the changes as noted in analyzer.h
above.
(exploded_edge::exploded_edge): Update for these changes to
exploded_edge::custom_info_t.
(exploded_edge::m_custom_info): Likewise.
(class dynamic_call_info_t): Likewise.
(class rewind_info_t): Likewise.
(exploded_graph::add_edge): Likewise.
* program-state.cc (program_state::on_edge): Update for new
path_ctxt param.
(program_state::push_call): Likewise.
(program_state::returning_call): Likewise.
(program_state::prune_for_point): Likewise.
* region-model-impl-calls.cc: Include "analyzer/call-info.h".
(call_details::get_fndecl_for_call): New.
(region_model::impl_call_realloc): Reimplement.
* region-model.cc (region_model::on_call_pre): Move call to
impl_call_realloc to...
(region_model::on_call_post): ...here. Consolidate creation
of call_details instance.
(noop_region_model_context::bifurcate): New.
(noop_region_model_context::terminate_path): New.
* region-model.h (call_details::get_call_stmt): New.
(call_details::get_fndecl_for_call): New.
(region_model::on_realloc_with_move): New.
(region_model_context::bifurcate): New.
(region_model_context::terminate_path): New.
(region_model_context::get_ext_state): New.
(region_model_context::get_malloc_map): New.
(noop_region_model_context::bifurcate): New.
(noop_region_model_context::terminate_path): New.
(noop_region_model_context::get_ext_state): New.
(noop_region_model_context::get_malloc_map): New.
* sm-malloc.cc: Include "analyzer/program-state.h".
(malloc_state_machine::on_realloc_call): Reimplement.
(malloc_state_machine::on_realloc_with_move): New.
(region_model::on_realloc_with_move): New.
* sm-signal.cc (class signal_delivery_edge_info_t): Update for
conversion from exploded_edge::custom_info_t to custom_edge_info.
* sm.h (sm_context::get_path_context): New.
* svalue.cc (svalue::maybe_get_constant): Call
unwrap_any_unmergeable.
gcc/testsuite/ChangeLog:
PR analyzer/99260
* gcc.dg/analyzer/capacity-2.c: Update for changes to realloc
analysis.
* gcc.dg/analyzer/pr99193-1.c: Likewise.
* gcc.dg/analyzer/pr99193-3.c: Likewise.
* gcc.dg/analyzer/realloc-1.c: Likewise. Add test coverage for
realloc of non-heap pointer, realloc from mismatching allocator,
and realloc on a freed pointer.
* gcc.dg/analyzer/realloc-2.c: New test.
|
|
2021-08-19 Ankur Saini <arsenic@sourceware.org>
gcc/analyzer/ChangeLog:
PR analyzer/101980
* diagnostic-manager.cc
(diagnostic_manager::prune_for_sm_diagnostic)<case EK_CALL_EDGE>: Use
caller_model only when the supergraph_edge doesn't exixt.
(diagnostic_manager::prune_for_sm_diagnostic)<case EK_RETURN_EDGE>:
Likewise.
* engine.cc (exploded_graph::create_dynamic_call): Rename to...
(exploded_graph::maybe_create_dynamic_call): ...this, return call
creation status.
(exploded_graph::process_node): Handle calls which were not dynamically
discovered.
* exploded-graph.h (exploded_graph::create_dynamic_call): Rename to...
(exploded_graph::maybe_create_dynamic_call): ...this.
* region-model.cc (region_model::update_for_gcall): New param, use it
to push call to frame.
(region_model::update_for_call_superedge): Pass callee function to
update_for_gcall.
* region-model.h (region_model::update_for_gcall): New param.
gcc/testsuite/ChangeLog:
PR analyzer/101980
* gcc.dg/analyzer/function-ptr-2.c : Add issue for double 'free'.
* gcc.dg/analyzer/malloc-callbacks.c : Fix xfail testcase.
|
|
2021-07-29 Ankur Saini <arsenic@sourceware.org>
gcc/analyzer/ChangeLog:
PR analyzer/100546
* analysis-plan.cc (analysis_plan::use_summary_p): Don't use call
summaries if there is no callgraph edge
* checker-path.cc (call_event::call_event): Handle calls events that
are not represented by a supergraph call edge
(return_event::return_event): Likewise.
(call_event::get_desc): Work with new call_event structure.
(return_event::get_desc): Likeise.
* checker-path.h (call_event::m_src_snode): New field.
(call_event::m_dest_snode): New field.
(return_event::m_src_snode): New field.
(return_event::m_dest_snode): New field.
* diagnostic-manager.cc
(diagnostic_manager::prune_for_sm_diagnostic)<case EK_CALL_EDGE>:
Refactor to work with edges without callgraph edge.
(diagnostic_manager::prune_for_sm_diagnostic)<case EK_RETURN_EDGE>:
Likewise.
* engine.cc (dynamic_call_info_t::update_model): New function.
(dynamic_call_info_t::add_events_to_path): New function.
(exploded_graph::create_dynamic_call): New function.
(exploded_graph::process_node): Work with dynamically discovered calls.
* exploded-graph.h (class dynamic_call_info_t): New class.
(exploded_graph::create_dynamic_call): New decl.
* program-point.cc (program_point::push_to_call_stack): New function.
(program_point::pop_from_call_stack): New function.
* program-point.h (program_point::push_to_call_stack): New decl.
(program_point::pop_from_call_stack): New decl.
* program-state.cc (program_state::push_call): New function.
(program_state::returning_call): New function.
* program-state.h (program_state::push_call): New decl.
(program_state::returning_call): New decl.
* region-model.cc (region_model::update_for_gcall) New function.
(region_model::update_for_return_gcall): New function.
(egion_model::update_for_call_superedge): Get the underlying gcall and
update for gcall.
(region_model::update_for_return_superedge): Likewise.
* region-model.h (region_model::update_for_gcall): New decl.
(region_model::update_for_return_gcall): New decl.
* state-purge.cc (state_purge_per_ssa_name::process_point): Update to
work with calls without underlying cgraph edge.
* supergraph.cc (supergraph::supergraph) Split snodes at every callsite.
* supergraph.h (supernode::get_returning_call) New accessor.
gcc/testsuite/ChangeLog:
PR analyzer/100546
* gcc.dg/analyzer/function-ptr-4.c: New test.
* gcc.dg/analyzer/pr100546.c: New test.
|
|
The initial gcc 10 era commit of the analyzer (in
757bf1dff5e8cee34c0a75d06140ca972bfecfa7) had an implementation of
-Wanalyzer-use-of-uninitialized-value, but was sufficiently buggy
that I removed it in 78b9783774bfd3540f38f5b1e3c7fc9f719653d7 before
the release of gcc 10.1
This patch reintroduces the warning, heavily rewritten, with (I hope)
a less buggy implementation this time, for GCC 12.
gcc/analyzer/ChangeLog:
PR analyzer/95006
PR analyzer/94713
PR analyzer/94714
* analyzer.cc (maybe_reconstruct_from_def_stmt): Split out
GIMPLE_ASSIGN case into...
(get_diagnostic_tree_for_gassign_1): New.
(get_diagnostic_tree_for_gassign): New.
* analyzer.h (get_diagnostic_tree_for_gassign): New decl.
* analyzer.opt (Wanalyzer-write-to-string-literal): New.
* constraint-manager.cc (class svalue_purger): New.
(constraint_manager::purge_state_involving): New.
* constraint-manager.h
(constraint_manager::purge_state_involving): New.
* diagnostic-manager.cc (saved_diagnostic::supercedes_p): New.
(dedupe_winners::handle_interactions): New.
(diagnostic_manager::emit_saved_diagnostics): Call it.
* diagnostic-manager.h (saved_diagnostic::supercedes_p): New decl.
* engine.cc (impl_region_model_context::warn): Convert return type
to bool. Return false if the diagnostic isn't saved.
(impl_region_model_context::purge_state_involving): New.
(impl_sm_context::get_state): Use NULL ctxt when querying old
rvalue.
(impl_sm_context::set_next_state): Use new sval when querying old
state.
(class dump_path_diagnostic): Move to region-model.cc
(exploded_node::on_stmt): Move to on_stmt_pre and on_stmt_post.
Remove call to purge_state_involving.
(exploded_node::on_stmt_pre): New, based on the above. Move most
of it to region_model::on_stmt_pre.
(exploded_node::on_stmt_post): Likewise, moving to
region_model::on_stmt_post.
(class stale_jmp_buf): Fix parent class to use curiously recurring
template pattern.
(feasibility_state::maybe_update_for_edge): Call on_call_pre and
on_call_post on gcalls.
* exploded-graph.h (impl_region_model_context::warn): Return bool.
(impl_region_model_context::purge_state_involving): New decl.
(exploded_node::on_stmt_pre): New decl.
(exploded_node::on_stmt_post): New decl.
* pending-diagnostic.h (pending_diagnostic::use_of_uninit_p): New.
(pending_diagnostic::supercedes_p): New.
* program-state.cc (sm_state_map::get_state): Inherit state for
conjured_svalue as well as initial_svalue.
(sm_state_map::purge_state_involving): Also support SK_CONJURED.
* region-model-impl-calls.cc (call_details::get_uncertainty):
Handle m_ctxt being NULL.
(call_details::get_or_create_conjured_svalue): New.
(region_model::impl_call_fgets): New.
(region_model::impl_call_fread): New.
* region-model-manager.cc
(region_model_manager::get_or_create_initial_value): Return an
uninitialized poisoned value for regions that can't have initial
values.
* region-model-reachability.cc
(reachable_regions::mark_escaped_clusters): Handle ctxt being
NULL.
* region-model.cc (region_to_value_map::purge_state_involving): New.
(poisoned_value_diagnostic::use_of_uninit_p): New.
(poisoned_value_diagnostic::emit): Handle POISON_KIND_UNINIT.
(poisoned_value_diagnostic::describe_final_event): Likewise.
(region_model::check_for_poison): New.
(region_model::on_assignment): Call it.
(class dump_path_diagnostic): Move here from engine.cc.
(region_model::on_stmt_pre): New, based on exploded_node::on_stmt.
(region_model::on_call_pre): Move the setting of the LHS to a
conjured svalue to before the checks for specific functions.
Handle "fgets", "fgets_unlocked", and "fread".
(region_model::purge_state_involving): New.
(region_model::handle_unrecognized_call): Handle ctxt being NULL.
(region_model::get_rvalue): Call check_for_poison.
(selftest::test_stack_frames): Use NULL for context when getting
uninitialized rvalue.
(selftest::test_alloca): Likewise.
* region-model.h (region_to_value_map::purge_state_involving): New
decl.
(call_details::get_or_create_conjured_svalue): New decl.
(region_model::on_stmt_pre): New decl.
(region_model::purge_state_involving): New decl.
(region_model::impl_call_fgets): New decl.
(region_model::impl_call_fread): New decl.
(region_model::check_for_poison): New decl.
(region_model_context::warn): Return bool.
(region_model_context::purge_state_involving): New.
(noop_region_model_context::warn): Return bool.
(noop_region_model_context::purge_state_involving): New.
(test_region_model_context:: warn): Return bool.
* region.cc (region::get_memory_space): New.
(region::can_have_initial_svalue_p): New.
(region::involves_p): New.
* region.h (enum memory_space): New.
(region::get_memory_space): New decl.
(region::can_have_initial_svalue_p): New decl.
(region::involves_p): New decl.
* sm-malloc.cc (use_after_free::supercedes_p): New.
* store.cc (binding_cluster::purge_state_involving): New.
(store::purge_state_involving): New.
* store.h (class symbolic_binding): New forward decl.
(binding_key::dyn_cast_symbolic_binding): New.
(symbolic_binding::dyn_cast_symbolic_binding): New.
(binding_cluster::purge_state_involving): New.
(store::purge_state_involving): New.
* svalue.cc (svalue::can_merge_p): Reject attempts to merge
poisoned svalues with other svalues, so that we identify
paths in which a variable is conditionally uninitialized.
(involvement_visitor::visit_conjured_svalue): New.
(svalue::involves_p): Also handle SK_CONJURED.
(poison_kind_to_str): Handle POISON_KIND_UNINIT.
(poisoned_svalue::maybe_fold_bits_within): New.
* svalue.h (enum poison_kind): Add POISON_KIND_UNINIT.
(poisoned_svalue::maybe_fold_bits_within): New decl.
gcc/ChangeLog:
PR analyzer/95006
PR analyzer/94713
PR analyzer/94714
* doc/invoke.texi: Add -Wanalyzer-use-of-uninitialized-value.
gcc/testsuite/ChangeLog:
PR analyzer/95006
PR analyzer/94713
PR analyzer/94714
* g++.dg/analyzer/pr93212.C: Update location of warning.
* g++.dg/analyzer/pr94011.C: Add
-Wno-analyzer-use-of-uninitialized-value.
* g++.dg/analyzer/pr94503.C: Likewise.
* gcc.dg/analyzer/clobbers-1.c: Convert "f" from a local to a
param to avoid uninitialized warning.
* gcc.dg/analyzer/data-model-1.c (test_12): Add test for
uninitialized value on result of alloca.
(test_12a): Add expected warning.
(test_12c): Likewise.
(test_19): Likewise.
(test_29b): Likewise.
(test_29c): Likewise.
(test_37): Remove xfail.
(test_37a): Likewise.
* gcc.dg/analyzer/data-model-20.c: Add warning about leak.
* gcc.dg/analyzer/explode-2.c: Remove params; add
-Wno-analyzer-too-complex, -Wno-analyzer-malloc-leak, and xfails.
Initialize the locals.
* gcc.dg/analyzer/explode-2a.c: Initialize the locals. Add
expected leak.
* gcc.dg/analyzer/fgets-1.c: New test.
* gcc.dg/analyzer/fread-1.c: New test.
* gcc.dg/analyzer/malloc-1.c (test_16): Add expected warning.
(test_40): Likewise.
* gcc.dg/analyzer/memset-CVE-2017-18549-1.c: Check for
uninitialized padding.
* gcc.dg/analyzer/pr93355-localealias-feasibility.c (fread): New
decl.
(read_alias_file): Call it.
* gcc.dg/analyzer/pr94047.c: Add expected warnings.
* gcc.dg/analyzer/pr94851-2.c: Likewise.
* gcc.dg/analyzer/pr96841.c: Convert local to a param.
* gcc.dg/analyzer/pr98628.c: Likewise.
* gcc.dg/analyzer/pr99042.c: Updated expected location of leak
diagnostics.
* gcc.dg/analyzer/symbolic-1.c: Add expected warnings.
* gcc.dg/analyzer/symbolic-7.c: Likewise.
* gcc.dg/analyzer/torture/pr93649.c: Add expected warning. Skip
with -fno-fat-lto-objects.
* gcc.dg/analyzer/uninit-1.c: New test.
* gcc.dg/analyzer/uninit-2.c: New test.
* gcc.dg/analyzer/uninit-3.c: New test.
* gcc.dg/analyzer/uninit-4.c: New test.
* gcc.dg/analyzer/uninit-pr94713.c: New test.
* gcc.dg/analyzer/uninit-pr94714.c: New test.
* gcc.dg/analyzer/use-after-free-2.c: New test.
* gcc.dg/analyzer/use-after-free-3.c: New test.
* gcc.dg/analyzer/zlib-3.c: Add expected warning.
* gcc.dg/analyzer/zlib-6.c: Convert locals to params to avoid
uninitialized warnings. Remove xfail.
* gcc.dg/analyzer/zlib-6a.c: New test, based on the old version
of the above.
* gfortran.dg/analyzer/pr97668.f: Add
-Wno-analyzer-use-of-uninitialized-value and
-Wno-analyzer-too-complex.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
gcc/analyzer/ChangeLog:
* analyzer.opt (fdump-analyzer-exploded-paths): New.
* diagnostic-manager.cc
(diagnostic_manager::emit_saved_diagnostic): Implement it.
* engine.cc (exploded_path::dump_to_pp): Add ext_state param and
use it to dump states if non-NULL.
(exploded_path::dump): Likewise.
(exploded_path::dump_to_file): New.
* exploded-graph.h (exploded_path::dump_to_pp): Add ext_state
param.
(exploded_path::dump): Likewise.
(exploded_path::dump): Likewise.
(exploded_path::dump_to_file): New.
gcc/ChangeLog:
* doc/invoke.texi (-fdump-analyzer-exploded-paths): New.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
I'm working on reimplementing -Wanalyzer-use-of-uninitialized-value, but
I ran into issues with
region_model::add_any_constraints_from_ssa_def_stmt.
This function is from the initial commit of the analyzer and walks the
SSA names finding conditions that were missed due to the GCC 10 era
region_model not retaining useful information on how values were
created; as of GCC 11 the symbolic values contain this information,
and so the conditions can be reconstructed from them instead.
region_model::add_any_constraints_from_ssa_def_stmt is a liability
when tracking uninitialized values as it requires looking up SSA
values when those values may have been purged, thus greatly complicating
detection of uses of uninitialized values.
It's simplest to eliminate it and reimplement the condition-finding
via the makeup of the svalues, which this patch does. Doing so requires
supporting add_condition on svalues rather than just on trees, which
requires some changes to ana::state_machine and its subclasses.
gcc/analyzer/ChangeLog:
* diagnostic-manager.cc (null_assignment_sm_context::get_state):
New overload.
(null_assignment_sm_context::set_next_state): New overload.
(null_assignment_sm_context::get_diagnostic_tree): New.
* engine.cc (impl_sm_context::get_state): New overload.
(impl_sm_context::set_next_state): New overload.
(impl_sm_context::get_diagnostic_tree): New overload.
(impl_region_model_context::on_condition): Convert params from
tree to const svalue *.
* exploded-graph.h (impl_region_model_context::on_condition):
Likewise.
* region-model.cc (region_model::on_call_pre): Move handling of
internal calls to before checking for get_fndecl_for_call.
(region_model::add_constraints_from_binop): New.
(region_model::add_constraint): Split out into a new overload
working on const svalue * rather than tree. Call
add_constraints_from_binop. Drop call to
add_any_constraints_from_ssa_def_stmt.
(region_model::add_any_constraints_from_ssa_def_stmt): Delete.
(region_model::add_any_constraints_from_gassign): Delete.
(region_model::add_any_constraints_from_gcall): Delete.
* region-model.h
(region_model::add_any_constraints_from_ssa_def_stmt): Delete.
(region_model::add_any_constraints_from_gassign): Delete.
(region_model::add_any_constraints_from_gcall): Delete.
(region_model::add_constraint): Add overload decl.
(region_model::add_constraints_from_binop): New decl.
(region_model_context::on_condition): Convert params from tree to
const svalue *.
(noop_region_model_context::on_condition): Likewise.
* sm-file.cc (fileptr_state_machine::condition): Likewise.
* sm-malloc.cc (malloc_state_machine::on_condition): Likewise.
* sm-pattern-test.cc: Include tristate.h, selftest.h,
analyzer/call-string.h, analyzer/program-point.h,
analyzer/store.h, and analyzer/region-model.h.
(pattern_test_state_machine::on_condition): Convert params from tree to
const svalue *.
* sm-sensitive.cc (sensitive_state_machine::on_condition): Delete.
* sm-signal.cc (signal_state_machine::on_condition): Delete.
* sm-taint.cc (taint_state_machine::on_condition): Convert params
from tree to const svalue *.
* sm.cc: Include tristate.h, selftest.h, analyzer/call-string.h,
analyzer/program-point.h, analyzer/store.h, and
analyzer/region-model.h.
(any_pointer_p): Add overload taking const svalue *sval.
* sm.h (any_pointer_p): Add overload taking const svalue *sval.
(state_machine::on_condition): Convert params from tree to
const svalue *. Provide no-op default implementation.
(sm_context::get_state): Add overload taking const svalue *sval.
(sm_context::set_next_state): Likewise.
(sm_context::on_transition): Likewise.
(sm_context::get_diagnostic_tree): Likewise.
* svalue.cc (svalue::all_zeroes_p): New.
(constant_svalue::all_zeroes_p): New.
(repeated_svalue::all_zeroes_p): Convert to vfunc.
* svalue.h (svalue::all_zeroes_p): New decl.
(constant_svalue::all_zeroes_p): New decl.
(repeated_svalue::all_zeroes_p): Convert decl to vfunc.
gcc/testsuite/ChangeLog:
* gcc.dg/analyzer/pattern-test-2.c: Update expected results.
* gcc.dg/plugin/analyzer_gil_plugin.c
(gil_state_machine::on_condition): Remove.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
This patch extends region_model to add tracking of the sizes of
dynamically-allocated regions, both on the heap (via malloc etc) and
stack (via alloca). It adds enough purging of this state to avoid
blowing up any existing analyzer test cases.
The state can be queried via a new "__analyzer_dump_capacity" for use
in DejaGnu tests but other than that doesn't do anything - I have
various followup experiments that make use of this.
gcc/analyzer/ChangeLog:
* engine.cc (exploded_node::on_stmt): Handle __analyzer_dump_capacity.
(exploded_node::on_stmt): Drop m_sm_changes from on_stmt_flags.
(state_change_requires_new_enode_p): New function...
(exploded_graph::process_node): Call it, rather than querying
flags.m_sm_changes, so that dynamic-extent differences can also
trigger the splitting of nodes.
* exploded-graph.h (struct on_stmt_flags): Drop field m_sm_changes.
* program-state.cc (program_state::detect_leaks): Purge dead
heap-allocated regions from dynamic extents.
(selftest::test_program_state_1): Fix type of "size_in_bytes".
(selftest::test_program_state_merging): Likewise.
* region-model-impl-calls.cc
(region_model::impl_call_analyzer_dump_capacity): New.
(region_model::impl_call_free): Remove dynamic extents from the
freed region.
* region-model-reachability.h
(reachable_regions::begin_mutable_base_regs): New.
(reachable_regions::end_mutable_base_regs): New.
* region-model.cc: Include "tree-object-size.h".
(region_model::region_model): Support new field m_dynamic_extents.
(region_model::operator=): Likewise.
(region_model::operator==): Likewise.
(region_model::dump_to_pp): Dump sizes of dynamic regions.
(region_model::handle_unrecognized_call): Purge dynamic extents
from any regions that have escaped mutably:.
(region_model::get_capacity): New function.
(region_model::add_constraint): Unset dynamic extents when a
heap-allocated region's address is NULL.
(region_model::unbind_region_and_descendents): Purge dynamic
extents of unbound regions.
(region_model::can_merge_with_p): Call
m_dynamic_extents.can_merge_with_p.
(region_model::create_region_for_heap_alloc): Assert that
size_in_bytes's type is compatible with size_type_node. Update
for renaming of record_dynamic_extents to set_dynamic_extents.
(region_model::create_region_for_alloca): Likewise.
(region_model::record_dynamic_extents): Rename to...
(region_model::set_dynamic_extents): ...this. Assert that
size_in_bytes's type is compatible with size_type_node. Add it
to the m_dynamic_extents map.
(region_model::get_dynamic_extents): New.
(region_model::unset_dynamic_extents): New.
(selftest::test_state_merging): Fix type of "size".
(selftest::test_malloc_constraints): Likewise.
(selftest::test_malloc): Verify dynamic extents.
(selftest::test_alloca): Likewise.
* region-model.h (region_to_value_map::is_empty): New.
(region_model::dynamic_extents_t): New typedef.
(region_model::impl_call_analyzer_dump_capacity): New decl.
(region_model::get_dynamic_extents): New function.
(region_model::get_dynamic_extents): New decl.
(region_model::set_dynamic_extents): New decl.
(region_model::unset_dynamic_extents): New decl.
(region_model::get_capacity): New decl.
(region_model::record_dynamic_extents): Rename to set_dynamic_extents.
(region_model::m_dynamic_extents): New field.
gcc/ChangeLog:
* doc/analyzer.texi
(Special Functions for Debugging the Analyzer): Add
__analyzer_dump_capacity.
gcc/testsuite/ChangeLog:
* gcc.dg/analyzer/analyzer-decls.h (__analyzer_dump_capacity): New decl.
* gcc.dg/analyzer/capacity-1.c: New test.
* gcc.dg/analyzer/capacity-2.c: New test.
* gcc.dg/analyzer/capacity-3.c: New test.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
Prior to this patch, program_state::detect_leaks worked by finding all
live svalues in the old state and in the new state, and calling
on_svalue_leak for each svalue that has changed from being live to
not being live.
PR analyzer/99042 and PR analyzer/99774 both describe false leak
diagnostics from -fanalyzer (a false FILE * leak in git, and a false
malloc leak in qemu, respectively).
In both cases the root cause of the false leak diagnostic relates to
svalues no longer being explicitly bound in the store due to regions
being conservatively clobbered, due to an unknown function being
called, or due to a write through a pointer that could alias the
region, respectively.
We have a transition from an svalue being explicitly live to not
being explicitly live - but only because the store is being
conservative, clobbering the binding. The leak detection is looking
for transitions from "definitely live" to "not definitely live",
when it should be looking for transitions from "definitely live"
to "definitely not live".
This patch introduces a new class to temporarily capture information
about svalues that were explicitly live, but for which a region bound
to them got clobbered for conservative reasons. This new
"uncertainty_t" class is passed around to capture the data long enough
for use in program_state::detect_leaks, where it is used to only
complain about svalues that were definitely live and are now both
not definitely live *or* possibly-live i.e. definitely not-live.
The class also captures for which svalues we can't meaningfully track
sm-state anymore, and resets the svalues back to the "start" state.
Together, these changes fix the false leak reports.
gcc/analyzer/ChangeLog:
PR analyzer/99042
PR analyzer/99774
* engine.cc
(impl_region_model_context::impl_region_model_context): Add
uncertainty param and use it to initialize m_uncertainty.
(impl_region_model_context::get_uncertainty): New.
(impl_sm_context::get_fndecl_for_call): Add NULL for new
uncertainty param when constructing impl_region_model_context.
(impl_sm_context::get_state): Likewise.
(impl_sm_context::set_next_state): Likewise.
(impl_sm_context::warn): Likewise.
(exploded_node::on_stmt): Add uncertainty param
and use it when constructing impl_region_model_context.
(exploded_node::on_edge): Add uncertainty param and pass
to on_edge call.
(exploded_node::detect_leaks): Create uncertainty_t and pass to
impl_region_model_context.
(exploded_graph::get_or_create_node): Create uncertainty_t and
pass to prune_for_point.
(maybe_process_run_of_before_supernode_enodes): Create
uncertainty_t and pass to impl_region_model_context.
(exploded_graph::process_node): Create uncertainty_t instances and
pass around as needed.
* exploded-graph.h
(impl_region_model_context::impl_region_model_context): Add
uncertainty param.
(impl_region_model_context::get_uncertainty): New decl.
(impl_region_model_context::m_uncertainty): New field.
(exploded_node::on_stmt): Add uncertainty param.
(exploded_node::on_edge): Likewise.
* program-state.cc (sm_state_map::on_liveness_change): Get
uncertainty from context and use it to unset sm-state from
svalues as appropriate.
(program_state::on_edge): Add uncertainty param and use it when
constructing impl_region_model_context. Fix indentation.
(program_state::prune_for_point): Add uncertainty param and use it
when constructing impl_region_model_context.
(program_state::detect_leaks): Get any uncertainty from ctxt and
use it to get maybe-live svalues for dest_state, rather than
definitely-live ones; use this when determining which svalues
have leaked.
(selftest::test_program_state_merging): Create uncertainty_t and
pass to impl_region_model_context.
* program-state.h (program_state::on_edge): Add uncertainty param.
(program_state::prune_for_point): Likewise.
* region-model-impl-calls.cc (call_details::get_uncertainty): New.
(region_model::impl_call_memcpy): Pass uncertainty to
mark_region_as_unknown call.
(region_model::impl_call_memset): Likewise.
(region_model::impl_call_strcpy): Likewise.
* region-model-reachability.cc (reachable_regions::handle_sval):
Also add sval to m_mutable_svals.
* region-model.cc (region_model::on_assignment): Pass any
uncertainty from ctxt to the store::set_value call.
(region_model::handle_unrecognized_call): Get any uncertainty from
ctxt and use it to record mutable svalues at the unknown call.
(region_model::get_reachable_svalues): Add uncertainty param and
use it to mark any maybe-bound svalues as being reachable.
(region_model::set_value): Pass any uncertainty from ctxt to the
store::set_value call.
(region_model::mark_region_as_unknown): Add uncertainty param and
pass it on to the store::mark_region_as_unknown call.
(region_model::update_for_call_summary): Add uncertainty param and
pass it on to the region_model::mark_region_as_unknown call.
* region-model.h (call_details::get_uncertainty): New decl.
(region_model::get_reachable_svalues): Add uncertainty param.
(region_model::mark_region_as_unknown): Add uncertainty param.
(region_model_context::get_uncertainty): New vfunc.
(noop_region_model_context::get_uncertainty): New vfunc
implementation.
* store.cc (dump_svalue_set): New.
(uncertainty_t::dump_to_pp): New.
(uncertainty_t::dump): New.
(binding_cluster::clobber_region): Pass NULL for uncertainty to
remove_overlapping_bindings.
(binding_cluster::mark_region_as_unknown): Add uncertainty param
and pass it to remove_overlapping_bindings.
(binding_cluster::remove_overlapping_bindings): Add uncertainty param.
Use it to record any svalues that were in clobbered bindings.
(store::set_value): Add uncertainty param. Pass it to
binding_cluster::mark_region_as_unknown when handling symbolic
regions.
(store::mark_region_as_unknown): Add uncertainty param and pass it
to binding_cluster::mark_region_as_unknown.
(store::remove_overlapping_bindings): Add uncertainty param and
pass it to binding_cluster::remove_overlapping_bindings.
* store.h (binding_cluster::mark_region_as_unknown): Add
uncertainty param.
(binding_cluster::remove_overlapping_bindings): Likewise.
(store::set_value): Likewise.
(store::mark_region_as_unknown): Likewise.
gcc/testsuite/ChangeLog:
PR analyzer/99042
PR analyzer/99774
* gcc.dg/analyzer/pr99042.c: New test.
* gcc.dg/analyzer/pr99774-1.c: New test.
* gcc.dg/analyzer/pr99774-2.c: New test.
|
|
Various places iterate through all of the saved_diagnostics to find
just the ones that are at a given enode. This patch adds a per-enode
record of the diagnostics that are at each node, to save iterating
through all of the diagnostics each time.
gcc/analyzer/ChangeLog:
* diagnostic-manager.cc (diagnostic_manager::add_diagnostic): Make
enode param non-constant, and call add_diagnostic on it. Add
enode index to log message.
(diagnostic_manager::add_diagnostic): Make enode param
non-constant.
* diagnostic-manager.h (diagnostic_manager::add_diagnostic):
Likewise for both decls.
* engine.cc
(impl_region_model_context::impl_region_model_context): Likewise
for enode_for_diag.
(impl_sm_context::impl_sm_context): Likewise.
(impl_sm_context::m_enode_for_diag): Likewise.
(exploded_node::dump_dot): Don't pass the diagnostic manager
to dump_saved_diagnostics.
(exploded_node::dump_saved_diagnostics): Drop param. Iterate
directly through all saved diagnostics for the enode, rather
than all saved diagnostics in the diagnostic_manager and
filtering.
(exploded_node::on_stmt): Make non-const.
(exploded_node::on_edge): Likewise.
(exploded_node::on_longjmp): Likewise.
(exploded_node::detect_leaks): Likewise.
(exploded_graph::get_or_create_node): Make enode_for_diag param
non-const.
(exploded_graph_annotator::print_enode): Iterate
directly through all saved diagnostics for the enode, rather
than all saved diagnostics in the diagnostic_manager and
filtering.
* exploded-graph.h
(impl_region_model_context::impl_region_model_context): Make
enode_for_diag param non-constant.
(impl_region_model_context::m_enode_for_diag): Likewise.
(exploded_node::dump_saved_diagnostics): Drop param.
(exploded_node::on_stmt): Make non-const.
(exploded_node::on_edge): Likewise.
(exploded_node::on_longjmp): Likewise.
(exploded_node::detect_leaks): Likewise.
(exploded_node::add_diagnostic): New.
(exploded_node::get_num_diagnostics): New.
(exploded_node::get_saved_diagnostic): New.
(exploded_node::m_saved_diagnostics): New.
(exploded_graph::get_or_create_node): Make enode_for_diag param
non-constant.
* feasible-graph.cc (feasible_node::dump_dot): Drop
diagnostic_manager from call to dump_saved_diagnostics.
* program-state.cc (program_state::on_edge): Convert enode param
to non-const pointer.
(program_state::prune_for_point): Likewise for enode_for_diag
param.
* program-state.h (program_state::on_edge): Convert enode param
to non-const pointer.
(program_state::prune_for_point): Likewise for enode_for_diag
param.
|
|
The analyzer builds an exploded graph of (point,state) pairs and when
it finds a problem, records a diagnostic at the relevant exploded node.
Once it has finished exploring the graph, the analyzer needs to generate
the shortest feasible path through the graph to each diagnostic's node.
This is used:
- for rejecting diagnostics that are infeasible (due to impossible sets
of constraints),
- for use in determining which diagnostic to use in each deduplication
set (the one with the shortest path), and
- for building checker_paths for the "winning" diagnostics, giving a
list of events
Prior to this patch the analyzer simply found the shortest path to the
node, and then checked it for feasibility, which could lead to falsely
rejecting diagnostics: "the shortest path, if feasible" is not the same
as "the shortest feasible path" (PR analyzer/96374).
An example is PR analyzer/93355, where this issue causes the analyzer
to fail to emit a leak warning for a missing fclose on an error-handling
path in intl/localealias.c.
This patch implements a new algorithm for finding the shortest feasible
path to an exploded node: instead of simply finding the shortest path,
the new algorithm uses a worklist to iteratively build a tree of path
prefixes, which are feasible paths by construction, until a path to the
target node is found. The worklist is prioritized, so that the first
feasible path discovered is the shortest possible feasible path. The
algorithm continues trying paths until the target node is reached or a
limit is exceeded, in which case the diagnostic is treated as being
infeasible (which could still be a false negative, but is much less
likely to happen than before). Iteratively building a tree of paths
allows for work to be reused, and the tree can be dumped in .dot form
(via a new -fdump-analyzer-feasibility option), making it much easier to
debug compared to other approaches I tried.
Doing so fixes the missing leak warning for PR analyzer/93355 and
various other test cases.
Testing:
- I manually verified that the behavior is determistic using 50 builds
of pr93355-localealias.c. All dumps were identical.
- I manually verified that it still builds with --disable-analyzer.
- Lightly tested with valgrind; no additional issues.
- Lightly performance tested, showing a slight speed regression to the
analyzer relative to before the patch, but correctness for this issue
is more important than the slight performance hit for the analyzer.
gcc/ChangeLog:
PR analyzer/96374
* Makefile.in (ANALYZER_OBJS): Add analyzer/feasible-graph.o and
analyzer/trimmed-graph.o.
* doc/analyzer.texi (Analyzer Paths): Rewrite description of
feasibility checking to reflect new implementation.
* doc/invoke.texi (-fdump-analyzer-feasibility): Document new
option.
* shortest-paths.h (shortest_paths::get_shortest_distance): New.
gcc/analyzer/ChangeLog:
PR analyzer/96374
* analyzer.opt (-param=analyzer-max-infeasible-edges=): New param.
(fdump-analyzer-feasibility): New flag.
* diagnostic-manager.cc: Include "analyzer/trimmed-graph.h" and
"analyzer/feasible-graph.h".
(epath_finder::epath_finder): Convert m_sep to a pointer and
only create it if !flag_analyzer_feasibility.
(epath_finder::~epath_finder): New.
(epath_finder::m_sep): Convert to a pointer.
(epath_finder::get_best_epath): Add param "diag_idx" and use it
when logging. Rather than finding the shortest path and then
checking feasibility, instead use explore_feasible_paths unless
!flag_analyzer_feasibility, in which case simply use the shortest
path, and note if it is infeasible. Update for m_sep becoming a
pointer.
(class feasible_worklist): New.
(epath_finder::explore_feasible_paths): New.
(epath_finder::process_worklist_item): New.
(class dump_eg_with_shortest_path): New.
(epath_finder::dump_trimmed_graph): New.
(epath_finder::dump_feasible_graph): New.
(saved_diagnostic::saved_diagnostic): Add "idx" param, using it
on new field m_idx.
(saved_diagnostic::to_json): Dump m_idx.
(saved_diagnostic::calc_best_epath): Pass m_idx to get_best_epath.
Remove assertion that m_problem was set when m_best_epath is NULL.
(diagnostic_manager::add_diagnostic): Pass an index when created
saved_diagnostic instances.
* diagnostic-manager.h (saved_diagnostic::saved_diagnostic): Add
"idx" param.
(saved_diagnostic::get_index): New accessor.
(saved_diagnostic::m_idx): New field.
* engine.cc (exploded_node::dump_dot): Call args.dump_extra_info.
Move code to...
(exploded_node::dump_processed_stmts): ...this new function and...
(exploded_node::dump_saved_diagnostics): ...this new function.
Add index of each diagnostic.
(exploded_edge::dump_dot): Move bulk of code to...
(exploded_edge::dump_dot_label): ...this new function.
* exploded-graph.h (eg_traits::dump_args_t::dump_extra_info): New
vfunc.
(exploded_node::dump_processed_stmts): New decl.
(exploded_node::dump_saved_diagnostics): New decl.
(exploded_edge::dump_dot_label): New decl.
* feasible-graph.cc: New file.
* feasible-graph.h: New file.
* trimmed-graph.cc: New file.
* trimmed-graph.h: New file.
gcc/testsuite/ChangeLog:
PR analyzer/96374
* gcc.dg/analyzer/dot-output.c: Add -fdump-analyzer-feasibility
to options.
* gcc.dg/analyzer/feasibility-1.c (test_6): Remove xfail.
(test_7): New.
* gcc.dg/analyzer/pr93355-localealias-feasibility-2.c: Remove xfail.
* gcc.dg/analyzer/pr93355-localealias-feasibility-3.c: Remove xfails.
* gcc.dg/analyzer/pr93355-localealias-feasibility.c: Remove
-fno-analyzer-feasibility from options.
* gcc.dg/analyzer/pr93355-localealias.c: Likewise.
* gcc.dg/analyzer/unknown-fns-4.c: Remove xfail.
|
|
As preparatory work for a fix to PR analyzer/96374, this patch
moves the core state-update logic from the loop in
exploded_path::feasible_p into a new class feasibility_state.
No functional change intended.
gcc/analyzer/ChangeLog:
PR analyzer/96374
* engine.cc (exploded_path::feasible_p): Move "snodes_visited" and
"model" locals into a new class feasibility_state. Move heart
of per-edge processing into
feasibility_state::maybe_update_for_edge.
(feasibility_state::feasibility_state): New.
(feasibility_state::maybe_update_for_edge): New, based on loop
body in exploded_path::feasible_p.
* exploded-graph.h (class feasibility_state): New.
|
|
gcc/analyzer/ChangeLog:
* engine.cc (exploded_path::exploded_path): New copy-ctor.
* exploded-graph.h (exploded_path::operator=): Drop decl.
|
|
In gcc/analyzer/diagnostic-manager.cc the code partitions
saved_diagnostic instances by dedupe_key, and tries to find the "best"
saved_diagnostic for each dedupe_key.
Ideally we would find the shortest feasible path for each
saved_diagnostic and pick the winner in each deduplication set.
Currently we merely approximate that by finding the shortest path for
each saved_diagnostic, and checking to see if it feasible, rejecting
the saved_diagnostic if it is not. The "shortest path, or nothing if
it's infeasible" is not the same as the "shortest feasible path", and
this leads to false negatives, where we reject valid diagnostics,
tracked as PR analyzer/96374.
I have been attempting various fixes for this, but in doing so I
found that the existing structure of the code makes things unnecessarily
awkward: each dedupe_set had a a dedupe_candidate which stored the
best epath for that set, creating it from the shortest path when that
dedupe_candidate was constructed.
This patch eliminates the dedupe_candidate, instead storing the best
epath for each saved_diagnostic within the saved_diagnostic itself,
along with any feasibility_problem, and eliminating a redundant "status"
field. The logic for finding the best epath is moved to a new
epath_finder::get_best_epath subroutine, introducing an epath_finder
class to give a place to cache state.
This patch merely copies over the existing logic to
epath_finder::get_best_epath, so no functional change is intended,
but the patch simplifies the logic and makes it much easier to
experiment with alternate implementations as I try to fix
PR analyzer/96374.
I attempted another version of this patch in which I added a dedupe_set
class and partitioned saved_diagnostics into them as the diagnostics were
added, but in this earlier iteration of the patch there were regressions
e.g. from gcc.dg/analyzer/zlib-4.c where 4 deduplication sets became 3.
The issue was that the deduplication logic needs source locations, which
need gimple statements, and the stmt_finder needs epaths to run. Finding
the epaths needs the full egraph (as opposed to the egraph in its state
at the time when the diagnostic is saved). Hence the partitioning needs to
happen after the egraph is fully explored. I backed up the earlier patch
kit to:
https://dmalcolm.fedorapeople.org/gcc/2021-02-23/feasibility-v0.3-relative-to-72d78655a91bb2f89ac4432cfd6374380d6f9987/
gcc/analyzer/ChangeLog:
PR analyzer/96374
* diagnostic-manager.cc (class epath_finder): New.
(epath_finder::get_best_epath): New.
(saved_diagnostic::saved_diagnostic): Update for replacement of
m_state and m_epath_length with m_best_epath.
(saved_diagnostic::~saved_diagnostic): Delete m_best_epath.
(saved_diagnostic::to_json): Update "path_length" to be optional.
(saved_diagnostic::calc_best_epath): New, based on
dedupe_winners::add and parts of dedupe_key::dedupe_key.
(saved_diagnostic::get_epath_length): New.
(saved_diagnostic::add_duplicate): New.
(dedupe_key::dedupe_key): Drop epath param. Move invocation of
stmt_finder to saved_diagnostic::calc_best_epath.
(class dedupe_candidate): Delete.
(class dedupe_hash_map_traits): Update to use saved_diagnotic *
rather than dedupe_candidate * as the value_type/compare_type.
(dedupe_winners::~dedupe_winners): Don't delete the values.
(dedupe_winners::add): Convert param from shortest_exploded_paths to
epath_finder. Drop "eg" param. Drop dedupe_candidate, moving
path generation and feasiblity checking to
epath_finder::get_best_epath. Update winner-selection for move
of epaths from dedupe_candidate to saved_diagnostic.
(dedupe_winners::emit_best): Update for removal of class
dedupe_candidate.
(dedupe_winners::map_t): Update to use saved_diagnotic * rather
than dedupe_candidate * as the value_type/compare_type.
(diagnostic_manager::emit_saved_diagnostics): Move
shortest_exploded_paths instance into epath_finder and pass that
around instead.
(diagnostic_manager::emit_saved_diagnostic): Drop epath, stmt
and num_dupes params, instead getting these from the
saved_diagnostic. Use correct location in inform_n call.
* diagnostic-manager.h (class epath_finder): New forward decl.
(saved_diagnostic::status): Drop enum.
(saved_diagnostic::set_feasible): Drop.
(saved_diagnostic::set_infeasible): Drop.
(saved_diagnostic::get_status): Drop.
(saved_diagnostic::calc_best_epath): New decl.
(saved_diagnostic::get_best_epath): New decl.
(saved_diagnostic::get_epath_length): New decl.
(saved_diagnostic::set_epath_length): Drop.
(saved_diagnostic::get_epath_length): Drop inline implementation.
(saved_diagnostic::add_duplicate): New.
(saved_diagnostic::get_num_dupes): New.
(saved_diagnostic::m_d): Document ownership.
(saved_diagnostic::m_trailing_eedge): Make const.
(saved_diagnostic::m_status): Drop field.
(saved_diagnostic::m_epath_length): Drop field.
(saved_diagnostic::m_best_epath): New field.
(saved_diagnostic::m_problem): Document ownership.
(saved_diagnostic::m_duplicates): New field.
(diagnostic_manager::emit_saved_diagnostic): Drop params epath,
stmt, and num_dupes.
* engine.cc (exploded_graph_annotator::print_saved_diagnostic):
Update for changes to saved_diagnostic class.
* exploded-graph.h (exploded_path::feasible_p): Drop unused
overloaded decl.
|
|
I've been implementing a PyGTK viewer for the output of
-fdump-analyzer-json, to help me debug analyzer issues:
https://github.com/davidmalcolm/gcc-analyzer-viewer
The viewer is very much just a work in progress.
This patch adds some fields that were missing from the dump, and
fixes some mistakes I spotted whilst working on the viewer.
gcc/analyzer/ChangeLog:
* engine.cc (strongly_connected_components::to_json): New.
(worklist::to_json): New.
(exploded_graph::to_json): JSON-ify the worklist.
* exploded-graph.h (strongly_connected_components::to_json): New
decl.
(worklist::to_json): New decl.
* store.cc (store::to_json): Fix comment.
* supergraph.cc (supernode::to_json): Fix reference to
"returning_call" in comment. Add optional "fun" to JSON.
(edge_kind_to_string): New.
(superedge::to_json): Add "kind" to JSON.
|
|
|
|
The analyzer's initial worklist was only populated with non-static
functions in the TU (along with those that look promising for call
summaries). Hence some static functions that were never explicitly
called but could be called via function pointers were not being
analyzed.
This patch remedies this by ensuring that functions that escape as
function pointers get added to the worklist, if they haven't been
already. Another fix would be to simply analyze all functions that
we have a body for, but too much of the testsuite relies on static
test functions not being directly analyzed.
gcc/analyzer/ChangeLog:
PR analyzer/97258
* engine.cc (impl_region_model_context::on_escaped_function): New
vfunc.
(exploded_graph::add_function_entry): Use m_functions_with_enodes
to implement idempotency.
(add_any_callbacks): New.
(exploded_graph::build_initial_worklist): Use the above to find
callbacks that are reachable from global initializers.
(exploded_graph::on_escaped_function): New.
* exploded-graph.h
(impl_region_model_context::on_escaped_function): New decl.
(exploded_graph::on_escaped_function): New decl.
(exploded_graph::m_functions_with_enodes): New field.
* region-model-reachability.cc
(reachable_regions::reachable_regions): Replace "store" param with
"model" param; use it to initialize m_model.
(reachable_regions::add): When getting the svalue for the region,
call get_store_value on the model rather than using an initial
value.
(reachable_regions::mark_escaped_clusters): Add ctxt param and
use it to call on_escaped_function when a function_region escapes.
* region-model-reachability.h
(reachable_regions::reachable_regions): Replace "store" param with
"model" param.
(reachable_regions::mark_escaped_clusters): Add ctxt param.
(reachable_regions::m_model): New field.
* region-model.cc (region_model::handle_unrecognized_call): Update
for change in reachable_regions ctor.
(region_model::handle_unrecognized_call): Pass ctxt to
mark_escaped_clusters.
(region_model::get_reachable_svalues): Update for change in
reachable_regions ctor.
(region_model::get_initial_value_for_global): Read-only variables
keep their initial values.
* region-model.h (region_model_context::on_escaped_function): New
vfunc.
(noop_region_model_context::on_escaped_function): New.
gcc/testsuite/ChangeLog:
PR analyzer/97258
* gcc.dg/analyzer/callbacks-1.c: New test.
* gcc.dg/analyzer/callbacks-2.c: New test.
* gcc.dg/analyzer/callbacks-3.c: New test.
|
|
This patch provides a new option "-fno-analyzer-feasibility" as a way
to disable feasibility-checking of the constraints along the control
flow paths for -fanalyzer diagnostics. I'm adding this in the hope of
making it easier to debug issues involving the feasibility-checking
logic.
The patch adds a new rejected_constraint object which is captured if
exploded_path::feasible_p fails, and adds logic that uses this to emit
an additional custom_event within the checker_path for the diagnostic,
showing where in the control flow path the diagnostic would have been
rejected, and giving details of why.
gcc/analyzer/ChangeLog:
* analyzer.h (struct rejected_constraint): New decl.
* analyzer.opt (fanalyzer-feasibility): New option.
* diagnostic-manager.cc (path_builder::path_builder): Add
"problem" param and use it to initialize new field.
(path_builder::get_feasibility_problem): New accessor.
(path_builder::m_feasibility_problem): New field.
(dedupe_winners::add): Remove inversion of logic in "if" clause,
swapping if/else suites. In the !feasible_p suite, inspect
flag_analyzer_feasibility and add code to handle when this
is off, accepting the infeasible path, but recording the
feasibility_problem.
(diagnostic_manager::emit_saved_diagnostic): Pass the
feasibility_problem to the path_builder.
(diagnostic_manager::add_events_for_eedge): If we have
a feasibility_problem at this edge, use it to add a custom event.
* engine.cc (exploded_path::feasible_p): Pass a
rejected_constraint ** to model.maybe_update_for_edge and transfer
ownership of any created instance to any feasibility_problem.
(feasibility_problem::dump_to_pp): New.
* exploded-graph.h (feasibility_problem::feasibility_problem):
Drop "model" param; add rejected_constraint * param.
(feasibility_problem::~feasibility_problem): New.
(feasibility_problem::dump_to_pp): New decl.
(feasibility_problem::m_model): Drop field.
(feasibility_problem::m_rc): New field.
* program-point.cc (function_point::get_location): Handle
PK_BEFORE_SUPERNODE and PK_AFTER_SUPERNODE.
* program-state.cc (program_state::on_edge): Pass NULL to new
param of region_model::maybe_update_for_edge.
* region-model.cc (region_model::add_constraint): New overload
adding a rejected_constraint ** param.
(region_model::maybe_update_for_edge): Add rejected_constraint **
param and pass it to the various apply_constraints_for_ calls.
(region_model::apply_constraints_for_gcond): Add
rejected_constraint ** param and pass it to add_constraint calls.
(region_model::apply_constraints_for_gswitch): Likewise.
(region_model::apply_constraints_for_exception): Likewise.
(rejected_constraint::dump_to_pp): New.
* region-model.h (region_model::maybe_update_for_edge):
Add rejected_constraint ** param.
(region_model::add_constraint): New overload adding a
rejected_constraint ** param.
(region_model::apply_constraints_for_gcond): Add
rejected_constraint ** param.
(region_model::apply_constraints_for_gswitch): Likewise.
(region_model::apply_constraints_for_exception): Likewise.
(struct rejected_constraint): New.
gcc/ChangeLog:
* doc/analyzer.texi (Analyzer Paths): Add note about
-fno-analyzer-feasibility.
* doc/invoke.texi (Static Analyzer Options): Add
-fno-analyzer-feasibility.
gcc/testsuite/ChangeLog:
* gcc.dg/analyzer/feasibility-2.c: New test.
|
|
I've found this useful for debugging state explosions in the analyzer.
gcc/analyzer/ChangeLog:
* analysis-plan.cc: Include "json.h".
* analyzer.opt (fdump-analyzer-json): New.
* call-string.cc: Include "json.h".
(call_string::to_json): New.
* call-string.h (call_string::to_json): New decl.
* checker-path.cc: Include "json.h".
* constraint-manager.cc: Include "json.h".
(equiv_class::to_json): New.
(constraint::to_json): New.
(constraint_manager::to_json): New.
* constraint-manager.h (equiv_class::to_json): New decl.
(constraint::to_json): New decl.
(constraint_manager::to_json): New decl.
* diagnostic-manager.cc: Include "json.h".
(saved_diagnostic::to_json): New.
(diagnostic_manager::to_json): New.
* diagnostic-manager.h (saved_diagnostic::to_json): New decl.
(diagnostic_manager::to_json): New decl.
* engine.cc: Include "json.h", <zlib.h>.
(exploded_node::status_to_str): New.
(exploded_node::to_json): New.
(exploded_edge::to_json): New.
(exploded_graph::to_json): New.
(dump_analyzer_json): New.
(impl_run_checkers): Call it.
* exploded-graph.h (exploded_node::status_to_str): New decl.
(exploded_node::to_json): New.
(exploded_edge::to_json): New.
(exploded_graph::to_json): New.
* pending-diagnostic.cc: Include "json.h".
* program-point.cc: Include "json.h".
(program_point::to_json): New.
* program-point.h (program_point::to_json): New decl.
* program-state.cc: Include "json.h".
(extrinsic_state::to_json): New.
(sm_state_map::to_json): New.
(program_state::to_json): New.
* program-state.h (extrinsic_state::to_json): New decl.
(sm_state_map::to_json): New decl.
(program_state::to_json): New decl.
* region-model-impl-calls.cc: Include "json.h".
* region-model-manager.cc: Include "json.h".
* region-model-reachability.cc: Include "json.h".
* region-model.cc: Include "json.h".
* region-model.h (svalue::to_json): New decl.
(region::to_json): New decl.
* region.cc: Include "json.h".
(region::to_json: New.
* sm-file.cc: Include "json.h".
* sm-malloc.cc: Include "json.h".
* sm-pattern-test.cc: Include "json.h".
* sm-sensitive.cc: Include "json.h".
* sm-signal.cc: Include "json.h".
(signal_delivery_edge_info_t::to_json): New.
* sm-taint.cc: Include "json.h".
* sm.cc: Include "diagnostic.h", "tree-diagnostic.h", and
"json.h".
(state_machine::state::to_json): New.
(state_machine::to_json): New.
* sm.h (state_machine::state::to_json): New.
(state_machine::to_json): New.
* state-purge.cc: Include "json.h".
* store.cc: Include "json.h".
(binding_key::get_desc): New.
(binding_map::to_json): New.
(binding_cluster::to_json): New.
(store::to_json): New.
* store.h (binding_key::get_desc): New decl.
(binding_map::to_json): New decl.
(binding_cluster::to_json): New decl.
(store::to_json): New decl.
* supergraph.cc: Include "json.h".
(supergraph::to_json): New.
(supernode::to_json): New.
(superedge::to_json): New.
* supergraph.h (supergraph::to_json): New decl.
(supernode::to_json): New decl.
(superedge::to_json): New decl.
* svalue.cc: Include "json.h".
(svalue::to_json): New.
gcc/ChangeLog:
* doc/analyzer.texi (Other Debugging Techniques): Mention
-fdump-analyzer-json.
* doc/invoke.texi (Static Analyzer Options): Add
-fdump-analyzer-json.
|