davidmalcolm / gcc-python-plugin

GCC plugin that embeds CPython inside the compiler
GNU General Public License v3.0
199 stars 58 forks source link

Python exception from divide by zero #65

Closed davidmalcolm closed 7 years ago

davidmalcolm commented 7 years ago

I saw this Python exception due to a divide-by-zero. I think the user should never see a Python trace, so the checker should issue an error or something here instead.

The code is: {{{ reloc_count = relplt->size / elf_section_data (relplt)->this_hdr.sh_entsize; }}} This actually can never be 0. {{{ ../../archer/gdb/elfread.c: In function ‘elf_rel_plt_read’: ../../archer/gdb/elfread.c:634:15: error: Unhandled Python exception raised calling 'execute' method Traceback (most recent call last): File "/home/tromey/Space/Trunk/gcc-python-plugin/libcpychecker/init.py", line 64, in execute self._check_refcounts(fun) File "/home/tromey/Space/Trunk/gcc-python-plugin/libcpychecker/init.py", line 68, in _check_refcounts self.show_possible_null_derefs) File "/home/tromey/Space/Trunk/gcc-python-plugin/libcpychecker/refcounts.py", line 2838, in check_refcounts limits=limits) File "/home/tromey/Space/Trunk/gcc-python-plugin/libcpychecker/absinterp.py", line 2716, in iter_traces depth + 1): File "/home/tromey/Space/Trunk/gcc-python-plugin/libcpychecker/absinterp.py", line 2716, in iter_traces depth + 1): File "/home/tromey/Space/Trunk/gcc-python-plugin/libcpychecker/absinterp.py", line 2716, in iter_traces depth + 1): File "/home/tromey/Space/Trunk/gcc-python-plugin/libcpychecker/absinterp.py", line 2716, in iter_traces depth + 1): File "/home/tromey/Space/Trunk/gcc-python-plugin/libcpychecker/absinterp.py", line 2716, in iter_traces depth + 1): File "/home/tromey/Space/Trunk/gcc-python-plugin/libcpychecker/absinterp.py", line 2716, in iter_traces depth + 1): File "/home/tromey/Space/Trunk/gcc-python-plugin/libcpychecker/absinterp.py", line 2716, in iter_traces depth + 1): File "/home/tromey/Space/Trunk/gcc-python-plugin/libcpychecker/absinterp.py", line 2716, in iter_traces depth + 1): File "/home/tromey/Space/Trunk/gcc-python-plugin/libcpychecker/absinterp.py", line 2716, in iter_traces depth + 1): File "/home/tromey/Space/Trunk/gcc-python-plugin/libcpychecker/absinterp.py", line 2716, in iter_traces depth + 1): File "/home/tromey/Space/Trunk/gcc-python-plugin/libcpychecker/absinterp.py", line 2716, in iter_traces depth + 1): File "/home/tromey/Space/Trunk/gcc-python-plugin/libcpychecker/absinterp.py", line 2716, in iter_traces depth + 1): File "/home/tromey/Space/Trunk/gcc-python-plugin/libcpychecker/absinterp.py", line 2716, in iter_traces depth + 1): File "/home/tromey/Space/Trunk/gcc-python-plugin/libcpychecker/absinterp.py", line 2716, in iter_traces depth + 1): File "/home/tromey/Space/Trunk/gcc-python-plugin/libcpychecker/absinterp.py", line 2716, in iter_traces depth + 1): File "/home/tromey/Space/Trunk/gcc-python-plugin/libcpychecker/absinterp.py", line 2716, in iter_traces depth + 1): File "/home/tromey/Space/Trunk/gcc-python-plugin/libcpychecker/absinterp.py", line 2716, in iter_traces depth + 1): File "/home/tromey/Space/Trunk/gcc-python-plugin/libcpychecker/absinterp.py", line 2716, in iter_traces depth + 1): File "/home/tromey/Space/Trunk/gcc-python-plugin/libcpychecker/absinterp.py", line 2716, in iter_traces depth + 1): File "/home/tromey/Space/Trunk/gcc-python-plugin/libcpychecker/absinterp.py", line 2716, in iter_traces depth + 1): File "/home/tromey/Space/Trunk/gcc-python-plugin/libcpychecker/absinterp.py", line 2716, in iter_traces depth + 1): File "/home/tromey/Space/Trunk/gcc-python-plugin/libcpychecker/absinterp.py", line 2716, in iter_traces depth + 1): File "/home/tromey/Space/Trunk/gcc-python-plugin/libcpychecker/absinterp.py", line 2716, in iter_traces depth + 1): File "/home/tromey/Space/Trunk/gcc-python-plugin/libcpychecker/absinterp.py", line 2716, in iter_traces depth + 1): File "/home/tromey/Space/Trunk/gcc-python-plugin/libcpychecker/absinterp.py", line 2716, in iter_traces depth + 1): File "/home/tromey/Space/Trunk/gcc-python-plugin/libcpychecker/absinterp.py", line 2716, in iter_traces depth + 1): File "/home/tromey/Space/Trunk/gcc-python-plugin/libcpychecker/absinterp.py", line 2716, in iter_traces depth + 1): File "/home/tromey/Space/Trunk/gcc-python-plugin/libcpychecker/absinterp.py", line 2716, in iter_traces depth + 1): File "/home/tromey/Space/Trunk/gcc-python-plugin/libcpychecker/absinterp.py", line 2716, in iter_traces depth + 1): File "/home/tromey/Space/Trunk/gcc-python-plugin/libcpychecker/absinterp.py", line 2716, in iter_traces depth + 1): File "/home/tromey/Space/Trunk/gcc-python-plugin/libcpychecker/absinterp.py", line 2716, in iter_traces depth + 1): File "/home/tromey/Space/Trunk/gcc-python-plugin/libcpychecker/absinterp.py", line 2716, in iter_traces depth + 1): File "/home/tromey/Space/Trunk/gcc-python-plugin/libcpychecker/absinterp.py", line 2716, in iter_traces depth + 1): File "/home/tromey/Space/Trunk/gcc-python-plugin/libcpychecker/absinterp.py", line 2716, in iter_traces depth + 1): File "/home/tromey/Space/Trunk/gcc-python-plugin/libcpychecker/absinterp.py", line 2716, in iter_traces depth + 1): File "/home/tromey/Space/Trunk/gcc-python-plugin/libcpychecker/absinterp.py", line 2716, in iter_traces depth + 1): File "/home/tromey/Space/Trunk/gcc-python-plugin/libcpychecker/absinterp.py", line 2716, in iter_traces depth + 1): File "/home/tromey/Space/Trunk/gcc-python-plugin/libcpychecker/absinterp.py", line 2716, in iter_traces depth + 1): File "/home/tromey/Space/Trunk/gcc-python-plugin/libcpychecker/absinterp.py", line 2716, in iter_traces depth + 1): File "/home/tromey/Space/Trunk/gcc-python-plugin/libcpychecker/absinterp.py", line 2716, in iter_traces depth + 1): File "/home/tromey/Space/Trunk/gcc-python-plugin/libcpychecker/absinterp.py", line 2716, in iter_traces depth + 1): File "/home/tromey/Space/Trunk/gcc-python-plugin/libcpychecker/absinterp.py", line 2716, in iter_traces depth + 1): File "/home/tromey/Space/Trunk/gcc-python-plugin/libcpychecker/absinterp.py", line 2716, in iter_traces depth + 1): File "/home/tromey/Space/Trunk/gcc-python-plugin/libcpychecker/absinterp.py", line 2716, in iter_traces depth + 1): File "/home/tromey/Space/Trunk/gcc-python-plugin/libcpychecker/absinterp.py", line 2716, in iter_traces depth + 1): File "/home/tromey/Space/Trunk/gcc-python-plugin/libcpychecker/absinterp.py", line 2716, in iter_traces depth + 1): File "/home/tromey/Space/Trunk/gcc-python-plugin/libcpychecker/absinterp.py", line 2716, in iter_traces depth + 1): File "/home/tromey/Space/Trunk/gcc-python-plugin/libcpychecker/absinterp.py", line 2716, in iter_traces depth + 1): File "/home/tromey/Space/Trunk/gcc-python-plugin/libcpychecker/absinterp.py", line 2716, in iter_traces depth + 1): File "/home/tromey/Space/Trunk/gcc-python-plugin/libcpychecker/absinterp.py", line 2716, in iter_traces depth + 1): File "/home/tromey/Space/Trunk/gcc-python-plugin/libcpychecker/absinterp.py", line 2716, in iter_traces depth + 1): File "/home/tromey/Space/Trunk/gcc-python-plugin/libcpychecker/absinterp.py", line 2716, in iter_traces depth + 1): File "/home/tromey/Space/Trunk/gcc-python-plugin/libcpychecker/absinterp.py", line 2680, in iter_traces transitions = curstate.get_transitions() File "/home/tromey/Space/Trunk/gcc-python-plugin/libcpychecker/absinterp.py", line 1828, in get_transitions return self._get_transitions_for_stmt(stmt) File "/home/tromey/Space/Trunk/gcc-python-plugin/libcpychecker/absinterp.py", line 1855, in _get_transitions_for_stmt return self._get_transitions_for_GimpleAssign(stmt) File "/home/tromey/Space/Trunk/gcc-python-plugin/libcpychecker/absinterp.py", line 2308, in _get_transitions_for_GimpleAssign value = self.eval_rhs(stmt) File "/home/tromey/Space/Trunk/gcc-python-plugin/libcpychecker/absinterp.py", line 2251, in eval_rhs c = a.eval_binop(stmt.exprcode, b, stmt.lhs.type, stmt.loc) File "/home/tromey/Space/Trunk/gcc-python-plugin/libcpychecker/absinterp.py", line 587, in eval_binop values = (eval_binop(exprcode, self.minvalue, rhs.minvalue), File "/home/tromey/Space/Trunk/gcc-python-plugin/libcpychecker/absinterp.py", line 365, in eval_binop result = inner() File "/home/tromey/Space/Trunk/gcc-python-plugin/libcpychecker/absinterp.py", line 340, in inner return a // b ZeroDivisionError: integer division or modulo by zero }}}

davidmalcolm commented 7 years ago

Imported from trac issue 25. Created by tromey on 2012-01-05T09:28:23, last modified: 2012-01-06T17:24:48

davidmalcolm commented 7 years ago

Trac comment by dmalcolm on 2012-01-05 14:26:21:

Minimal reproducer: {{{ int test(int i, unsigned int j) { return i % j; } }}}

What's happening is j is WithinRange(0, UINT_MAX), and it considers the four corners:

davidmalcolm commented 7 years ago

Trac comment by dmalcolm on 2012-01-05 17:12:57:

Fix for the Python traceback committed as 65640b654a16ed174457a52d25b2af1ee241d5c1

Note that this merely fixes the traceback, splitting unsigned values into the RHS == 0 and RHS > 0 cases, and leads to a huge warning for the above gdb code: {{{ ../../src/gdb/elfread.c: In function ‘elf_rel_plt_read’: ../../src/gdb/elfread.c:649:15: error: possible integer division or modulo by zero with right-hand-side (bfd_size_type)val [0 <= val <= 0] from ../../src/gdb/elfread.c:649 [-Werror] ../../src/gdb/elfread.c:610:8: note: when treating unknown struct objfile from ../../src/gdb/elfread.c:608 as non-NULL at: bfd obfd = objfile->obfd; ../../src/gdb/elfread.c:611:40: note: when treating unknown struct bfd from ../../src/gdb/elfread.c:610 as non-NULL at: const struct elf_backend_data bed = get_elf_backend_data (obfd); ../../src/gdb/elfread.c:611:34: note: when treating unknown const struct bfd_target from ../../src/gdb/elfread.c:611 as non-NULL at: const struct elf_backend_data bed = get_elf_backend_data (obfd); ../../src/gdb/elfread.c:620:16: note: when treating unknown const struct builtin_type from ../../src/gdb/elfread.c:620 as non-NULL at: struct type ptr_type = builtin_type (gdbarch)->builtin_data_ptr; ../../src/gdb/elfread.c:621:21: note: when treating unknown struct type const from ../../src/gdb/elfread.c:620 as non-NULL at: size_t ptr_size = TYPE_LENGTH (ptr_type); ../../src/gdb/elfread.c:623:6: note: when treating unknown struct objfile from ../../src/gdb/elfread.c:623 as NULL at: if (objfile->separate_debug_objfile_backlink) ../../src/gdb/elfread.c:623:6: note: taking False path at: if (objfile->separate_debug_objfile_backlink) ../../src/gdb/elfread.c:626:7: note: reaching: plt = bfd_get_section_by_name (obfd, ".plt"); ../../src/gdb/elfread.c:627:6: note: when treating unknown struct asection from ../../src/gdb/elfread.c:626 as non-NULL at: if (plt == NULL) ../../src/gdb/elfread.c:627:6: note: taking False path at: if (plt == NULL) ../../src/gdb/elfread.c:629:17: note: reaching: plt_elf_idx = elf_section_data (plt)->this_idx; ../../src/gdb/elfread.c:629:15: note: when treating unknown void from ../../src/gdb/elfread.c:629 as non-NULL at: plt_elf_idx = elf_section_data (plt)->this_idx; ../../src/gdb/elfread.c:632:6: note: when treating unknown struct asection from ../../src/gdb/elfread.c:631 as non-NULL at: if (got_plt == NULL) ../../src/gdb/elfread.c:632:6: note: taking False path at: if (got_plt == NULL) ../../src/gdb/elfread.c:636:15: note: reaching: for (relplt = obfd->sections; relplt != NULL; relplt = relplt->next) ../../src/gdb/elfread.c:636:3: note: when treating unknown struct bfd_section from ../../src/gdb/elfread.c:636 as non-NULL at: for (relplt = obfd->sections; relplt != NULL; relplt = relplt->next) ../../src/gdb/elfread.c:636:3: note: taking True path at: for (relplt = obfd->sections; relplt != NULL; relplt = relplt->next) ../../src/gdb/elfread.c:637:9: note: reaching: if (elf_section_data (relplt)->this_hdr.sh_info == plt_elf_idx ../../src/gdb/elfread.c:637:44: note: when treating unknown void from ../../src/gdb/elfread.c:637 as non-NULL at: if (elf_section_data (relplt)->this_hdr.sh_info == plt_elf_idx ../../src/gdb/elfread.c:637:8: note: when taking True path at: if (elf_section_data (relplt)->this_hdr.sh_info == plt_elf_idx ../../src/gdb/elfread.c:638:6: note: reaching: && (elf_section_data (relplt)->this_hdr.sh_type == SHT_REL ../../src/gdb/elfread.c:638:41: note: when treating unknown void from ../../src/gdb/elfread.c:638 as non-NULL at: && (elf_section_data (relplt)->this_hdr.sh_type == SHT_REL ../../src/gdb/elfread.c:638:2: note: taking True path at: && (elf_section_data (relplt)->this_hdr.sh_type == SHT_REL ../../src/gdb/elfread.c:641:6: note: reaching: if (relplt == NULL) ../../src/gdb/elfread.c:641:6: note: taking False path at: if (relplt == NULL) ../../src/gdb/elfread.c:644:12: note: reaching: if (! bed->s->slurp_reloc_table (obfd, relplt, dyn_symbol_table, TRUE)) ../../src/gdb/elfread.c:644:12: note: when treating unknown const void const from ../../src/gdb/elfread.c:611 as non-NULL at: if (! bed->s->slurp_reloc_table (obfd, relplt, dyn_symbol_table, TRUE)) ../../src/gdb/elfread.c:644:15: note: when treating unknown const struct elf_size_info const from ../../src/gdb/elfread.c:644 as non-NULL at: if (! bed->s->slurp_reloc_table (obfd, relplt, dyn_symbol_table, TRUE)) ../../src/gdb/elfread.c:644:35: note: calling unknown bfd_boolean () (struct bfd , struct asection , struct asymbol , bfd_boolean) from ../../src/gdb/elfread.c:644 at: if (! bed->s->slurp_reloc_table (obfd, relplt, dyn_symbol_table, TRUE)) ../../src/gdb/elfread.c:644:6: note: when taking False path at: if (! bed->s->slurp_reloc_table (obfd, relplt, dyn_symbol_table, TRUE)) ../../src/gdb/elfread.c:647:11: note: reaching: back_to = make_cleanup (free_current_contents, &string_buffer); ../../src/gdb/elfread.c:649:67: note: when treating unknown void from ../../src/gdb/elfread.c:649 as non-NULL at: reloc_count = relplt->size / elf_section_data (relplt)->this_hdr.sh_entsize; ../../src/gdb/elfread.c:649:15: note: when considering range: 0 <= value <= 0 at: reloc_count = relplt->size / elf_section_data (relplt)->this_hdr.sh_entsize; ../../src/gdb/elfread.c:609:1: note: graphical error report for function 'elf_rel_plt_read' written out to 'elfread.c.elf_rel_plt_read-refcount-errors.html' }}}

davidmalcolm commented 7 years ago

Trac comment by dmalcolm on 2012-01-06 17:24:48:

3c6e7c7a33e3fb026ee1206ef8ebc9e1a5301062 suppresses this warning: we now only report about arithmetic errors that will definitely occur down a path of execution, rather than those that might occur.