This set of patches has been committed today:

https://gcc.gnu.org/pipermail/gcc-cvs/2025-August/432733.html
https://gcc.gnu.org/pipermail/gcc-cvs/2025-August/432734.html
https://gcc.gnu.org/pipermail/gcc-cvs/2025-August/432735.html
https://gcc.gnu.org/pipermail/gcc-cvs/2025-August/432736.html

Qing

> On Aug 11, 2025, at 11:01, Qing Zhao <qing.z...@oracle.com> wrote:
> 
> Hi, a status update on this patch set:
> 
> [PATCH v9 1/4] Extend "counted_by" attribute to pointer fields of structures.
> [PATCH v9 2/4] Use the counted_by attribute of pointers in 
> builtinin-object-size
> [PATCH v9 3/4] Use the counted_by attribute of pointers in array bound 
> checker.
> [PATCH v9 4/4] Generate a call to a .ACCESS_WITH_SIZE for a FAM with 
> counted_by attribute only when it's read from.
> 
> Among these 4 patches, #1, #3 and #4 have been approved by Joseph.
> #2 is a test case only patch, no any change needed in middle-end. Except 
> gcc.dg/pr120929.c, which is a new test case for
> PR120929 and written by Siddhesh, all the other test cases keep the same as 
> the version 7 of this patch.
> 
> I plan to commit the whole set this Friday if no further comments or 
> objections. 
> 
> Thanks a lot for all the help.
> 
> Qing
> 
>> On Aug 1, 2025, at 14:11, Qing Zhao <qing.z...@oracle.com> wrote:
>> 
>> Hi,
>> 
>> This is the 9th version of the patch set to extend "counted_by" attribute
>> to pointer fields of structures, which fixes PR120929:
>> 
>> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120929
>> 
>> The 7th version of the patch has been committed into trunk, but triggered
>> PR120929. I reverted the patches from trunk due to PR120929.  
>> 
>> In order to fix PR120929, we agreed on the following solution:
>> 
>> for a pointer field with counted_by attribute:
>> 
>> struct S {
>> int n;
>> int *p __attribute__((counted_by(n)));
>> } *f;
>> 
>> when generating call to .ACCESS_WITH_SIZE for f->p, instead of generating
>> *.ACCESS_WITH_SIZE (&f->p, &f->n,...)
>> 
>> in the 7th patch,
>> 
>> We should generate
>> .ACCESS_WITH_SIZE (f->p, &f->n,...)
>> 
>> i.e., 
>> the return type and the type of the first argument of the call is the 
>>  original pointer type in this version,
>>  instead of the pointer to the original pointer type in the 7th version;
>> 
>> However, this code generation might bring undefined behavior into the
>> applicaiton if the call to .ACCESS_WITH_SIZE is generated for a pointer
>> field reference when this refernece is written to.
>> 
>> For example:
>> 
>> f->p = malloc (size);
>> 
>> ***** the IL for the above is:
>> 
>> tmp1 = f->p;
>> tmp2 = &f->n;
>> tmp3 = .ACCESS_WITH_SIZE (tmp1, tmp2, ...);
>> tmp4 = malloc (size);
>> tmp3 = tmp4;
>> 
>> In the above, in order to generate a call to .ACCESS_WITH_SIZE for the 
>> pointer
>> reference f->p,  the new GIMPLE tmp1 = f->p is necessary to pass the value of
>> the pointer f->p to the call to .ACCESS_WITH_SIZE. However, this new GIMPLE 
>> is
>> the one that brings UB into the application since the value of f->p is not
>> initialized yet when it is assigned to "tmp1".
>> 
>> the above IL will be expanded to the following when .ACCESS_WITH_SIZE is 
>> expanded
>> to its first argument:
>> 
>> tmp1 = f->p;
>> tmp2 = &f->n;
>> tmp3 = tmp1;
>> tmp4 = malloc (size);
>> tmp3 = tmp4;
>> 
>> the final optimized IL will be:
>> 
>> tmp3 = f->p;
>> tmp3 = malloc (size);;
>> 
>> As a result, the f->p will NOT be set correctly to the pointer
>> returned by malloc (size).
>> 
>> Due to this potential issue, We will need to selectively generate the call to
>> .ACCESS_WITH_SIZE for f->p according to whether it's a read or a write.
>> 
>> We will only generate call to .ACCESS_WITH_SIZE for f->p when it's a read in
>> C FE.
>> 
>> In addition to the above major changes, other minor changes include:
>> 
>> A. add the testing case pr120929.c, and some more testing cases.
>> B. delete the change in gcc/tree-object-size.cc, no any change is
>>  needed now in middle-end;
>> C. adjust the patch for using the counted_by attribute in array bound checker
>>  per the new format of .ACCESS_WITH_SIZE.
>> D. add a new 4th patch: 
>>   Generate a call to a .ACCESS_WITH_SIZE for a FAM with counted_by attribute
>>   only when it's read from.
>> 
>> In patch #1, the changes in c-attribs.cc, c-decl.cc and doc/extend.texi are
>> exactly the same as the 7th version, which has been reviewed and approved by
>> Joseph. The other changes in c-tree.h, c-parser.cc, c-typeck.cc are new 
>> changes
>> for the new code generation for call to .ACCESS_WITH_SIZE for pointers. Also,
>> I added two more new testing cases, pointer-counted-by-8.c and
>> pointer-counted-by-9.c.
>> 
>> In patch #2, compared to 7th version, the change in gcc/tree-object-size.cc
>> is completely deleted. no need change middle end to use the counted_by
>> of pointers in tree-object-size.cc. except the new testing case pr120929.c,
>> all the other testing cases are kept the same as tghe 7th version.
>> 
>> In Patch #3, compared to the 7th version, the following is the diff:
>> 
>> =============================
>> From ff3dd7ebc0e41dff13ce47aefdcef609aac541fa Mon Sep 17 00:00:00 2001
>> From: Qing Zhao <qing.z...@oracle.com>
>> Date: Fri, 11 Jul 2025 14:54:21 +0000
>> Subject: [PATCH] fix ubsan per the new design
>> 
>> ---
>> gcc/c-family/c-gimplify.cc |  3 +--
>> gcc/c-family/c-ubsan.cc    | 27 +++++++++++----------------
>> 2 files changed, 12 insertions(+), 18 deletions(-)
>> 
>> diff --git a/gcc/c-family/c-gimplify.cc b/gcc/c-family/c-gimplify.cc
>> index e905059708f7..131eca8297f8 100644
>> --- a/gcc/c-family/c-gimplify.cc
>> +++ b/gcc/c-family/c-gimplify.cc
>> @@ -74,8 +74,7 @@ static bool
>> is_address_with_access_with_size (tree tp)
>> {
>>  if (TREE_CODE (tp) == POINTER_PLUS_EXPR
>> -      && (TREE_CODE (TREE_OPERAND (tp, 0)) == INDIRECT_REF)
>> -      && (is_access_with_size_p (TREE_OPERAND (TREE_OPERAND (tp, 0), 0))))
>> +      && is_access_with_size_p (TREE_OPERAND (tp, 0)))
>> return true;
>>  return false;
>> }
>> diff --git a/gcc/c-family/c-ubsan.cc b/gcc/c-family/c-ubsan.cc
>> index 8d44b4ba39b4..97bb5459fbfc 100644
>> --- a/gcc/c-family/c-ubsan.cc
>> +++ b/gcc/c-family/c-ubsan.cc
>> @@ -550,7 +550,7 @@ ubsan_instrument_bounds (location_t loc, tree array, 
>> tree *index,
>> 
>> 
>> /* Instrument array bounds for the pointer array address which is
>> -   an INDIRECT_REF to the call to .ACCESS_WITH_SIZE.  We create special
>> +   a call to .ACCESS_WITH_SIZE.  We create special
>>   builtin, that gets expanded in the sanopt pass, and make an array
>>   dimention of it.  POINTER_ADDR is the pointer array's base address.
>>   *INDEX is an index to the array.
>> @@ -563,8 +563,7 @@ ubsan_instrument_bounds_pointer_address (location_t loc, 
>> tree pointer_addr,
>> tree *index,
>> bool ignore_off_by_one)
>> {
>> -  gcc_assert (TREE_CODE (pointer_addr) == INDIRECT_REF);
>> -  tree call = TREE_OPERAND (pointer_addr, 0);
>> +  tree call = pointer_addr;
>>  if (!is_access_with_size_p (call))
>>    return NULL_TREE;
>>  tree bound = get_bound_from_access_with_size (call);
>> @@ -593,7 +592,7 @@ ubsan_instrument_bounds_pointer_address (location_t loc, 
>> tree pointer_addr,
>>  tree itype = build_range_type (sizetype, size_zero_node, NULL_TREE);
>>  /* The array's element type can be get from the return type of the call to
>>     .ACCESS_WITH_SIZE.  */
>> -  tree element_type = TREE_TYPE (TREE_TYPE (TREE_TYPE (call)));
>> +  tree element_type = TREE_TYPE (TREE_TYPE (call));
>>  tree array_type = build_array_type (element_type, itype);
>>  /* Create a "(T *) 0" tree node to describe the array type.  */
>>  tree zero_with_type = build_int_cst (build_pointer_type (array_type), 0);
>> @@ -702,7 +701,7 @@ get_index_from_offset (tree offset, tree *index_p,
>> }
>> 
>> /* For an pointer + offset computation expression, such as,
>> -   *.ACCESS_WITH_SIZE (p->c, &p->b, 1, 0, -1, 0B)
>> +   .ACCESS_WITH_SIZE (p->c, &p->b, 1, 0, -1, 0B)
>>    + (sizetype) ((long unsigned int) index * 4
>>   Return the index of this pointer array reference,
>>   set the parent tree of INDEX to *INDEX_P.
>> @@ -714,15 +713,13 @@ get_index_from_pointer_addr_expr (tree pointer, tree 
>> *index_p, int *index_n)
>> {
>>  *index_p = NULL_TREE;
>>  *index_n = -1;
>> -  if (TREE_CODE (TREE_OPERAND (pointer, 0)) != INDIRECT_REF)
>> -    return NULL_TREE;
>> -  tree call = TREE_OPERAND (TREE_OPERAND (pointer, 0), 0);
>> +  tree call = TREE_OPERAND (pointer, 0);
>>  if (!is_access_with_size_p (call))
>>    return NULL_TREE;
>> 
>>  /* Get the pointee type of the call to .ACCESS_WITH_SIZE.
>>     This should be the element type of the pointer array.  */
>> -  tree pointee_type = TREE_TYPE (TREE_TYPE (TREE_TYPE (call)));
>> +  tree pointee_type = TREE_TYPE (TREE_TYPE (call));
>>  tree pointee_size = TYPE_SIZE_UNIT (pointee_type);
>> 
>>  tree index_exp = TREE_OPERAND (pointer, 1);
>> @@ -758,11 +755,11 @@ get_index_from_pointer_addr_expr (tree pointer, tree 
>> *index_p, int *index_n)
>> /* Return TRUE when the EXPR is a pointer array address that could be
>>   instrumented.
>>   We only instrument an address computation similar as the following:
>> -      *.ACCESS_WITH_SIZE (p->c, &p->b, 1, 0, -1, 0B)
>> +      .ACCESS_WITH_SIZE (p->c, &p->b, 1, 0, -1, 0B)
>> + (sizetype) ((long unsigned int) index * 4)
>>   if the EXPR is instrumentable, return TRUE and
>>   set the index to *INDEX.
>> -   set the *.ACCESS_WITH_SIZE to *BASE.
>> +   set the .ACCESS_WITH_SIZE to *BASE.
>>   set the parent tree of INDEX to *INDEX_P.
>>   set the operand position of the INDEX in the parent tree to INDEX_N.  */
>> 
>> @@ -772,17 +769,15 @@ is_instrumentable_pointer_array_address (tree expr, 
>> tree *base,
>> int *index_n)
>> {
>>  /* For a poiner array address as:
>> - (*.ACCESS_WITH_SIZE (p->c, &p->b, 1, 0, -1, 0B)
>> + .ACCESS_WITH_SIZE (p->c, &p->b, 1, 0, -1, 0B)
>> + (sizetype) ((long unsigned int) index * 4)
>> -     op0 is the call to *.ACCESS_WITH_SIZE;
>> +     op0 is the call to .ACCESS_WITH_SIZE;
>>     op1 is the index.  */
>>  if (TREE_CODE (expr) != POINTER_PLUS_EXPR)
>>    return false;
>> 
>>  tree op0 = TREE_OPERAND (expr, 0);
>> -  if (TREE_CODE (op0) != INDIRECT_REF)
>> -    return false;
>> -  if (!is_access_with_size_p (TREE_OPERAND (op0, 0)))
>> +  if (!is_access_with_size_p (op0))
>>    return false;
>>  tree op1 = get_index_from_pointer_addr_expr (expr, index_p, index_n);
>>  if (op1 != NULL_TREE)
>> -- 
>> 2.43.5
>> 
>> The whole patch set has been bootstrapped and regression tested on both 
>> aarch64 and x86.
>> 
>> Okay for trunk?
>> 
>> Thanks a lot.
>> 
>> Qing
> 

Reply via email to