@@ -6764,77 +6764,103 @@ def UnsafeBufferUsageDocs : Documentation {
6764
6764
let Category = DocCatFunction;
6765
6765
let Content = [{
6766
6766
The attribute ``[[clang::unsafe_buffer_usage]]`` should be placed on functions
6767
- that need to be avoided as they are prone to buffer overflows. It is designed to
6768
- work together with the off-by-default compiler warning ``-Wunsafe-buffer-usage``
6769
- to help codebases transition away from raw pointer based buffer management,
6770
- in favor of safer abstractions such as C++20 ``std::span``. The attribute causes
6771
- ``-Wunsafe-buffer-usage`` to warn on every use of the function, and it may
6772
- enable ``-Wunsafe-buffer-usage`` to emit automatic fix-it hints
6773
- which would help the user replace such unsafe functions with safe
6767
+ that need to be avoided as they are prone to buffer overflows or unsafe buffer
6768
+ struct fields. It is designed to work together with the off-by-default compiler
6769
+ warning ``-Wunsafe-buffer-usage`` to help codebases transition away from raw pointer
6770
+ based buffer management, in favor of safer abstractions such as C++20 ``std::span``.
6771
+ The attribute causes ``-Wunsafe-buffer-usage`` to warn on every use of the function or
6772
+ the field it is attached to, and it may also lead to emission of automatic fix-it
6773
+ hints which would help the user replace the use of unsafe functions(/fields) with safe
6774
6774
alternatives, though the attribute can be used even when the fix can't be automated.
6775
6775
6776
- The attribute does not suppress ``-Wunsafe-buffer-usage`` inside the function
6777
- to which it is attached. These warnings still need to be addressed.
6776
+ * Attribute attached to functions: The attribute does not suppress
6777
+ ``-Wunsafe-buffer-usage`` inside the function to which it is attached.
6778
+ These warnings still need to be addressed.
6778
6779
6779
- The attribute is warranted even if the only way a function can overflow
6780
- the buffer is by violating the function's preconditions. For example, it
6781
- would make sense to put the attribute on function ``foo()`` below because
6782
- passing an incorrect size parameter would cause a buffer overflow:
6780
+ The attribute is warranted even if the only way a function can overflow
6781
+ the buffer is by violating the function's preconditions. For example, it
6782
+ would make sense to put the attribute on function ``foo()`` below because
6783
+ passing an incorrect size parameter would cause a buffer overflow:
6783
6784
6784
- .. code-block:: c++
6785
+ .. code-block:: c++
6785
6786
6786
- [[clang::unsafe_buffer_usage]]
6787
- void foo(int *buf, size_t size) {
6788
- for (size_t i = 0; i < size; ++i) {
6789
- buf[i] = i;
6787
+ [[clang::unsafe_buffer_usage]]
6788
+ void foo(int *buf, size_t size) {
6789
+ for (size_t i = 0; i < size; ++i) {
6790
+ buf[i] = i;
6791
+ }
6790
6792
}
6791
- }
6792
6793
6793
- The attribute is NOT warranted when the function uses safe abstractions,
6794
- assuming that these abstractions weren't misused outside the function.
6795
- For example, function ``bar()`` below doesn't need the attribute,
6796
- because assuming that the container ``buf`` is well-formed (has size that
6797
- fits the original buffer it refers to), overflow cannot occur:
6794
+ The attribute is NOT warranted when the function uses safe abstractions,
6795
+ assuming that these abstractions weren't misused outside the function.
6796
+ For example, function ``bar()`` below doesn't need the attribute,
6797
+ because assuming that the container ``buf`` is well-formed (has size that
6798
+ fits the original buffer it refers to), overflow cannot occur:
6798
6799
6799
- .. code-block:: c++
6800
+ .. code-block:: c++
6800
6801
6801
- void bar(std::span<int> buf) {
6802
- for (size_t i = 0; i < buf.size(); ++i) {
6803
- buf[i] = i;
6802
+ void bar(std::span<int> buf) {
6803
+ for (size_t i = 0; i < buf.size(); ++i) {
6804
+ buf[i] = i;
6805
+ }
6804
6806
}
6805
- }
6806
6807
6807
- In this case function ``bar()`` enables the user to keep the buffer
6808
- "containerized" in a span for as long as possible. On the other hand,
6809
- Function ``foo()`` in the previous example may have internal
6810
- consistency, but by accepting a raw buffer it requires the user to unwrap
6811
- their span, which is undesirable according to the programming model
6812
- behind ``-Wunsafe-buffer-usage``.
6808
+ In this case function ``bar()`` enables the user to keep the buffer
6809
+ "containerized" in a span for as long as possible. On the other hand,
6810
+ Function ``foo()`` in the previous example may have internal
6811
+ consistency, but by accepting a raw buffer it requires the user to unwrap
6812
+ their span, which is undesirable according to the programming model
6813
+ behind ``-Wunsafe-buffer-usage``.
6813
6814
6814
- The attribute is warranted when a function accepts a raw buffer only to
6815
- immediately put it into a span:
6815
+ The attribute is warranted when a function accepts a raw buffer only to
6816
+ immediately put it into a span:
6816
6817
6817
- .. code-block:: c++
6818
+ .. code-block:: c++
6818
6819
6819
- [[clang::unsafe_buffer_usage]]
6820
- void baz(int *buf, size_t size) {
6821
- std::span<int> sp{ buf, size };
6822
- for (size_t i = 0; i < sp.size(); ++i) {
6823
- sp[i] = i;
6820
+ [[clang::unsafe_buffer_usage]]
6821
+ void baz(int *buf, size_t size) {
6822
+ std::span<int> sp{ buf, size };
6823
+ for (size_t i = 0; i < sp.size(); ++i) {
6824
+ sp[i] = i;
6825
+ }
6824
6826
}
6825
- }
6826
6827
6827
- In this case ``baz()`` does not contain any unsafe operations, but the awkward
6828
- parameter type causes the caller to unwrap the span unnecessarily.
6829
- Note that regardless of the attribute, code inside ``baz()`` isn't flagged
6830
- by ``-Wunsafe-buffer-usage`` as unsafe. It is definitely undesirable,
6831
- but if ``baz()`` is on an API surface, there is no way to improve it
6832
- to make it as safe as ``bar()`` without breaking the source and binary
6833
- compatibility with existing users of the function. In such cases
6834
- the proper solution would be to create a different function (possibly
6835
- an overload of ``baz()``) that accepts a safe container like ``bar()``,
6836
- and then use the attribute on the original ``baz()`` to help the users
6837
- update their code to use the new function.
6828
+ In this case ``baz()`` does not contain any unsafe operations, but the awkward
6829
+ parameter type causes the caller to unwrap the span unnecessarily.
6830
+ Note that regardless of the attribute, code inside ``baz()`` isn't flagged
6831
+ by ``-Wunsafe-buffer-usage`` as unsafe. It is definitely undesirable,
6832
+ but if ``baz()`` is on an API surface, there is no way to improve it
6833
+ to make it as safe as ``bar()`` without breaking the source and binary
6834
+ compatibility with existing users of the function. In such cases
6835
+ the proper solution would be to create a different function (possibly
6836
+ an overload of ``baz()``) that accepts a safe container like ``bar()``,
6837
+ and then use the attribute on the original ``baz()`` to help the users
6838
+ update their code to use the new function.
6839
+
6840
+ * Attribute attached to fields: The attribute should only be attached to
6841
+ struct fields, if the fields can not be updated to a safe type with bounds
6842
+ check, such as std::span. In other words, the buffers prone to unsafe accesses
6843
+ should always be updated to use safe containers/views and attaching the attribute
6844
+ must be last resort when such an update is infeasible.
6845
+
6846
+ The attribute can be placed on individual fields or a set of them as shown below.
6847
+
6848
+ .. code-block:: c++
6849
+
6850
+ struct A {
6851
+ [[clang::unsafe_buffer_usage]]
6852
+ int *ptr1;
6853
+
6854
+ [[clang::unsafe_buffer_usage]]
6855
+ int *ptr2, buf[10];
6856
+
6857
+ [[clang::unsafe_buffer_usage]]
6858
+ size_t sz;
6859
+ };
6860
+
6861
+ Here, every read/write to the fields ptr1, ptr2, buf and sz will trigger a warning
6862
+ that the field has been explcitly marked as unsafe due to unsafe-buffer operations.
6863
+
6838
6864
}];
6839
6865
}
6840
6866
0 commit comments