mirror of
https://github.com/gcc-mirror/gcc.git
synced 2026-05-06 14:59:39 +02:00
Fix [PR124230]
For a pointer array reference that is annotated with counted_by attribute,
such as:
struct annotated {
int *c __attribute__ ((counted_by (b)));
int b;
};
struct annotated *p = setup (10);
p->c[12] = 2; //out of bound access
the IR for p->c[12] is:
(.ACCESS_WITH_SIZE (p->c, &p->b, 0B, 4) + 48) = 2;
The current routine get_index_from_offset in c-family/c-ubsan.cc cannot
handle the integer constant offset "48" correctly.
The fix is to enhance "get_index_from_offset" to correctly handle the constant
offset.
PR c/124230
gcc/c-family/ChangeLog:
* c-ubsan.cc (get_index_from_offset): Handle the special case when
the offset is an integer constant.
gcc/testsuite/ChangeLog:
* gcc.dg/ubsan/pointer-counted-by-bounds-124230-char.c: New test.
* gcc.dg/ubsan/pointer-counted-by-bounds-124230-float.c: New test.
* gcc.dg/ubsan/pointer-counted-by-bounds-124230-struct.c: New test.
* gcc.dg/ubsan/pointer-counted-by-bounds-124230-union.c: New test.
* gcc.dg/ubsan/pointer-counted-by-bounds-124230.c: New test.
This commit is contained in:
@@ -659,6 +659,9 @@ get_factors_from_mul_expr (tree mult_expr, tree parent,
|
||||
ELEMENT_SIZE:
|
||||
(sizetype) SAVE_EXPR <n> * 4
|
||||
get the index as (long unsigned int) m, and return it.
|
||||
One special case is when the OFFSET is an integer constant, and the
|
||||
element_size is also an integer constant, we should get the index
|
||||
as OFFSET/element_size.
|
||||
The INDEX_P holds the pointer to the parent tree of the index,
|
||||
INDEX_N holds the position of the index in its parent. */
|
||||
|
||||
@@ -666,9 +669,19 @@ static tree
|
||||
get_index_from_offset (tree offset, tree *index_p,
|
||||
int *index_n, tree element_size)
|
||||
{
|
||||
if (TREE_CODE (offset) != MULT_EXPR)
|
||||
if (TREE_CODE (offset) != MULT_EXPR
|
||||
&& TREE_CODE (offset) != INTEGER_CST)
|
||||
return NULL_TREE;
|
||||
|
||||
if (TREE_CODE (offset) == INTEGER_CST
|
||||
&& TREE_CODE (element_size) != INTEGER_CST)
|
||||
return NULL_TREE;
|
||||
|
||||
if (TREE_CODE (offset) == INTEGER_CST
|
||||
&& TREE_CODE (element_size) == INTEGER_CST)
|
||||
return fold_build2 (EXACT_DIV_EXPR, TREE_TYPE (offset),
|
||||
offset, element_size);
|
||||
|
||||
auto_vec<factor_t> e_factors, o_factors;
|
||||
get_factors_from_mul_expr (element_size, NULL, -1, &e_factors);
|
||||
get_factors_from_mul_expr (offset, *index_p, *index_n, &o_factors);
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
/* Test the attribute counted_by for pointer fields and its usage in
|
||||
bounds sanitizer. */
|
||||
/* { dg-do run } */
|
||||
/* { dg-options "-fsanitize=bounds" } */
|
||||
/* { dg-output "index 10 out of bounds for type 'char \\\[\\\*\\\]'\[^\n\r]*(\n|\r\n|\r)" } */
|
||||
/* { dg-output "\[^\n\r]*index 11 out of bounds for type 'char \\\[\\\*\\\]'\[^\n\r]*(\n|\r\n|\r)" } */
|
||||
|
||||
#define PTR_TYPE char
|
||||
#include "pointer-counted-by-bounds-124230.c"
|
||||
@@ -0,0 +1,9 @@
|
||||
/* Test the attribute counted_by for pointer fields and its usage in
|
||||
bounds sanitizer. */
|
||||
/* { dg-do run } */
|
||||
/* { dg-options "-fsanitize=bounds" } */
|
||||
/* { dg-output "index 10 out of bounds for type 'float \\\[\\\*\\\]'\[^\n\r]*(\n|\r\n|\r)" } */
|
||||
/* { dg-output "\[^\n\r]*index 11 out of bounds for type 'float \\\[\\\*\\\]'\[^\n\r]*(\n|\r\n|\r)" } */
|
||||
|
||||
#define PTR_TYPE float
|
||||
#include "pointer-counted-by-bounds-124230.c"
|
||||
@@ -0,0 +1,61 @@
|
||||
/* Test the attribute counted_by for pointer fields and its usage in
|
||||
bounds sanitizer. */
|
||||
/* { dg-do run } */
|
||||
/* { dg-options "-fsanitize=bounds" } */
|
||||
/* { dg-output "index 10 out of bounds for type 'A \\\[\\\*\\\]'\[^\n\r]*(\n|\r\n|\r)" } */
|
||||
/* { dg-output "\[^\n\r]*index 11 out of bounds for type 'A \\\[\\\*\\\]'\[^\n\r]*(\n|\r\n|\r)" } */
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
struct A {
|
||||
int a;
|
||||
char *b;
|
||||
};
|
||||
#define PTR_TYPE struct A
|
||||
struct annotated {
|
||||
int b;
|
||||
PTR_TYPE *c __attribute__ ((counted_by (b)));
|
||||
} *p_array_annotated;
|
||||
|
||||
struct nested_annotated {
|
||||
PTR_TYPE *c __attribute__ ((counted_by (b)));
|
||||
struct {
|
||||
union {
|
||||
int b;
|
||||
float f;
|
||||
};
|
||||
int n;
|
||||
};
|
||||
} *p_array_nested_annotated;
|
||||
|
||||
void __attribute__((__noinline__)) setup (int annotated_count)
|
||||
{
|
||||
p_array_annotated
|
||||
= (struct annotated *) malloc (sizeof (struct annotated));
|
||||
p_array_annotated->c = (PTR_TYPE *) malloc (annotated_count * sizeof (PTR_TYPE));
|
||||
p_array_annotated->b = annotated_count;
|
||||
|
||||
p_array_nested_annotated
|
||||
= (struct nested_annotated *) malloc (sizeof (struct nested_annotated));
|
||||
p_array_nested_annotated->c = (PTR_TYPE *) malloc (sizeof (PTR_TYPE) * annotated_count);
|
||||
p_array_nested_annotated->b = annotated_count;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void cleanup ()
|
||||
{
|
||||
free (p_array_annotated->c);
|
||||
free (p_array_annotated);
|
||||
free (p_array_nested_annotated->c);
|
||||
free (p_array_nested_annotated);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
setup (10);
|
||||
p_array_annotated->c[10].a = 2;
|
||||
p_array_nested_annotated->c[11].a = 3;
|
||||
cleanup ();
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/* Test the attribute counted_by for pointer fields and its usage in
|
||||
bounds sanitizer. */
|
||||
/* { dg-do run } */
|
||||
/* { dg-options "-fsanitize=bounds" } */
|
||||
/* { dg-output "index 10 out of bounds for type 'A \\\[\\\*\\\]'\[^\n\r]*(\n|\r\n|\r)" } */
|
||||
/* { dg-output "\[^\n\r]*index 11 out of bounds for type 'A \\\[\\\*\\\]'\[^\n\r]*(\n|\r\n|\r)" } */
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
union A {
|
||||
int a;
|
||||
float b;
|
||||
};
|
||||
#define PTR_TYPE union A
|
||||
struct annotated {
|
||||
int b;
|
||||
PTR_TYPE *c __attribute__ ((counted_by (b)));
|
||||
} *p_array_annotated;
|
||||
|
||||
struct nested_annotated {
|
||||
PTR_TYPE *c __attribute__ ((counted_by (b)));
|
||||
struct {
|
||||
union {
|
||||
int b;
|
||||
float f;
|
||||
};
|
||||
int n;
|
||||
};
|
||||
} *p_array_nested_annotated;
|
||||
|
||||
void __attribute__((__noinline__)) setup (int annotated_count)
|
||||
{
|
||||
p_array_annotated
|
||||
= (struct annotated *) malloc (sizeof (struct annotated));
|
||||
p_array_annotated->c = (PTR_TYPE *) malloc (annotated_count * sizeof (PTR_TYPE));
|
||||
p_array_annotated->b = annotated_count;
|
||||
|
||||
p_array_nested_annotated
|
||||
= (struct nested_annotated *) malloc (sizeof (struct nested_annotated));
|
||||
p_array_nested_annotated->c = (PTR_TYPE *) malloc (sizeof (PTR_TYPE) * annotated_count);
|
||||
p_array_nested_annotated->b = annotated_count;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void cleanup ()
|
||||
{
|
||||
free (p_array_annotated->c);
|
||||
free (p_array_annotated);
|
||||
free (p_array_nested_annotated->c);
|
||||
free (p_array_nested_annotated);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
setup (10);
|
||||
p_array_annotated->c[10].a = 2;
|
||||
p_array_nested_annotated->c[11].a = 3;
|
||||
cleanup ();
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/* Test the attribute counted_by for pointer fields and its usage in
|
||||
bounds sanitizer. */
|
||||
/* { dg-do run } */
|
||||
/* { dg-options "-fsanitize=bounds" } */
|
||||
/* { dg-output "index 10 out of bounds for type 'int \\\[\\\*\\\]'\[^\n\r]*(\n|\r\n|\r)" } */
|
||||
/* { dg-output "\[^\n\r]*index 11 out of bounds for type 'int \\\[\\\*\\\]'\[^\n\r]*(\n|\r\n|\r)" } */
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifndef PTR_TYPE
|
||||
#define PTR_TYPE int
|
||||
#endif
|
||||
struct annotated {
|
||||
int b;
|
||||
PTR_TYPE *c __attribute__ ((counted_by (b)));
|
||||
} *p_array_annotated;
|
||||
|
||||
struct nested_annotated {
|
||||
PTR_TYPE *c __attribute__ ((counted_by (b)));
|
||||
struct {
|
||||
union {
|
||||
int b;
|
||||
float f;
|
||||
};
|
||||
int n;
|
||||
};
|
||||
} *p_array_nested_annotated;
|
||||
|
||||
void __attribute__((__noinline__)) setup (int annotated_count)
|
||||
{
|
||||
p_array_annotated
|
||||
= (struct annotated *) malloc (sizeof (struct annotated));
|
||||
p_array_annotated->c = (PTR_TYPE *) malloc (annotated_count * sizeof (PTR_TYPE));
|
||||
p_array_annotated->b = annotated_count;
|
||||
|
||||
p_array_nested_annotated
|
||||
= (struct nested_annotated *) malloc (sizeof (struct nested_annotated));
|
||||
p_array_nested_annotated->c = (PTR_TYPE *) malloc (sizeof (PTR_TYPE) * annotated_count);
|
||||
p_array_nested_annotated->b = annotated_count;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void cleanup ()
|
||||
{
|
||||
free (p_array_annotated->c);
|
||||
free (p_array_annotated);
|
||||
free (p_array_nested_annotated->c);
|
||||
free (p_array_nested_annotated);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
setup (10);
|
||||
p_array_annotated->c[10] = 2;
|
||||
p_array_nested_annotated->c[11] = 3;
|
||||
cleanup ();
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user