diff mbox

Fix ICEs when -fsanitize={undefined,address,thread} is used during -c -flto but not during the final link (PR sanitizer/78708)

Message ID 20161209193026.GH3541@tucnak.redhat.com
State New
Headers show

Commit Message

Jakub Jelinek Dec. 9, 2016, 7:30 p.m. UTC
Hi!

If some TUs are compiled with -flto -fsanitize={undefined,address} or
-fsanitize=thread, there might be some internal calls in them which require
sanopt pass to lower them.  If the final link is performed without
the corresponding -fsanitize=* options (user bug), that pass might not be
run at all and we'd ICE.  With this patch we throw away unexpected sanitizer
ifns and so worst case the final link will fail because of missing libasan,
libubsan or libtsan symbols.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2016-12-09  Jakub Jelinek  <jakub@redhat.com>

	PR sanitizer/78708
	* lto-streamer-in.c (input_function): In addition to debug stmts
	without -g, remove IFN_*SAN_* calls if corresponding flag_sanitize
	bit is not enabled.


	Jakub

Comments

Richard Biener Dec. 10, 2016, 6:19 a.m. UTC | #1
On December 9, 2016 8:30:26 PM GMT+01:00, Jakub Jelinek <jakub@redhat.com> wrote:
>Hi!
>
>If some TUs are compiled with -flto -fsanitize={undefined,address} or
>-fsanitize=thread, there might be some internal calls in them which
>require
>sanopt pass to lower them.  If the final link is performed without
>the corresponding -fsanitize=* options (user bug), that pass might not
>be
>run at all and we'd ICE.  With this patch we throw away unexpected
>sanitizer
>ifns and so worst case the final link will fail because of missing
>libasan,
>libubsan or libtsan symbols.
>
>Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

OK.

Richard.

