aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Botcazou <ebotcazou@adacore.com>2024-05-27 16:31:20 +0200
committerMarc Poulhiès <poulhies@adacore.com>2024-06-21 10:34:23 +0200
commitd69c53f73dae181c79f6ec6c7276a172476a2728 (patch)
treea8b3bbf854e45892067954889819e4fcd04b707b
parent9aa8324e8a2c992593591d965b3e2d527ed891d3 (diff)
downloadgcc-d69c53f73dae181c79f6ec6c7276a172476a2728.zip
gcc-d69c53f73dae181c79f6ec6c7276a172476a2728.tar.gz
gcc-d69c53f73dae181c79f6ec6c7276a172476a2728.tar.bz2
ada: Fix bogus Address Sanitizer stack-buffer-overflow on packed record equality
We set DECL_BIT_FIELD optimistically during the translation of record types and clear it afterward if needed, but fail to clear other attributes in the latter case, which fools the logic of the Address Sanitizer. gcc/ada/ * gcc-interface/utils.cc (clear_decl_bit_field): New function. (finish_record_type): Call clear_decl_bit_field instead of clearing DECL_BIT_FIELD manually.
-rw-r--r--gcc/ada/gcc-interface/utils.cc26
1 files changed, 19 insertions, 7 deletions
diff --git a/gcc/ada/gcc-interface/utils.cc b/gcc/ada/gcc-interface/utils.cc
index 771cb1a..0eb9af8 100644
--- a/gcc/ada/gcc-interface/utils.cc
+++ b/gcc/ada/gcc-interface/utils.cc
@@ -2002,6 +2002,21 @@ finish_fat_pointer_type (tree record_type, tree field_list)
TYPE_CONTAINS_PLACEHOLDER_INTERNAL (record_type) = 2;
}
+/* Clear DECL_BIT_FIELD flag and associated markers on FIELD, which is a field
+ of aggregate type TYPE. */
+
+static void
+clear_decl_bit_field (tree field, tree type)
+{
+ DECL_BIT_FIELD (field) = 0;
+ DECL_BIT_FIELD_TYPE (field) = NULL_TREE;
+
+ /* DECL_BIT_FIELD_REPRESENTATIVE is not defined for QUAL_UNION_TYPE since
+ it uses the same slot as DECL_QUALIFIER. */
+ if (TREE_CODE (type) != QUAL_UNION_TYPE)
+ DECL_BIT_FIELD_REPRESENTATIVE (field) = NULL_TREE;
+}
+
/* Given a record type RECORD_TYPE and a list of FIELD_DECL nodes FIELD_LIST,
finish constructing the record or union type. If REP_LEVEL is zero, this
record has no representation clause and so will be entirely laid out here.
@@ -2112,7 +2127,7 @@ finish_record_type (tree record_type, tree field_list, int rep_level,
if (TYPE_ALIGN (record_type) >= align)
{
SET_DECL_ALIGN (field, MAX (DECL_ALIGN (field), align));
- DECL_BIT_FIELD (field) = 0;
+ clear_decl_bit_field (field, record_type);
}
else if (!had_align
&& rep_level == 0
@@ -2122,7 +2137,7 @@ finish_record_type (tree record_type, tree field_list, int rep_level,
{
SET_TYPE_ALIGN (record_type, align);
SET_DECL_ALIGN (field, MAX (DECL_ALIGN (field), align));
- DECL_BIT_FIELD (field) = 0;
+ clear_decl_bit_field (field, record_type);
}
}
@@ -2130,7 +2145,7 @@ finish_record_type (tree record_type, tree field_list, int rep_level,
if (!STRICT_ALIGNMENT
&& DECL_BIT_FIELD (field)
&& value_factor_p (pos, BITS_PER_UNIT))
- DECL_BIT_FIELD (field) = 0;
+ clear_decl_bit_field (field, record_type);
}
/* Clear DECL_BIT_FIELD_TYPE for a variant part at offset 0, it's simply
@@ -2453,10 +2468,7 @@ rest_of_record_type_compilation (tree record_type)
avoid generating useless attributes for the field in DWARF. */
if (DECL_SIZE (old_field) == TYPE_SIZE (field_type)
&& value_factor_p (pos, BITS_PER_UNIT))
- {
- DECL_BIT_FIELD (new_field) = 0;
- DECL_BIT_FIELD_TYPE (new_field) = NULL_TREE;
- }
+ clear_decl_bit_field (new_field, new_record_type);
DECL_CHAIN (new_field) = TYPE_FIELDS (new_record_type);
TYPE_FIELDS (new_record_type) = new_field;