public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Martin Sebor <msebor@gmail.com>
To: Marek Polacek <polacek@redhat.com>,
	 GCC Patches <gcc-patches@gcc.gnu.org>,
	Jason Merrill <jason@redhat.com>
Subject: Re: C++ PATCH for c++/69509 and c++/69516 (infinite recursion with invalid VLAs in constexpr functions)
Date: Fri, 29 Jan 2016 03:53:00 -0000	[thread overview]
Message-ID: <56AAE239.5010500@gmail.com> (raw)
In-Reply-To: <20160128203305.GE25193@redhat.com>

On 01/28/2016 01:33 PM, Marek Polacek wrote:
> This patch fixes some problems with VLAs and constexprs.  (The runtime aspect
> of this matter is being tracked in PR69517.)  It does two things:
>
> 1) Changes build_vec_init slightly to prevent the compiler from getting into
>     infinite recursion.  Currently, we emit the following sequence when we're
>     initializing e.g. n = 1; int a[n] = { 1, 2 }; (cleanup_point junk omitted):
>
>    int a[0:(sizetype) (SAVE_EXPR <(ssizetype) n + -1>)];
>    (void) (int[0:(sizetype) (SAVE_EXPR <(ssizetype) n + -1>)] *)   int * D.2256;
>    (void) (D.2256 = (int *) &a)
>      int * D.2257;
>    (void) (D.2257 = D.2256)
>      long int D.2258;
>    (void) (D.2258 = (long int) (SAVE_EXPR <(ssizetype) n + -1>)) // == 0
>    (void) (*D.2257 = 1)
>    (void)  ++D.2257
>    (void)  --D.2258	// == -1
>    (void) (*D.2257 = 2)
>    (void)  ++D.2257
>    (void)  --D.2258	// == -2
>
>    while (1)
>      {
>        if (D.2258 == -1)	// never triggers
> 	goto <D.2261>;
>        (void) (*D.2257 = 0)
>        (void)  ++D.2257
>        (void)  --D.2258;
>      }
>    <D.2261>:;
>    ...
>
>    So we first write the elements from the initializer and then we default-initialize
>    any remaining elements.  But the iterator == -1 check is never true for invalid
>    code, which means the compiler will get stuck in the while loop forever, leading
>    to crash -- it tries to cxx_eval_* the body of the loop over and over again.
>
>    Fixed by changing == -1 into <= -1; this should only ever happen for invalid code,
>    but we don't want to ICE in any case.
>
>    This also "fixes" the problem in PR69517 -- the program could get into infinite
>    recursion as well, because it was evaluating the sequence above at runtime. But
>    since it's invoking UB, it doesn't matter much.
>
> 2) Moves the check for "array subscript out of bound" a tad above, because for
>     invalid VLAs we can't rely on the bool "found" -- e.g. for the example above
>     it will find all indexes in the initializer, so "found" is true, which means
>     we wouldn't get to the out-of-bounds check below.

I haven't had time to study the code but I did apply the patch
and play with it a bit.  It sure does fix the infinite loop/
recursion problem!

That said, while the test case below is rejected with the array
being of type int (as it should be), it's accepted as is, with
the struct.  I don't know enough to tell if it's because of
the change you mention or if it's a latent bug.

The test case is also accepted with an invalid argument to foo
(negative or excessive), both which should be rejected as well.

You're clearly good and efficient at fixing things.  I seem to
have a knack for breaking them.  Please let me know if I should
open a new bug for this.

   struct A {
     constexpr A (int = 0) { }
     constexpr operator int () const { return 0; }
   };

   constexpr int foo (int n) {
     A a [n] = { 1, 2, 3, 4, 5, 6 };
     return a [99];
   }

   struct B { unsigned b: foo (1) + 1; };

Martin

      parent reply	other threads:[~2016-01-29  3:53 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-01-28 20:33 Marek Polacek
2016-01-28 22:51 ` Jason Merrill
2016-01-28 23:09   ` Marek Polacek
2016-01-29  3:53 ` Martin Sebor [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=56AAE239.5010500@gmail.com \
    --to=msebor@gmail.com \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=jason@redhat.com \
    --cc=polacek@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).