>2016-12-09  Jakub Jelinek  <jakub@redhat.com>
>
>	PR sanitizer/78708
>	* lto-streamer-in.c (input_function): In addition to debug stmts
>	without -g, remove IFN_*SAN_* calls if corresponding flag_sanitize
>	bit is not enabled.
>
>--- gcc/lto-streamer-in.c.jj	2016-10-31 13:28:11.000000000 +0100
>+++ gcc/lto-streamer-in.c	2016-12-09 14:54:12.050362649 +0100
>@@ -1110,15 +1110,59 @@ input_function (tree fn_decl, struct dat
>       while (!gsi_end_p (bsi))
> 	{
> 	  gimple *stmt = gsi_stmt (bsi);
>+	  bool remove = false;
> 	  /* If we're recompiling LTO objects with debug stmts but
> 	     we're not supposed to have debug stmts, remove them now.
> 	     We can't remove them earlier because this would cause uid
> 	     mismatches in fixups, but we can do it at this point, as
>-	     long as debug stmts don't require fixups.  */
>-	  if (!MAY_HAVE_DEBUG_STMTS && !flag_wpa && is_gimple_debug (stmt))
>+	     long as debug stmts don't require fixups.
>+	     Similarly remove all IFN_*SAN_* internal calls   */
>+	  if (!flag_wpa)
>+	    {
>+	      if (!MAY_HAVE_DEBUG_STMTS && is_gimple_debug (stmt))
>+		remove = true;
>+	      if (is_gimple_call (stmt)
>+		  && gimple_call_internal_p (stmt))
>+		{
>+		  switch (gimple_call_internal_fn (stmt))
>+		    {
>+		    case IFN_UBSAN_NULL:
>+		      if ((flag_sanitize
>+			  & (SANITIZE_NULL | SANITIZE_ALIGNMENT)) == 0)
>+			remove = true;
>+		      break;
>+		    case IFN_UBSAN_BOUNDS:
>+		      if ((flag_sanitize & SANITIZE_BOUNDS) == 0)
>+			remove = true;
>+		      break;
>+		    case IFN_UBSAN_VPTR:
>+		      if ((flag_sanitize & SANITIZE_VPTR) == 0)
>+			remove = true;
>+		      break;
>+		    case IFN_UBSAN_OBJECT_SIZE:
>+		      if ((flag_sanitize & SANITIZE_OBJECT_SIZE) == 0)
>+			remove = true;
>+		      break;
>+		    case IFN_ASAN_MARK:
>+		      if ((flag_sanitize & SANITIZE_ADDRESS) == 0)
>+			remove = true;
>+		      break;
>+		    case IFN_TSAN_FUNC_EXIT:
>+		      if ((flag_sanitize & SANITIZE_THREAD) == 0)
>+			remove = true;
>+		      break;
>+		    default:
>+		      break;
>+		    }
>+		  gcc_assert (!remove || gimple_call_lhs (stmt) == NULL_TREE);
>+		}
>+	    }
>+	  if (remove)
> 	    {
> 	      gimple_stmt_iterator gsi = bsi;
> 	      gsi_next (&bsi);
>+	      unlink_stmt_vdef (stmt);
>+	      release_defs (stmt);
> 	      gsi_remove (&gsi, true);
> 	    }
> 	  else
>
>	Jakub
diff mbox

Patch

--- gcc/lto-streamer-in.c.jj	2016-10-31 13:28:11.000000000 +0100
+++ gcc/lto-streamer-in.c	2016-12-09 14:54:12.050362649 +0100
@@ -1110,15 +1110,59 @@  input_function (tree fn_decl, struct dat
       while (!gsi_end_p (bsi))
 	{
 	  gimple *stmt = gsi_stmt (bsi);
+	  bool remove = false;
 	  /* If we're recompiling LTO objects with debug stmts but
 	     we're not supposed to have debug stmts, remove them now.
 	     We can't remove them earlier because this would cause uid
 	     mismatches in fixups, but we can do it at this point, as
-	     long as debug stmts don't require fixups.  */
-	  if (!MAY_HAVE_DEBUG_STMTS && !flag_wpa && is_gimple_debug (stmt))
+	     long as debug stmts don't require fixups.
+	     Similarly remove all IFN_*SAN_* internal calls   */
+	  if (!flag_wpa)
+	    {
+	      if (!MAY_HAVE_DEBUG_STMTS && is_gimple_debug (stmt))
+		remove = true;
+	      if (is_gimple_call (stmt)
+		  && gimple_call_internal_p (stmt))
+		{
+		  switch (gimple_call_internal_fn (stmt))
+		    {
+		    case IFN_UBSAN_NULL:
+		      if ((flag_sanitize
+			  & (SANITIZE_NULL | SANITIZE_ALIGNMENT)) == 0)
+			remove = true;
+		      break;
+		    case IFN_UBSAN_BOUNDS:
+		      if ((flag_sanitize & SANITIZE_BOUNDS) == 0)
+			remove = true;
+		      break;
+		    case IFN_UBSAN_VPTR:
+		      if ((flag_sanitize & SANITIZE_VPTR) == 0)
+			remove = true;
+		      break;
+		    case IFN_UBSAN_OBJECT_SIZE:
+		      if ((flag_sanitize & SANITIZE_OBJECT_SIZE) == 0)
+			remove = true;
+		      break;
+		    case IFN_ASAN_MARK:
+		      if ((flag_sanitize & SANITIZE_ADDRESS) == 0)
+			remove = true;
+		      break;
+		    case IFN_TSAN_FUNC_EXIT:
+		      if ((flag_sanitize & SANITIZE_THREAD) == 0)
+			remove = true;
+		      break;
+		    default:
+		      break;
+		    }
+		  gcc_assert (!remove || gimple_call_lhs (stmt) == NULL_TREE);
+		}
+	    }
+	  if (remove)
 	    {
 	      gimple_stmt_iterator gsi = bsi;
 	      gsi_next (&bsi);
+	      unlink_stmt_vdef (stmt);
+	      release_defs (stmt);
 	      gsi_remove (&gsi, true);
 	    }
 	  else