[clang] [Clang] Fix __builtin_dynamic_object_size off by 4 (PR #111015)

Jan Hendrik Farr via cfe-commits cfe-commits at lists.llvm.org
Thu Oct 3 09:30:00 PDT 2024


Cydox wrote:

I'm not 100% sure if the gcc or the clang behavior is currently correct. However, I'm gonna argue that gcc has it correct.

gcc currently says that the __bdos of struct containing a flexible array member is:

```
sizeof(<whole struct>) + sizeof(<flexible array element>) * <count>
```

clang however does the following:

```
max(sizeof(<whole struct>), offsetof(<flexible array member>) + sizeof(<flexible array element>) * <count>)
```


The kernel assumes the gcc behvaior in places like linux/fs/posix_acl.c:

```C
struct posix_acl *
posix_acl_clone(const struct posix_acl *acl, gfp_t flags)
{
	struct posix_acl *clone = NULL;

	if (acl) {
		int size = sizeof(struct posix_acl) + acl->a_count *
		           sizeof(struct posix_acl_entry);
		clone = kmemdup(acl, size, flags);
		if (clone)
			refcount_set(&clone->a_refcount, 1);
	}
	return clone;
}
EXPORT_SYMBOL_GPL(posix_acl_clone);
```

This is the code that triggers the problem in [1]. The way I see it, this code should work, as you also allocate `struct posix_acl` with the same `sizeof(struct posix_acl) + acl->a_count * sizeof(struct posix_acl_entry)` as an argument to malloc (or in-kernel equivalent).

Based on the C standard the size of that object is the size passed to
malloc. See bottom of page 348 [2].

[1] https://lore.kernel.org/linux-kernel/3D0816D1-0807-4D37-8D5F-3C55CA910FAA@linux.dev/
[2] https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1548.pdf

https://github.com/llvm/llvm-project/pull/111015


More information about the cfe-commits mailing list