@@ -7749,3 +7749,81 @@ but do not pass them to the underlying coroutine or pass them by value.
77497749.. _`CRT`: https://clang.llvm.org/docs/AttributeReference.html#coro-return-type
77507750}];
77517751}
7752+
7753+ def CountedByDocs : Documentation {
7754+ let Category = DocCatField;
7755+ let Content = [{
7756+ Clang supports the ``counted_by`` attribute on the flexible array member of a
7757+ structure in C. The argument for the attribute is the name of a field member
7758+ holding the count of elements in the flexible array. This information can be
7759+ used to improve the results of the array bound sanitizer and the
7760+ ``__builtin_dynamic_object_size`` builtin. The ``count`` field member must be
7761+ within the same non-anonymous, enclosing struct as the flexible array member.
7762+
7763+ This example specifies that the flexible array member ``array`` has the number
7764+ of elements allocated for it in ``count``:
7765+
7766+ .. code-block:: c
7767+
7768+ struct bar;
7769+
7770+ struct foo {
7771+ size_t count;
7772+ char other;
7773+ struct bar *array[] __attribute__((counted_by(count)));
7774+ };
7775+
7776+ This establishes a relationship between ``array`` and ``count``. Specifically,
7777+ ``array`` must have at least ``count`` number of elements available. It's the
7778+ user's responsibility to ensure that this relationship is maintained through
7779+ changes to the structure.
7780+
7781+ In the following example, the allocated array erroneously has fewer elements
7782+ than what's specified by ``p->count``. This would result in an out-of-bounds
7783+ access not being detected.
7784+
7785+ .. code-block:: c
7786+
7787+ #define SIZE_INCR 42
7788+
7789+ struct foo *p;
7790+
7791+ void foo_alloc(size_t count) {
7792+ p = malloc(MAX(sizeof(struct foo),
7793+ offsetof(struct foo, array[0]) + count * sizeof(struct bar *)));
7794+ p->count = count + SIZE_INCR;
7795+ }
7796+
7797+ The next example updates ``p->count``, but breaks the relationship requirement
7798+ that ``p->array`` must have at least ``p->count`` number of elements available:
7799+
7800+ .. code-block:: c
7801+
7802+ #define SIZE_INCR 42
7803+
7804+ struct foo *p;
7805+
7806+ void foo_alloc(size_t count) {
7807+ p = malloc(MAX(sizeof(struct foo),
7808+ offsetof(struct foo, array[0]) + count * sizeof(struct bar *)));
7809+ p->count = count;
7810+ }
7811+
7812+ void use_foo(int index, int val) {
7813+ p->count += SIZE_INCR + 1; /* 'count' is now larger than the number of elements of 'array'. */
7814+ p->array[index] = val; /* The sanitizer can't properly check this access. */
7815+ }
7816+
7817+ In this example, an update to ``p->count`` maintains the relationship
7818+ requirement:
7819+
7820+ .. code-block:: c
7821+
7822+ void use_foo(int index, int val) {
7823+ if (p->count == 0)
7824+ return;
7825+ --p->count;
7826+ p->array[index] = val;
7827+ }
7828+ }];
7829+ }
0 commit comments