@@ -6933,77 +6933,103 @@ def UnsafeBufferUsageDocs : Documentation {
6933
6933
let Category = DocCatFunction;
6934
6934
let Content = [{
6935
6935
The attribute ``[[clang::unsafe_buffer_usage]]`` should be placed on functions
6936
- that need to be avoided as they are prone to buffer overflows. It is designed to
6937
- work together with the off-by-default compiler warning ``-Wunsafe-buffer-usage``
6938
- to help codebases transition away from raw pointer based buffer management,
6939
- in favor of safer abstractions such as C++20 ``std::span``. The attribute causes
6940
- ``-Wunsafe-buffer-usage`` to warn on every use of the function, and it may
6941
- enable ``-Wunsafe-buffer-usage`` to emit automatic fix-it hints
6942
- which would help the user replace such unsafe functions with safe
6936
+ that need to be avoided as they are prone to buffer overflows or unsafe buffer
6937
+ struct fields. It is designed to work together with the off-by-default compiler
6938
+ warning ``-Wunsafe-buffer-usage`` to help codebases transition away from raw pointer
6939
+ based buffer management, in favor of safer abstractions such as C++20 ``std::span``.
6940
+ The attribute causes ``-Wunsafe-buffer-usage`` to warn on every use of the function or
6941
+ the field it is attached to, and it may also lead to emission of automatic fix-it
6942
+ hints which would help the user replace the use of unsafe functions(/fields) with safe
6943
6943
alternatives, though the attribute can be used even when the fix can't be automated.
6944
6944
6945
- The attribute does not suppress ``-Wunsafe-buffer-usage`` inside the function
6946
- to which it is attached. These warnings still need to be addressed.
6945
+ * Attribute attached to functions: The attribute does not suppress
6946
+ ``-Wunsafe-buffer-usage`` inside the function to which it is attached.
6947
+ These warnings still need to be addressed.
6947
6948
6948
- The attribute is warranted even if the only way a function can overflow
6949
- the buffer is by violating the function's preconditions. For example, it
6950
- would make sense to put the attribute on function ``foo()`` below because
6951
- passing an incorrect size parameter would cause a buffer overflow:
6949
+ The attribute is warranted even if the only way a function can overflow
6950
+ the buffer is by violating the function's preconditions. For example, it
6951
+ would make sense to put the attribute on function ``foo()`` below because
6952
+ passing an incorrect size parameter would cause a buffer overflow:
6952
6953
6953
- .. code-block:: c++
6954
+ .. code-block:: c++
6954
6955
6955
- [[clang::unsafe_buffer_usage]]
6956
- void foo(int *buf, size_t size) {
6957
- for (size_t i = 0; i < size; ++i) {
6958
- buf[i] = i;
6956
+ [[clang::unsafe_buffer_usage]]
6957
+ void foo(int *buf, size_t size) {
6958
+ for (size_t i = 0; i < size; ++i) {
6959
+ buf[i] = i;
6960
+ }
6959
6961
}
6960
- }
6961
6962
6962
- The attribute is NOT warranted when the function uses safe abstractions,
6963
- assuming that these abstractions weren't misused outside the function.
6964
- For example, function ``bar()`` below doesn't need the attribute,
6965
- because assuming that the container ``buf`` is well-formed (has size that
6966
- fits the original buffer it refers to), overflow cannot occur:
6963
+ The attribute is NOT warranted when the function uses safe abstractions,
6964
+ assuming that these abstractions weren't misused outside the function.
6965
+ For example, function ``bar()`` below doesn't need the attribute,
6966
+ because assuming that the container ``buf`` is well-formed (has size that
6967
+ fits the original buffer it refers to), overflow cannot occur:
6967
6968
6968
- .. code-block:: c++
6969
+ .. code-block:: c++
6969
6970
6970
- void bar(std::span<int> buf) {
6971
- for (size_t i = 0; i < buf.size(); ++i) {
6972
- buf[i] = i;
6971
+ void bar(std::span<int> buf) {
6972
+ for (size_t i = 0; i < buf.size(); ++i) {
6973
+ buf[i] = i;
6974
+ }
6973
6975
}
6974
- }
6975
6976
6976
- In this case function ``bar()`` enables the user to keep the buffer
6977
- "containerized" in a span for as long as possible. On the other hand,
6978
- Function ``foo()`` in the previous example may have internal
6979
- consistency, but by accepting a raw buffer it requires the user to unwrap
6980
- their span, which is undesirable according to the programming model
6981
- behind ``-Wunsafe-buffer-usage``.
6977
+ In this case function ``bar()`` enables the user to keep the buffer
6978
+ "containerized" in a span for as long as possible. On the other hand,
6979
+ Function ``foo()`` in the previous example may have internal
6980
+ consistency, but by accepting a raw buffer it requires the user to unwrap
6981
+ their span, which is undesirable according to the programming model
6982
+ behind ``-Wunsafe-buffer-usage``.
6982
6983
6983
- The attribute is warranted when a function accepts a raw buffer only to
6984
- immediately put it into a span:
6984
+ The attribute is warranted when a function accepts a raw buffer only to
6985
+ immediately put it into a span:
6985
6986
6986
- .. code-block:: c++
6987
+ .. code-block:: c++
6987
6988
6988
- [[clang::unsafe_buffer_usage]]
6989
- void baz(int *buf, size_t size) {
6990
- std::span<int> sp{ buf, size };
6991
- for (size_t i = 0; i < sp.size(); ++i) {
6992
- sp[i] = i;
6989
+ [[clang::unsafe_buffer_usage]]
6990
+ void baz(int *buf, size_t size) {
6991
+ std::span<int> sp{ buf, size };
6992
+ for (size_t i = 0; i < sp.size(); ++i) {
6993
+ sp[i] = i;
6994
+ }
6993
6995
}
6994
- }
6995
6996
6996
- In this case ``baz()`` does not contain any unsafe operations, but the awkward
6997
- parameter type causes the caller to unwrap the span unnecessarily.
6998
- Note that regardless of the attribute, code inside ``baz()`` isn't flagged
6999
- by ``-Wunsafe-buffer-usage`` as unsafe. It is definitely undesirable,
7000
- but if ``baz()`` is on an API surface, there is no way to improve it
7001
- to make it as safe as ``bar()`` without breaking the source and binary
7002
- compatibility with existing users of the function. In such cases
7003
- the proper solution would be to create a different function (possibly
7004
- an overload of ``baz()``) that accepts a safe container like ``bar()``,
7005
- and then use the attribute on the original ``baz()`` to help the users
7006
- update their code to use the new function.
6997
+ In this case ``baz()`` does not contain any unsafe operations, but the awkward
6998
+ parameter type causes the caller to unwrap the span unnecessarily.
6999
+ Note that regardless of the attribute, code inside ``baz()`` isn't flagged
7000
+ by ``-Wunsafe-buffer-usage`` as unsafe. It is definitely undesirable,
7001
+ but if ``baz()`` is on an API surface, there is no way to improve it
7002
+ to make it as safe as ``bar()`` without breaking the source and binary
7003
+ compatibility with existing users of the function. In such cases
7004
+ the proper solution would be to create a different function (possibly
7005
+ an overload of ``baz()``) that accepts a safe container like ``bar()``,
7006
+ and then use the attribute on the original ``baz()`` to help the users
7007
+ update their code to use the new function.
7008
+
7009
+ * Attribute attached to fields: The attribute should only be attached to
7010
+ struct fields, if the fields can not be updated to a safe type with bounds
7011
+ check, such as std::span. In other words, the buffers prone to unsafe accesses
7012
+ should always be updated to use safe containers/views and attaching the attribute
7013
+ must be last resort when such an update is infeasible.
7014
+
7015
+ The attribute can be placed on individual fields or a set of them as shown below.
7016
+
7017
+ .. code-block:: c++
7018
+
7019
+ struct A {
7020
+ [[clang::unsafe_buffer_usage]]
7021
+ int *ptr1;
7022
+
7023
+ [[clang::unsafe_buffer_usage]]
7024
+ int *ptr2, buf[10];
7025
+
7026
+ [[clang::unsafe_buffer_usage]]
7027
+ size_t sz;
7028
+ };
7029
+
7030
+ Here, every read/write to the fields ptr1, ptr2, buf and sz will trigger a warning
7031
+ that the field has been explcitly marked as unsafe due to unsafe-buffer operations.
7032
+
7007
7033
}];
7008
7034
}
7009
7035
0 commit comments