5 changes: 5 additions & 0 deletions clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -462,6 +462,11 @@ extern volatile int BoostModuleAnchorSource;
static int LLVM_ATTRIBUTE_UNUSED BoostModuleAnchorDestination =
BoostModuleAnchorSource;

// This anchor is used to force the linker to link the BugproneModule.
extern volatile int BugproneModuleAnchorSource;
static int LLVM_ATTRIBUTE_UNUSED BugproneModuleAnchorDestination =
BugproneModuleAnchorSource;

// This anchor is used to force the linker to link the LLVMModule.
extern volatile int LLVMModuleAnchorSource;
static int LLVM_ATTRIBUTE_UNUSED LLVMModuleAnchorDestination =
Expand Down
10 changes: 10 additions & 0 deletions clang-tools-extra/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,12 @@ Improvements to clang-tidy
Checks if the required file flag ``SOCK_CLOEXEC`` is present in the argument of
``socket()``.

- New `bugprone-suspicious-memset-usage
<http://clang.llvm.org/extra/clang-tidy/checks/bugprone-suspicious-memset-usage.html>`_ check

Finds ``memset()`` calls with potential mistakes in their arguments.
Replaces and extends the ``google-runtime-memset`` check.

- New `cert-dcl21-cpp
<http://clang.llvm.org/extra/clang-tidy/checks/cert-dcl21-cpp.html>`_ check

Expand Down Expand Up @@ -157,6 +163,10 @@ Improvements to clang-tidy
- Support clang-formatting of the code around applied fixes (``-format-style``
command-line option).

- New `bugprone` module

Adds checks that target bugprone code constructs.

- New `hicpp` module

Adds checks that implement the `High Integrity C++ Coding Standard <http://www.codingstandard.com/section/index/>`_ and other safety
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
.. title:: clang-tidy - bugprone-suspicious-memset-usage

bugprone-suspicious-memset-usage
================================

This check finds ``memset()`` calls with potential mistakes in their arguments.
Considering the function as ``void* memset(void* destination, int fill_value,
size_t byte_count)``, the following cases are covered:

**Case 1: Fill value is a character ``'0'``**

Filling up a memory area with ASCII code 48 characters is not customary,
possibly integer zeroes were intended instead.
The check offers a replacement of ``'0'`` with ``0``. Memsetting character
pointers with ``'0'`` is allowed.

**Case 2: Fill value is truncated**

Memset converts ``fill_value`` to ``unsigned char`` before using it. If
``fill_value`` is out of unsigned character range, it gets truncated
and memory will not contain the desired pattern.

**Case 3: Byte count is zero**

Calling memset with a literal zero in its ``byte_count`` argument is likely
to be unintended and swapped with ``fill_value``. The check offers to swap
these two arguments.

Corresponding cpplint.py check name: ``runtime/memset``.


Examples:

.. code-block:: c++

void foo() {
int i[5] = {1, 2, 3, 4, 5};
int *ip = i;
char c = '1';
char *cp = &c;
int v = 0;
// Case 1
memset(ip, '0', 1); // suspicious
memset(cp, '0', 1); // OK

// Case 2
memset(ip, 0xabcd, 1); // fill value gets truncated
memset(ip, 0x00, 1); // OK

// Case 3
memset(ip, sizeof(int), v); // zero length, potentially swapped
memset(ip, 0, 1); // OK
}
10 changes: 0 additions & 10 deletions clang-tools-extra/docs/clang-tidy/checks/google-runtime-memset.rst

This file was deleted.

