Cydox wrote:

> The point of __counted_by is precisely to supplement the normal standard 
> rules: specifically, if you have counted_by, the size of the flexible array 
> is precisely the size specified by the attribute. Not whatever size is 
> implied by the access. Otherwise, it would be illegal for __bdos to use the 
> counted_by attribute at all. The size of the array can't change based on how 
> __bdos is queried.

Let's say we simply define a `count` that is inconsistent with the size of the 
object as undefined behavior.

I agree that the size of the flexible array member when the __counted_by 
attribute is used is exactly count multiplied by size of each element. And this 
PR changes none of that.

```C
__builtin_dynamic_object_size(acl->a_entries)
```

Still does exactly that and therefore bounds-checking even an off-by-1 scenario 
will work correctly.

This PR only changes the behavior of:

```C
__builtin_dynamic_object_size(acl)
```

Here you are not asking for the size of the FAM, but of the whole struct 
object. The size of that object is whatever you gave to `malloc`. **There are 
multiple possible sizes you could have given to `malloc` that are consistent 
with the same `count`**, because the standard says that "it behaves as if that 
member were replaced with the longest array (with the same element type) that 
would not make the structure larger than the object being accessed". As long as 
the elements of the array are larger than 1 byte there are multiple `malloc` 
sizes that have the same correct `count`.

This is different when you ask for the size of the FAM itself, each size of the 
FAM only has a single correct value of `count`.

This is why I believe the gcc behavior is correct. When it knows the size given 
to `malloc` it uses that. When it doesn't know that it simply returns INT_MAX. 
When you ask gcc for the `__bdos` of the FAM it will use the `count` to 
calculate the size.


> `sizeof(struct s) + p->count * sizeof(*p->array))` is a weird compromise: 
> it's not unbounded, but it's larger than the size specified by the standard.

I agree that it is a weird compromise, I'm thinking clang should to with the 
gcc behavior here instead.

---

However:
> but it's larger than the size specified by the standard

Can you tell me what the size specified by the standard is? Let's say for these 
two examples:
(1)
```
struct posix_acl *acl = malloc(sizeof(struct posix_acl) + sizeof(struct 
posix_acl_entry) * 1);
acl.a_count = 1;
```
(2)
```
struct posix_acl *acl = malloc(offsetof(struct posix_acl, a_entries) + 
sizeof(struct posix_acl_entry) * 1);
acl.a_count = 1;
```

What is the size of the object `acl`  points to according to the C standard?

My answers:
(1): 40
(2): 36



https://github.com/llvm/llvm-project/pull/111015
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to