aboutsummaryrefslogtreecommitdiff
path: root/gcc/analyzer/exploded-graph.h
AgeCommit message (Collapse)AuthorFilesLines
2025-01-02Update copyright years.Jakub Jelinek1-1/+1
2024-11-01analyzer: use std::unique_ptr in "to_json" functionsDavid Malcolm1-5/+5
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>
2024-10-25gcc: Remove trailing whitespaceJakub Jelinek1-1/+1
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.
2024-06-01analyzer: detect -Wanalyzer-allocation-size at call stmts [PR106203]David Malcolm1-0/+1
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>
2024-02-29analyzer: fix ICE in call summarization [PR114159]David Malcolm1-4/+4
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>
2024-01-03Update copyright years.Jakub Jelinek1-1/+1
2023-11-17analyzer: new warning: -Wanalyzer-infinite-loop [PR106147]David Malcolm1-3/+36
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>
2023-09-14analyzer: use unique_ptr for rejected_constraintDavid Malcolm1-5/+4
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>
2023-08-30analyzer: implement reference count checking for CPython plugin [PR107646]Eric Feng1-1/+3
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>
2023-08-21analyzer: add ability for context to add events to a saved_diagnosticDavid Malcolm1-0/+1
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>
2023-02-15analyzer: fix uninit false +ves [PR108664,PR108666,PR108725]David Malcolm1-0/+1
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>
2023-01-16Update copyright years.Jakub Jelinek1-1/+1
2022-11-15analyzer: add warnings relating to sockets [PR106140]David Malcolm1-4/+6
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>
2022-11-11analyzer: new warning: -Wanalyzer-infinite-recursion [PR106147]David Malcolm1-0/+5
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>
2022-11-10analyzer: new warning: -Wanalyzer-deref-before-check [PR99671]David Malcolm1-0/+2
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>
2022-11-03analyzer: use std::unique_ptr during bifurcationDavid Malcolm1-1/+1
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>
2022-11-03analyzer: use std::unique_ptr for feasibility_problems and exploded_pathDavid Malcolm1-1/+1
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>
2022-11-03analyzer: use std::unique_ptr for custom_edge_info pointersDavid Malcolm1-7/+4
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>
2022-11-03analyzer: use std::unique_ptr for saved_diagnostic::m_stmt_finderDavid Malcolm1-1/+1
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>
2022-11-03analyzer: use std::unique_ptr for pending_diagnostic/noteDavid Malcolm1-2/+2
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>
2022-10-24analyzer: simplify sm_state_map lookupDavid Malcolm1-9/+4
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>
2022-10-24analyzer: handle "pipe" and "pipe2" [PR106300]David Malcolm1-0/+3
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>
2022-10-05analyzer: remove unused variablesMartin Liska1-2/+0
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.
2022-10-04analyzer: revamp side-effects of call summaries [PR107072]David Malcolm1-5/+31
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>
2022-07-19analyzer: fix taint handling of switch statements [PR106321]David Malcolm1-0/+3
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>
2022-06-24analyzer: consolidate call_string instancesDavid Malcolm1-58/+3
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>
2022-05-20Use "final" and "override" directly, rather than via macrosDavid Malcolm1-26/+26
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>
2022-04-28analyzer: add .fpath.txt dumps to -fdump-analyzer-feasibilityDavid Malcolm1-0/+2
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>
2022-03-10analyzer: add notes to write-to-const/string from access attr [PR104793]David Malcolm1-0/+1
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>
2022-02-15analyzer: fix uninit false +ve due to optimized conditionals [PR102692]David Malcolm1-0/+2
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>
2022-01-03Update copyright years.Jakub Jelinek1-1/+1
2021-11-13analyzer: add four new taint-based warningsDavid Malcolm1-0/+3
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>
2021-08-30analyzer: support "bifurcation"; reimplement realloc [PR99260]David Malcolm1-33/+29
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-21analyzer: Fix PR analyzer/101980Ankur Saini1-7/+7
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-08-18analyzer: detect and analyze calls via function pointerAnkur Saini1-0/+39
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.
2021-07-15analyzer: reimplement -Wanalyzer-use-of-uninitialized-value [PR95006 et al]David Malcolm1-1/+14
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>
2021-07-15analyzer: add -fdump-analyzer-exploded-pathsDavid Malcolm1-3/+6
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>
2021-07-07analyzer: remove add_any_constraints_from_ssa_def_stmtDavid Malcolm1-1/+3
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>
2021-06-15analyzer: track dynamic extents of regionsDavid Malcolm1-16/+4
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>
2021-04-08analyzer: fix leak false +ves due to maybe-clobbered regions [PR99042,PR99774]David Malcolm1-2/+9
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.
2021-04-01analyzer: record per-enode saved_diagnosticsDavid Malcolm1-9/+25
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.
2021-03-11analyzer: new implementation of shortest feasible path [PR96374]David Malcolm1-0/+8
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.
2021-03-10analyzer: factor out new class feasibility_stateDavid Malcolm1-0/+22
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.
2021-02-26analyzer: implement exploded_path copy ctorDavid Malcolm1-1/+0
gcc/analyzer/ChangeLog: * engine.cc (exploded_path::exploded_path): New copy-ctor. * exploded-graph.h (exploded_path::operator=): Drop decl.
2021-02-25analyzer: eliminate dedupe_candidate [PR96374]David Malcolm1-1/+0
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.
2021-01-14analyzer: fixes to -fdump-analyzer-jsonDavid Malcolm1-0/+4
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.
2021-01-04Update copyright years.Jakub Jelinek1-1/+1
2020-10-12analyzer: handle static callbacks [PR97258]David Malcolm1-0/+8
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.
2020-09-23analyzer: add -fno-analyzer-feasibilityDavid Malcolm1-5/+8
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.
2020-09-22analyzer: add -fdump-analyzer-jsonDavid Malcolm1-0/+7
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.