https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98223

--- Comment #2 from David Malcolm <dmalcolm at gcc dot gnu.org> ---
I believe the existing false positive may relate to bug 97072, where the
analyzer doesn't capture that the pointer to the malloc-ed buffer has been
written to one of the fields (perhaps due to state-merging), and hence reports
a leak when the frame is popped.

Comparing the before/after EVRP patch gimple dumps, I see:
    --- pr94851-1.c.071i.analyzer.before    2021-01-05 11:08:02.809471975 -0500
    +++ pr94851-1.c.071i.analyzer.after     2021-01-05 11:04:26.915680635 -0500
    @@ -39,7 +39,7 @@ pamark ()
         goto <bb 6>; [5.50%]

       <bb 6> [local count: 114863531]:
    -  # p_2 = PHI <p_8(4), p_8(5)>
    +  # p_2 = PHI <0B(4), p_8(5)>
       # last_16 = PHI <last_10(4), last_10(5)>
       if (p_2 != 0B)
         goto <bb 7>; [70.00%]

i.e. the ranger EVRP patch adds the "knowledge" that p_2 is NULL when reached
from BB 4.

Comparing the .supergraph.eg.dot dumps I see that both before/after consider a
malloc leak, but after the EVRP patch it considers the path in which the loop
isn't entered due to p being NULL.  It's considering the shortest path through
the egraph as:

      24   │   while (p != (AMARK *)NULL && p->m_name != (char)c) {  <-- (1) p
NULL here, skipping the loop
      25   │     last = p;
      26   │     p = p->m_next;
      27   │   }
      28   │ 
      29   │   if (p != (AMARK *)NULL) { <-- (2) p non-NULL here, skipping the
malloc
      30   │     printf("over writing mark %c\n", c);
      31   │   } else {
      32   │     if ((p = (AMARK *)malloc(sizeof(AMARK))) == (AMARK *)NULL)
      ...
      43   │   p->m_name = (char)c; <-- (3) to here

So the improved PHI from EVRP means that we hit bug 96374, which means that we
reject the false positive, albeit for the wrong reasons.

I plan to remove the xfail for now, but am recording this information here
since the false leak may reappear if we fix bug 96374 without fixing bug 97072.

Reply via email to