2 changes: 1 addition & 1 deletion clang-tools-extra/docs/clang-tidy/checks/list.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ Clang-Tidy Checks
android-cloexec-open
android-cloexec-socket
boost-use-to-string
bugprone-suspicious-memset-usage
cert-dcl03-c (redirects to misc-static-assert) <cert-dcl03-c>
cert-dcl21-cpp
cert-dcl50-cpp
Expand Down Expand Up @@ -55,7 +56,6 @@ Clang-Tidy Checks
google-readability-todo
google-runtime-int
google-runtime-member-string-references
google-runtime-memset
google-runtime-operator
google-runtime-references
hicpp-explicit-conversions
Expand Down
1 change: 1 addition & 0 deletions clang-tools-extra/docs/clang-tidy/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ Name prefix Description
====================== =========================================================
``android-`` Checks related to Android.
``boost-`` Checks related to Boost library.
``bugprone-`` Checks that target bugprone code constructs.
``cert-`` Checks related to CERT Secure Coding Guidelines.
``cppcoreguidelines-`` Checks related to C++ Core Guidelines.
``clang-analyzer-`` Clang Static Analyzer checks.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// RUN: %check_clang_tidy %s bugprone-suspicious-memset-usage %t

void *memset(void *, int, __SIZE_TYPE__);

namespace std {
using ::memset;
}

template <typename T>
void mtempl(int *ptr) {
memset(ptr, '0', sizeof(T));
// CHECK-MESSAGES: :[[@LINE-1]]:15: warning: memset fill value is char '0', potentially mistaken for int 0 [bugprone-suspicious-memset-usage]
// CHECK-FIXES: memset(ptr, 0, sizeof(T));
memset(ptr, 256, sizeof(T));
// CHECK-MESSAGES: :[[@LINE-1]]:15: warning: memset fill value is out of unsigned character range, gets truncated [bugprone-suspicious-memset-usage]
memset(0, sizeof(T), 0);
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: memset of size zero, potentially swapped arguments [bugprone-suspicious-memset-usage]
// CHECK-FIXES: memset(0, 0, sizeof(T));
memset(0, sizeof(int), 0);
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: memset of size zero, potentially swapped arguments [bugprone-suspicious-memset-usage]
// CHECK-FIXES: memset(0, 0, sizeof(int));
}

void foo(int xsize, int ysize) {
int i[5] = {1, 2, 3, 4, 5};
char ca[3] = {'a', 'b', 'c'};
int *p = i;
int l = 5;
char z = '1';
char *c = &z;
int v = 0;

memset(p, '0', l);
// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: memset fill value is char '0', potentially mistaken for int 0 [bugprone-suspicious-memset-usage]
// CHECK-FIXES: memset(p, 0, l);

memset(p, 0xabcd, l);
// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: memset fill value is out of unsigned character range, gets truncated [bugprone-suspicious-memset-usage]

memset(p, sizeof(int), 0);
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: memset of size zero, potentially swapped arguments [bugprone-suspicious-memset-usage]
// CHECK-FIXES: memset(p, 0, sizeof(int));
std::memset(p, sizeof(int), 0x00);
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: memset of size zero, potentially swapped arguments [bugprone-suspicious-memset-usage]
// CHECK-FIXES: std::memset(p, 0x00, sizeof(int));

#define M_CHAR_ZERO memset(p, '0', l);
M_CHAR_ZERO
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: memset fill value is char '0', potentially mistaken for int 0 [bugprone-suspicious-memset-usage]

#define M_OUTSIDE_RANGE memset(p, 0xabcd, l);
M_OUTSIDE_RANGE
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: memset fill value is out of unsigned character range, gets truncated [bugprone-suspicious-memset-usage]

#define M_ZERO_LENGTH memset(p, sizeof(int), 0);
M_ZERO_LENGTH
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: memset of size zero, potentially swapped arguments [bugprone-suspicious-memset-usage]

memset(p, '2', l);
memset(p, 0, l);
memset(c, '0', 1);
memset(ca, '0', sizeof(ca));

memset(p, 0x00, l);
mtempl<int>(p);

memset(p, sizeof(int), v + 1);
memset(p, 0xcd, 1);

// Don't warn when the fill char and the length are both known to be
// zero. No bug is possible.
memset(p, 0, v);

// -1 is clearly not a length by virtue of being negative, so no warning
// despite v == 0.
memset(p, -1, v);
}

This file was deleted.