1.. title:: clang-tidy - bugprone-sizeof-expression 2 3bugprone-sizeof-expression 4========================== 5 6The check finds usages of ``sizeof`` expressions which are most likely errors. 7 8The ``sizeof`` operator yields the size (in bytes) of its operand, which may be 9an expression or the parenthesized name of a type. Misuse of this operator may 10be leading to errors and possible software vulnerabilities. 11 12Suspicious usage of 'sizeof(K)' 13------------------------------- 14 15A common mistake is to query the ``sizeof`` of an integer literal. This is 16equivalent to query the size of its type (probably ``int``). The intent of the 17programmer was probably to simply get the integer and not its size. 18 19.. code-block:: c++ 20 21 #define BUFLEN 42 22 char buf[BUFLEN]; 23 memset(buf, 0, sizeof(BUFLEN)); // sizeof(42) ==> sizeof(int) 24 25Suspicious usage of 'sizeof(expr)' 26---------------------------------- 27 28In cases, where there is an enum or integer to represent a type, a common 29mistake is to query the ``sizeof`` on the integer or enum that represents the 30type that should be used by ``sizeof``. This results in the size of the integer 31and not of the type the integer represents: 32 33.. code-block:: c++ 34 35 enum data_type { 36 FLOAT_TYPE, 37 DOUBLE_TYPE 38 }; 39 40 struct data { 41 data_type type; 42 void* buffer; 43 data_type get_type() { 44 return type; 45 } 46 }; 47 48 void f(data d, int numElements) { 49 // should be sizeof(float) or sizeof(double), depending on d.get_type() 50 int numBytes = numElements * sizeof(d.get_type()); 51 ... 52 } 53 54 55Suspicious usage of 'sizeof(this)' 56---------------------------------- 57 58The ``this`` keyword is evaluated to a pointer to an object of a given type. 59The expression ``sizeof(this)`` is returning the size of a pointer. The 60programmer most likely wanted the size of the object and not the size of the 61pointer. 62 63.. code-block:: c++ 64 65 class Point { 66 [...] 67 size_t size() { return sizeof(this); } // should probably be sizeof(*this) 68 [...] 69 }; 70 71Suspicious usage of 'sizeof(char*)' 72----------------------------------- 73 74There is a subtle difference between declaring a string literal with 75``char* A = ""`` and ``char A[] = ""``. The first case has the type ``char*`` 76instead of the aggregate type ``char[]``. Using ``sizeof`` on an object declared 77with ``char*`` type is returning the size of a pointer instead of the number of 78characters (bytes) in the string literal. 79 80.. code-block:: c++ 81 82 const char* kMessage = "Hello World!"; // const char kMessage[] = "..."; 83 void getMessage(char* buf) { 84 memcpy(buf, kMessage, sizeof(kMessage)); // sizeof(char*) 85 } 86 87Suspicious usage of 'sizeof(A*)' 88-------------------------------- 89 90A common mistake is to compute the size of a pointer instead of its pointee. 91These cases may occur because of explicit cast or implicit conversion. 92 93.. code-block:: c++ 94 95 int A[10]; 96 memset(A, 0, sizeof(A + 0)); 97 98 struct Point point; 99 memset(point, 0, sizeof(&point)); 100 101Suspicious usage of 'sizeof(...)/sizeof(...)' 102--------------------------------------------- 103 104Dividing ``sizeof`` expressions is typically used to retrieve the number of 105elements of an aggregate. This check warns on incompatible or suspicious cases. 106 107In the following example, the entity has 10-bytes and is incompatible with the 108type ``int`` which has 4 bytes. 109 110.. code-block:: c++ 111 112 char buf[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; // sizeof(buf) => 10 113 void getMessage(char* dst) { 114 memcpy(dst, buf, sizeof(buf) / sizeof(int)); // sizeof(int) => 4 [incompatible sizes] 115 } 116 117In the following example, the expression ``sizeof(Values)`` is returning the 118size of ``char*``. One can easily be fooled by its declaration, but in parameter 119declaration the size '10' is ignored and the function is receiving a ``char*``. 120 121.. code-block:: c++ 122 123 char OrderedValues[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; 124 return CompareArray(char Values[10]) { 125 return memcmp(OrderedValues, Values, sizeof(Values)) == 0; // sizeof(Values) ==> sizeof(char*) [implicit cast to char*] 126 } 127 128Suspicious 'sizeof' by 'sizeof' expression 129------------------------------------------ 130 131Multiplying ``sizeof`` expressions typically makes no sense and is probably a 132logic error. In the following example, the programmer used ``*`` instead of 133``/``. 134 135.. code-block:: c++ 136 137 const char kMessage[] = "Hello World!"; 138 void getMessage(char* buf) { 139 memcpy(buf, kMessage, sizeof(kMessage) * sizeof(char)); // sizeof(kMessage) / sizeof(char) 140 } 141 142This check may trigger on code using the arraysize macro. The following code is 143working correctly but should be simplified by using only the ``sizeof`` 144operator. 145 146.. code-block:: c++ 147 148 extern Object objects[100]; 149 void InitializeObjects() { 150 memset(objects, 0, arraysize(objects) * sizeof(Object)); // sizeof(objects) 151 } 152 153Suspicious usage of 'sizeof(sizeof(...))' 154----------------------------------------- 155 156Getting the ``sizeof`` of a ``sizeof`` makes no sense and is typically an error 157hidden through macros. 158 159.. code-block:: c++ 160 161 #define INT_SZ sizeof(int) 162 int buf[] = { 42 }; 163 void getInt(int* dst) { 164 memcpy(dst, buf, sizeof(INT_SZ)); // sizeof(sizeof(int)) is suspicious. 165 } 166 167Options 168------- 169 170.. option:: WarnOnSizeOfConstant 171 172 When `true`, the check will warn on an expression like 173 ``sizeof(CONSTANT)``. Default is `true`. 174 175.. option:: WarnOnSizeOfIntegerExpression 176 177 When `true`, the check will warn on an expression like ``sizeof(expr)`` 178 where the expression results in an integer. Default is `false`. 179 180.. option:: WarnOnSizeOfThis 181 182 When `true`, the check will warn on an expression like ``sizeof(this)``. 183 Default is `true`. 184 185.. option:: WarnOnSizeOfCompareToConstant 186 187 When `true`, the check will warn on an expression like 188 ``sizeof(epxr) <= k`` for a suspicious constant `k` while `k` is `0` or 189 greater than `0x8000`. Default is `true`. 190