[clang] [Clang] Implement the 'counted_by' attribute (PR #76348)

Kees Cook via cfe-commits cfe-commits at lists.llvm.org
Tue Jan 9 15:42:35 PST 2024


kees wrote:

> @kees, the issue should be fixed with the newest push.

Nice! This is so extremely close. It fixed all but 1 instance in the torture testing. The remaining seems to be union order sensitive. O_o This arrangement still reports non-zero for the `int count_bytes` one, unless I move it below the `signed char count_ints` counter:

```
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <malloc.h>

#define noinline                __attribute__((__noinline__))
#define __counted_by(member)    __attribute__((__counted_by__(member)))

#define DECLARE_BOUNDED_FLEX_ARRAY(COUNT_TYPE, COUNT, TYPE, NAME)       \
        struct {                                                        \
                COUNT_TYPE COUNT;                                       \
                TYPE NAME[] __counted_by(COUNT);                        \
        }

#define DECLARE_FLEX_ARRAY(TYPE, NAME)          \
        struct {                                \
                struct { } __empty_ ## NAME;    \
                TYPE NAME[];                    \
        }

struct multi {
        unsigned long flags;
        union {
                /* count member type intentionally mismatched to induce padding */
                DECLARE_BOUNDED_FLEX_ARRAY(int, count_bytes, unsigned char, bytes);
                DECLARE_BOUNDED_FLEX_ARRAY(signed char,  count_ints,  unsigned char, ints);
                DECLARE_FLEX_ARRAY(unsigned char, unsafe);
        };
};

/* Helper to hide the allocation size by using a leaf function. */
static struct multi * noinline alloc_multi_ints(int index)
{
        struct multi *p;

        p = malloc(sizeof(*p) + index * sizeof(*p->ints));
        p->count_ints = index;

        return p;
}

/* Helper to hide the allocation size by using a leaf function. */
static struct multi * noinline alloc_multi_bytes(int index)
{
        struct multi *p;

        p = malloc(sizeof(*p) + index * sizeof(*p->bytes));
        p->count_bytes = index;

        return p;
}

int main(void)
{
        struct multi *mi, *mb;
        volatile int negative = -3;
        volatile int index = 10;

        mi = alloc_multi_ints(index);
        mi->count_ints = negative;
        printf("%zu\n", __builtin_dynamic_object_size(mi->ints, 1));

        mb = alloc_multi_bytes(index);
        mb->count_bytes = negative;
        printf("%zu\n", __builtin_dynamic_object_size(mb->bytes, 1));

        return 0;
}
```

Returns:

```
253
0
```

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


More information about the cfe-commits mailing list