Patchwork Handle bit-fields in ubsan.c (PR sanitizer/58413)

login
register
mail settings
Submitter Marek Polacek
Date Sept. 16, 2013, 3:59 p.m.
Message ID <20130916155927.GD23899@redhat.com>
Download mbox | patch
Permalink /patch/275235/
State New
Headers show

Comments

Marek Polacek - Sept. 16, 2013, 3:59 p.m.
This patch ought to fix the unexpected size of type 'long long unsigned int:40'
issue in PR58413.  Since libubsan will fail when the precision of a type
is not 32/64/128, we can't pass the width of a bitfield, instead we should pass
the TYPE_SIZE of the base type, I guess.

What is not very nice is that the type we get in the bit-field case
doesn't have the TYPE_NAME set, so we'll have to live with "<unnamed>"
(renamed, since I find it better than "<unknown>").

Regtested/ran bootstrap-ubsan on x86_64-linux.

Ok for trunk?

2013-09-16  Marek Polacek  <polacek@redhat.com>

	PR sanitizer/58413
	* ubsan.c (ubsan_type_descriptor): Change TYPE_PRECISION of
	a bit-field type to its TYPE_SIZE.  Tweak type name.

	* c-c++-common/ubsan/shift-4.c: New test.


	Marek
Jakub Jelinek - Sept. 16, 2013, 4:04 p.m.
On Mon, Sep 16, 2013 at 05:59:28PM +0200, Marek Polacek wrote:
> Regtested/ran bootstrap-ubsan on x86_64-linux.

That looks wrong.  ubsan_type_descriptor shouldn't change TYPE_PRECISION of
the type it has been called with, whether type is a bitfield or not can
change what typedescriptor is generated, but not unrelated code.

> 2013-09-16  Marek Polacek  <polacek@redhat.com>
> 
> 	PR sanitizer/58413
> 	* ubsan.c (ubsan_type_descriptor): Change TYPE_PRECISION of
> 	a bit-field type to its TYPE_SIZE.  Tweak type name.
> 
> 	* c-c++-common/ubsan/shift-4.c: New test.
> 
> --- gcc/ubsan.c.mp2	2013-09-16 16:55:26.653579402 +0200
> +++ gcc/ubsan.c	2013-09-16 16:57:29.192016988 +0200
> @@ -251,6 +251,10 @@ ubsan_type_descriptor (tree type)
>    /* See through any typedefs.  */
>    type = TYPE_MAIN_VARIANT (type);
>  
> +  /* Handle bit-fields.  */
> +  if (compare_tree_int (TYPE_SIZE (type), TYPE_PRECISION (type) == 1))
> +    TYPE_PRECISION (type) = tree_low_cst (TYPE_SIZE (type), 1);
> +
>    tree decl = decl_for_type_lookup (type);
>    if (decl != NULL_TREE)
>      return decl;
> @@ -270,7 +274,7 @@ ubsan_type_descriptor (tree type)
>  	tname = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)));
>      }
>    else
> -    tname = "<unknown>";
> +    tname = "<unnamed>";
>  
>    if (TREE_CODE (type) == INTEGER_TYPE)
>      {
> --- gcc/testsuite/c-c++-common/ubsan/shift-4.c.mp2	2013-09-16 17:01:55.852982631 +0200
> +++ gcc/testsuite/c-c++-common/ubsan/shift-4.c	2013-09-16 17:32:32.114891611 +0200
> @@ -0,0 +1,14 @@
> +/* { dg-do run } */
> +/* { dg-options "-fsanitize=shift -w" } */
> +
> +struct S { unsigned long long int b:40; } s;
> +
> +int
> +main ()
> +{
> +  s.b = 2;
> +  s.b <<= 120;
> +  return 0;
> +}
> +
> +/* { dg-output "shift exponent 120 is too large\[^\n\r]*(\n|\r\n|\r)" } */
> 
> 	Marek

	Jakub

Patch

--- gcc/ubsan.c.mp2	2013-09-16 16:55:26.653579402 +0200
+++ gcc/ubsan.c	2013-09-16 16:57:29.192016988 +0200
@@ -251,6 +251,10 @@  ubsan_type_descriptor (tree type)
   /* See through any typedefs.  */
   type = TYPE_MAIN_VARIANT (type);
 
+  /* Handle bit-fields.  */
+  if (compare_tree_int (TYPE_SIZE (type), TYPE_PRECISION (type) == 1))
+    TYPE_PRECISION (type) = tree_low_cst (TYPE_SIZE (type), 1);
+
   tree decl = decl_for_type_lookup (type);
   if (decl != NULL_TREE)
     return decl;
@@ -270,7 +274,7 @@  ubsan_type_descriptor (tree type)
 	tname = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)));
     }
   else
-    tname = "<unknown>";
+    tname = "<unnamed>";
 
   if (TREE_CODE (type) == INTEGER_TYPE)
     {
--- gcc/testsuite/c-c++-common/ubsan/shift-4.c.mp2	2013-09-16 17:01:55.852982631 +0200
+++ gcc/testsuite/c-c++-common/ubsan/shift-4.c	2013-09-16 17:32:32.114891611 +0200
@@ -0,0 +1,14 @@ 
+/* { dg-do run } */
+/* { dg-options "-fsanitize=shift -w" } */
+
+struct S { unsigned long long int b:40; } s;
+
+int
+main ()
+{
+  s.b = 2;
+  s.b <<= 120;
+  return 0;
+}
+
+/* { dg-output "shift exponent 120 is too large\[^\n\r]*(\n|\r\n|\r)" } */