On Fri, 2 Sep 2016, Dhiru Kholia wrote:

> On Fri, Sep 2, 2016 at 1:07 PM, Julia Lawall <[email protected]> wrote:
> >
> >
> > On Fri, 2 Sep 2016, Dhiru Kholia wrote:
> >
> >> Hi,
> >>
> >> When the following program is compiled with GCC 6 compiler running on
> >> Fedora 24 with "-O2" flag, the overflow check (rowstride / channels !=
> >> width) gets eliminated presumably due to undefined behavior.
> >>
> >> // gcc -c -O2 too-much-optimization.c
> >> //
> >> // objdump -d too-much-optimization.o
> >>
> >> #include <stdio.h>
> >> #include <stdlib.h>
> >>
> >> void *gdk_pixbuf_new_reduced(int has_alpha, int width, int height)
> >> {
> >>   void *buf = NULL;
> >>   int channels;
> >>   int rowstride;
> >>
> >>   if (width < 0)
> >>     return NULL;
> >>   if (height < 0)
> >>     return 0;
> >>
> >>   channels = has_alpha ? 4 : 3;
> >>   rowstride = width * channels;
> >>   if (rowstride / channels != width) /* overflow check */
> >>     return NULL;
> >>
> >>   buf = calloc(height, rowstride);
> >>   if (!buf)
> >>     return NULL;
> >>
> >>   return buf;
> >> }
> >>
> >> This code is present in the gdk-pixbuf software package. The
> >> elimination of this overflow check leads to memory corruption problems
> >> later on in the gdk-pixbuf library.
> >>
> >> Is it possible to detect such code patterns (multiplication operation
> >> followed by division to check for overflow) which invoke undefined
> >> behavior using Coccinelle?
> >
> > @@
> > expression x,y,z,e;
> > @@
> >
> > * x = y * z
> >   ... when != x = e
> > * x / z
> >
> > This should take advantage of the fact that * is commutative, and so you
> > should not have to write two rules.  To check this, you can run
> >
> > spatch --parse-cocci foo.cocci
> >
> > if the above code is in foo.cocci.
> >
> > The * at the beginning of the first and third lines means that these are
> > lines you are interested in seeing.  You will get a diff as a result, with
> > the lines that match the starred things having a - at the beginning.  This
> > will not affect the code.
>
> Thanks Julia!
>
> Here is my version of the Coccinelle script which checks that "x" is
> signed. When "x"  is unsigned the compiler does not eliminate the
> overflow check.
>
> @@
> type T;
> signed T x;
> expression y,z,e;
> @@
>
> * x = y * z
>   ... when != x = e
> * x / z

It looks reasonable.  You may however have some typedefs for signed types,
such as s32, etc.  If you need multiple types, you can put them in {}.

julia
_______________________________________________
Cocci mailing list
[email protected]
https://systeme.lip6.fr/mailman/listinfo/cocci

Reply via email to