summaryrefslogtreecommitdiffstats
path: root/clang-tools-extra/test/clang-tidy
diff options
context:
space:
mode:
Diffstat (limited to 'clang-tools-extra/test/clang-tidy')
-rw-r--r--clang-tools-extra/test/clang-tidy/Inputs/bugprone-not-null-terminated-result/not-null-terminated-result-c.h39
-rw-r--r--clang-tools-extra/test/clang-tidy/Inputs/bugprone-not-null-terminated-result/not-null-terminated-result-cxx.h65
-rw-r--r--clang-tools-extra/test/clang-tidy/bugprone-not-null-terminated-result-in-initialization-strlen.c84
-rw-r--r--clang-tools-extra/test/clang-tidy/bugprone-not-null-terminated-result-memcpy-before-safe.c71
-rw-r--r--clang-tools-extra/test/clang-tidy/bugprone-not-null-terminated-result-memcpy-safe-cxx.cpp124
-rw-r--r--clang-tools-extra/test/clang-tidy/bugprone-not-null-terminated-result-memcpy-safe-other.c112
-rw-r--r--clang-tools-extra/test/clang-tidy/bugprone-not-null-terminated-result-memcpy-safe.c124
-rw-r--r--clang-tools-extra/test/clang-tidy/bugprone-not-null-terminated-result-strlen.c118
-rw-r--r--clang-tools-extra/test/clang-tidy/bugprone-not-null-terminated-result-wcslen.cpp106
-rw-r--r--clang-tools-extra/test/clang-tidy/bugprone-not-null-terminated-result-wmemcpy-safe-cxx.cpp111
10 files changed, 954 insertions, 0 deletions
diff --git a/clang-tools-extra/test/clang-tidy/Inputs/bugprone-not-null-terminated-result/not-null-terminated-result-c.h b/clang-tools-extra/test/clang-tidy/Inputs/bugprone-not-null-terminated-result/not-null-terminated-result-c.h
new file mode 100644
index 00000000000..9a291124a32
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/Inputs/bugprone-not-null-terminated-result/not-null-terminated-result-c.h
@@ -0,0 +1,39 @@
+//===- not-null-terminated-result-c.h - Helper header -------------*- C -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This header helps to maintain every function call checked by the
+// NotNullTerminatedResult checker.
+//
+//===----------------------------------------------------------------------===//
+
+#pragma clang system_header
+
+typedef unsigned int size_t;
+typedef int errno_t;
+
+size_t strlen(const char *str);
+void *malloc(size_t size);
+char *strerror(int errnum);
+errno_t strerror_s(char *buffer, size_t bufferSize, int errnum);
+
+char *strcpy(char *dest, const char *src);
+errno_t strcpy_s(char *dest, size_t destSize, const char *src);
+char *strncpy(char *dest, const char *src, size_t count);
+errno_t strncpy_s(char *dest, size_t destSize, const char *src, size_t count);
+
+void *memcpy(void *dest, const void *src, size_t count);
+errno_t memcpy_s(void *dest, size_t destSize, const void *src, size_t count);
+
+char *strchr(char *str, int c);
+int strncmp(const char *str1, const char *str2, size_t count);
+size_t strxfrm(char *dest, const char *src, size_t count);
+
+void *memchr(const void *buffer, int c, size_t count);
+void *memmove(void *dest, const void *src, size_t count);
+errno_t memmove_s(void *dest, size_t destSize, const void *src, size_t count);
+void *memset(void *dest, int c, size_t count);
diff --git a/clang-tools-extra/test/clang-tidy/Inputs/bugprone-not-null-terminated-result/not-null-terminated-result-cxx.h b/clang-tools-extra/test/clang-tidy/Inputs/bugprone-not-null-terminated-result/not-null-terminated-result-cxx.h
new file mode 100644
index 00000000000..814c5b5e0f4
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/Inputs/bugprone-not-null-terminated-result/not-null-terminated-result-cxx.h
@@ -0,0 +1,65 @@
+//===- not-null-terminated-result-cxx.h - Helper header ---------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This header helps to maintain every function call checked by the
+// NotNullTerminatedResult checker.
+//
+//===----------------------------------------------------------------------===//
+
+#pragma clang system_header
+
+#include "not-null-terminated-result-c.h"
+
+namespace std {
+template <typename T>
+struct basic_string {
+ basic_string();
+ const T *data() const;
+ unsigned long size() const;
+ unsigned long length() const;
+};
+typedef basic_string<char> string;
+} // namespace std
+
+size_t wcslen(const wchar_t *str);
+
+template <size_t size>
+char *strcpy(char (&dest)[size], const char *src);
+template <size_t size>
+wchar_t *wcscpy(wchar_t (&dest)[size], const wchar_t *src);
+wchar_t *wcscpy(wchar_t *dest, const wchar_t *src);
+
+template <size_t size>
+errno_t strcpy_s(char (&dest)[size], const char *src);
+template <size_t size>
+errno_t wcscpy_s(wchar_t (&dest)[size], const wchar_t *src);
+errno_t wcscpy_s(wchar_t *dest, size_t destSize, const wchar_t *src);
+
+template <size_t size>
+char *strncpy(char (&dest)[size], const char *src, size_t count);
+template <size_t size>
+wchar_t *wcsncpy(wchar_t (&dest)[size], const wchar_t *src, size_t count);
+wchar_t *wcsncpy(wchar_t *dest, const wchar_t *src, size_t count);
+
+template <size_t size>
+errno_t strncpy_s(char (&dest)[size], const char *src, size_t count);
+template <size_t size>
+errno_t wcsncpy_s(wchar_t (&dest)[size], const wchar_t *src, size_t length);
+errno_t wcsncpy_s(wchar_t *dest, size_t destSize, const wchar_t *src, size_t c);
+
+wchar_t *wmemcpy(wchar_t *dest, const wchar_t *src, size_t count);
+errno_t wmemcpy_s(wchar_t *dest, size_t destSize, const wchar_t *src, size_t c);
+
+wchar_t *wcschr(const wchar_t *str, int c);
+int wcsncmp(const wchar_t *str1, const wchar_t *str2, size_t count);
+size_t wcsxfrm(wchar_t *dest, const wchar_t *src, size_t count);
+
+void *wmemchr(const void *buffer, int c, size_t count);
+void *wmemmove(void *dest, const void *src, size_t count);
+errno_t wmemmove_s(void *dest, size_t destSize, const void *src, size_t count);
+void *wmemset(void *dest, int c, size_t count);
diff --git a/clang-tools-extra/test/clang-tidy/bugprone-not-null-terminated-result-in-initialization-strlen.c b/clang-tools-extra/test/clang-tidy/bugprone-not-null-terminated-result-in-initialization-strlen.c
new file mode 100644
index 00000000000..259427e3bce
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/bugprone-not-null-terminated-result-in-initialization-strlen.c
@@ -0,0 +1,84 @@
+// RUN: %check_clang_tidy %s bugprone-not-null-terminated-result %t -- \
+// RUN: -- -std=c11 -I %S/Inputs/bugprone-not-null-terminated-result
+
+#include "not-null-terminated-result-c.h"
+
+void path_sensitive_unknown_length(char *position, const char *src) {
+ int length;
+ length = strlen(src);
+ position = (char *)memchr(src, '\0', length);
+}
+
+void bad_memchr(char *position, const char *src) {
+ int length = strlen(src);
+ position = (char *)memchr(src, '\0', length);
+ // CHECK-MESSAGES: :[[@LINE-1]]:40: warning: the length is too short to include the null terminator [bugprone-not-null-terminated-result]
+ // CHECK-FIXES: position = strchr(src, '\0');
+}
+
+void good_memchr(char *pos, const char *src) {
+ pos = strchr(src, '\0');
+}
+
+void bad_strerror_s(int errno) {
+ char dest[13];
+ int length = strlen(strerror(errno));
+ strerror_s(dest, length, errno);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: the result from calling 'strerror_s' is not null-terminated and missing the last character of the error message [bugprone-not-null-terminated-result]
+ // CHECK-FIXES: char dest[14];
+ // CHECK-FIXES-NEXT: int length = strlen(strerror(errno));
+ // CHECK-FIXES-NEXT: strerror_s(dest, length + 1, errno);
+}
+
+void good_strerror_s(int errno) {
+ char dst[14];
+ int length = strlen(strerror(errno));
+ strerror_s(dst, length + 1, errno);
+}
+
+int bad_strncmp_1(char *str1, const char *str2) {
+ int length = strlen(str1) + 1;
+ return strncmp(str1, str2, length);
+ // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: comparison length is too long and might lead to a buffer overflow [bugprone-not-null-terminated-result]
+ // CHECK-FIXES: strncmp(str1, str2, length - 1);
+}
+
+int good_strncmp_1(char *str1, const char *str2) {
+ int length = strlen(str1) + 1;
+ return strncmp(str1, str2, length - 1);
+}
+
+int bad_strncmp_2(char *str2) {
+ return strncmp(str2, "foobar", (strlen("foobar") + 1));
+ // CHECK-MESSAGES: :[[@LINE-1]]:35: warning: comparison length is too long and might lead to a buffer overflow [bugprone-not-null-terminated-result]
+ // CHECK-FIXES: strncmp(str2, "foobar", (strlen("foobar")));
+}
+
+int bad_strncmp_3(char *str3) {
+ return strncmp(str3, "foobar", 1 + strlen("foobar"));
+ // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: comparison length is too long and might lead to a buffer overflow [bugprone-not-null-terminated-result]
+ // CHECK-FIXES: strncmp(str3, "foobar", strlen("foobar"));
+}
+
+int good_strncmp_2_3(char *str) {
+ return strncmp(str, "foobar", strlen("foobar"));
+}
+
+void bad_strxfrm(const char *long_source_name) {
+ char long_destination_name[13];
+ int very_long_length_definition_name = strlen(long_source_name);
+ strxfrm(long_destination_name, long_source_name,
+ very_long_length_definition_name);
+ // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: the result from calling 'strxfrm' is not null-terminated [bugprone-not-null-terminated-result]
+ // CHECK-FIXES: char long_destination_name[14];
+ // CHECK-FIXES-NEXT: int very_long_length_definition_name = strlen(long_source_name);
+ // CHECK-FIXES-NEXT: strxfrm(long_destination_name, long_source_name,
+ // CHECK-FIXES-NEXT: very_long_length_definition_name + 1);
+}
+
+void good_strxfrm(const char *long_source_name) {
+ char long_destination_name[14];
+ int very_long_length_definition_name = strlen(long_source_name);
+ strxfrm(long_destination_name, long_source_name,
+ very_long_length_definition_name + 1);
+}
diff --git a/clang-tools-extra/test/clang-tidy/bugprone-not-null-terminated-result-memcpy-before-safe.c b/clang-tools-extra/test/clang-tidy/bugprone-not-null-terminated-result-memcpy-before-safe.c
new file mode 100644
index 00000000000..0217a77d81a
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/bugprone-not-null-terminated-result-memcpy-before-safe.c
@@ -0,0 +1,71 @@
+// RUN: %check_clang_tidy %s bugprone-not-null-terminated-result %t -- \
+// RUN: -config="{CheckOptions: \
+// RUN: [{key: bugprone-not-null-terminated-result.WantToUseSafeFunctions, \
+// RUN: value: 1}]}" \
+// RUN: -- -std=c11 -I %S/Inputs/bugprone-not-null-terminated-result
+
+#include "not-null-terminated-result-c.h"
+
+// The following is not defined therefore the safe functions are unavailable.
+// #define __STDC_LIB_EXT1__ 1
+
+#define __STDC_WANT_LIB_EXT1__ 1
+
+//===----------------------------------------------------------------------===//
+// memcpy() - destination array tests
+//===----------------------------------------------------------------------===//
+
+void bad_memcpy_not_just_char_dest(const char *src) {
+ unsigned char dest00[13];
+ memcpy(dest00, src, strlen(src));
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: the result from calling 'memcpy' is not null-terminated [bugprone-not-null-terminated-result]
+ // CHECK-FIXES: unsigned char dest00[14];
+ // CHECK-FIXES-NEXT: strcpy((char *)dest00, src);
+}
+
+void good_memcpy_not_just_char_dest(const char *src) {
+ unsigned char dst00[14];
+ strcpy((char *)dst00, src);
+}
+
+void bad_memcpy_known_dest(const char *src) {
+ char dest01[13];
+ memcpy(dest01, src, strlen(src));
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: the result from calling 'memcpy' is not null-terminated [bugprone-not-null-terminated-result]
+ // CHECK-FIXES: strcpy(dest01, src);
+}
+
+void good_memcpy_known_dest(const char *src) {
+ char dst01[13];
+ strcpy(dst01, src);
+}
+
+//===----------------------------------------------------------------------===//
+// memcpy() - length tests
+//===----------------------------------------------------------------------===//
+
+void bad_memcpy_full_source_length(const char *src) {
+ char dest20[13];
+ memcpy(dest20, src, strlen(src));
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: the result from calling 'memcpy' is not null-terminated [bugprone-not-null-terminated-result]
+ // CHECK-FIXES: strcpy(dest20, src);
+}
+
+void good_memcpy_full_source_length(const char *src) {
+ char dst20[13];
+ strcpy(dst20, src);
+}
+
+void bad_memcpy_partial_source_length(const char *src) {
+ char dest21[13];
+ memcpy(dest21, src, strlen(src) - 1);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: the result from calling 'memcpy' is not null-terminated [bugprone-not-null-terminated-result]
+ // CHECK-FIXES: strncpy(dest21, src, strlen(src) - 1);
+ // CHECK-FIXES-NEXT: dest21[strlen(src) - 1] = '\0';
+}
+
+void good_memcpy_partial_source_length(const char *src) {
+ char dst21[13];
+ strncpy(dst21, src, strlen(src) - 1);
+ dst21[strlen(src) - 1] = '\0';
+}
diff --git a/clang-tools-extra/test/clang-tidy/bugprone-not-null-terminated-result-memcpy-safe-cxx.cpp b/clang-tools-extra/test/clang-tidy/bugprone-not-null-terminated-result-memcpy-safe-cxx.cpp
new file mode 100644
index 00000000000..747bbc308b5
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/bugprone-not-null-terminated-result-memcpy-safe-cxx.cpp
@@ -0,0 +1,124 @@
+// RUN: %check_clang_tidy %s bugprone-not-null-terminated-result %t -- \
+// RUN: -- -std=c++11 -I %S/Inputs/bugprone-not-null-terminated-result
+
+#include "not-null-terminated-result-cxx.h"
+
+#define __STDC_LIB_EXT1__ 1
+#define __STDC_WANT_LIB_EXT1__ 1
+
+//===----------------------------------------------------------------------===//
+// memcpy() - destination array tests
+//===----------------------------------------------------------------------===//
+
+void bad_memcpy_not_just_char_dest(const char *src) {
+ unsigned char dest00[13];
+ memcpy(dest00, src, strlen(src));
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: the result from calling 'memcpy' is not null-terminated [bugprone-not-null-terminated-result]
+ // CHECK-FIXES: unsigned char dest00[14];
+ // CHECK-FIXES-NEXT: strcpy_s((char *)dest00, 14, src);
+}
+
+void good_memcpy_not_just_char_dest(const char *src) {
+ unsigned char dst00[14];
+ strcpy_s((char *)dst00, 14, src);
+}
+
+void bad_memcpy_known_dest(const char *src) {
+ char dest01[13];
+ memcpy(dest01, src, strlen(src));
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: the result from calling 'memcpy' is not null-terminated [bugprone-not-null-terminated-result]
+ // CHECK-FIXES: dest01[14];
+ // CHECK-FIXES-NEXT: strcpy_s(dest01, src);
+}
+
+void good_memcpy_known_dest(const char *src) {
+ char dst01[14];
+ strcpy_s(dst01, src);
+}
+
+//===----------------------------------------------------------------------===//
+// memcpy() - length tests
+//===----------------------------------------------------------------------===//
+
+void bad_memcpy_full_source_length(std::string src) {
+ char *dest20 = reinterpret_cast<char *>(malloc(src.size()));
+ memcpy(dest20, src.data(), src.size());
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: the result from calling 'memcpy' is not null-terminated [bugprone-not-null-terminated-result]
+ // CHECK-FIXES: dest20 = reinterpret_cast<char *>(malloc(src.size() + 1));
+ // CHECK-FIXES-NEXT: strcpy(dest20, src.data());
+}
+
+void good_memcpy_full_source_length(std::string src) {
+ char dst20[14];
+ strcpy_s(dst20, src.data());
+}
+
+void bad_memcpy_partial_source_length(const char *src) {
+ char dest21[13];
+ memcpy(dest21, src, strlen(src) - 1);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: the result from calling 'memcpy' is not null-terminated [bugprone-not-null-terminated-result]
+ // CHECK-FIXES: char dest21[14];
+ // CHECK-FIXES-NEXT: strncpy_s(dest21, src, strlen(src) - 1);
+}
+
+void good_memcpy_partial_source_length(const char *src) {
+ char dst21[14];
+ strncpy_s(dst21, src, strlen(src) - 1);
+}
+
+//===----------------------------------------------------------------------===//
+// memcpy_s() - destination array tests
+//===----------------------------------------------------------------------===//
+
+void bad_memcpy_s_unknown_dest(char *dest40, const char *src) {
+ memcpy_s(dest40, 13, src, strlen(src));
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: the result from calling 'memcpy_s' is not null-terminated [bugprone-not-null-terminated-result]
+ // CHECK-FIXES: strcpy_s(dest40, 13, src);
+}
+
+void good_memcpy_s_unknown_dest(char *dst40, const char *src) {
+ strcpy_s(dst40, 13, src);
+}
+
+void bad_memcpy_s_known_dest(const char *src) {
+ char dest41[13];
+ memcpy_s(dest41, 13, src, strlen(src));
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: the result from calling 'memcpy_s' is not null-terminated [bugprone-not-null-terminated-result]
+ // CHECK-FIXES: char dest41[14];
+ // CHECK-FIXES: strcpy_s(dest41, src);
+}
+
+void good_memcpy_s_known_dest(const char *src) {
+ char dst41[14];
+ strcpy_s(dst41, src);
+}
+
+//===----------------------------------------------------------------------===//
+// memcpy_s() - length tests
+//===----------------------------------------------------------------------===//
+
+void bad_memcpy_s_full_source_length(const char *src) {
+ char dest60[13];
+ memcpy_s(dest60, 13, src, strlen(src));
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: the result from calling 'memcpy_s' is not null-terminated [bugprone-not-null-terminated-result]
+ // CHECK-FIXES: char dest60[14];
+ // CHECK-FIXES-NEXT: strcpy_s(dest60, src);
+}
+
+void good_memcpy_s_full_source_length(const char *src) {
+ char dst60[14];
+ strcpy_s(dst60, src);
+}
+
+void bad_memcpy_s_partial_source_length(const char *src) {
+ char dest61[13];
+ memcpy_s(dest61, 13, src, strlen(src) - 1);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: the result from calling 'memcpy_s' is not null-terminated [bugprone-not-null-terminated-result]
+ // CHECK-FIXES: char dest61[14];
+ // CHECK-FIXES-NEXT: strncpy_s(dest61, src, strlen(src) - 1);
+}
+
+void good_memcpy_s_partial_source_length(const char *src) {
+ char dst61[14];
+ strncpy_s(dst61, src, strlen(src) - 1);
+}
diff --git a/clang-tools-extra/test/clang-tidy/bugprone-not-null-terminated-result-memcpy-safe-other.c b/clang-tools-extra/test/clang-tidy/bugprone-not-null-terminated-result-memcpy-safe-other.c
new file mode 100644
index 00000000000..0a4a45994fd
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/bugprone-not-null-terminated-result-memcpy-safe-other.c
@@ -0,0 +1,112 @@
+// RUN: %check_clang_tidy %s bugprone-not-null-terminated-result %t -- \
+// RUN: -- -std=c11 -I %S/Inputs/bugprone-not-null-terminated-result
+
+#include "not-null-terminated-result-c.h"
+
+#define __STDC_LIB_EXT1__ 1
+#define __STDC_WANT_LIB_EXT1__ 1
+
+#define SRC_LENGTH 3
+#define SRC "foo"
+
+//===----------------------------------------------------------------------===//
+// False positive suppression.
+//===----------------------------------------------------------------------===//
+
+void good_memcpy_known_src() {
+ char dest[13];
+ char src[] = "foobar";
+ memcpy(dest, src, sizeof(src));
+}
+
+void good_memcpy_null_terminated(const char *src) {
+ char dest[13];
+ const int length = strlen(src);
+ memcpy(dest, src, length);
+ dest[length] = '\0';
+}
+
+void good_memcpy_proper_length(const char *src) {
+ char *dest = 0;
+ int length = strlen(src) + 1;
+ dest = (char *)malloc(length);
+ memcpy(dest, src, length);
+}
+
+void may_bad_memcpy_unknown_length(const char *src, int length) {
+ char dest[13];
+ memcpy(dest, src, length);
+}
+
+void may_bad_memcpy_const_length(const char *src) {
+ char dest[13];
+ memcpy(dest, src, 12);
+}
+
+//===----------------------------------------------------------------------===//
+// Special cases.
+//===----------------------------------------------------------------------===//
+
+void bad_memcpy_unknown_dest(char *dest01, const char *src) {
+ memcpy(dest01, src, strlen(src));
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: the result from calling 'memcpy' is not null-terminated [bugprone-not-null-terminated-result]
+ // CHECK-FIXES: strcpy(dest01, src);
+}
+
+void good_memcpy_unknown_dest(char *dst01, const char *src) {
+ strcpy(dst01, src);
+}
+
+void bad_memcpy_variable_array(int dest_length) {
+ char dest02[dest_length + 1];
+ memcpy(dest02, "foobarbazqux", strlen("foobarbazqux"));
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: the result from calling 'memcpy' is not null-terminated [bugprone-not-null-terminated-result]
+ // CHECK-FIXES: strcpy(dest02, "foobarbazqux");
+}
+
+void good_memcpy_variable_array(int dest_length) {
+ char dst02[dest_length + 1];
+ strcpy(dst02, "foobarbazqux");
+}
+
+void bad_memcpy_equal_src_length_and_length() {
+ char dest03[13];
+ const char *src = "foobarbazqux";
+ memcpy(dest03, src, 12);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: the result from calling 'memcpy' is not null-terminated [bugprone-not-null-terminated-result]
+ // CHECK-FIXES: strcpy(dest03, src);
+}
+
+void good_memcpy_equal_src_length_and_length() {
+ char dst03[13];
+ const char *src = "foobarbazqux";
+ strcpy(dst03, src);
+}
+
+void bad_memcpy_dest_size_overflows(const char *src) {
+ const int length = strlen(src);
+ char *dest04 = (char *)malloc(length);
+ memcpy(dest04, src, length);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: the result from calling 'memcpy' is not null-terminated [bugprone-not-null-terminated-result]
+ // CHECK-FIXES: char *dest04 = (char *)malloc(length + 1);
+ // CHECK-FIXES-NEXT: strcpy(dest04, src);
+}
+
+void good_memcpy_dest_size_overflows(const char *src) {
+ const int length = strlen(src);
+ char *dst04 = (char *)malloc(length + 1);
+ strcpy(dst04, src);
+}
+
+void bad_memcpy_macro() {
+ char dest05[SRC_LENGTH];
+ memcpy(dest05, SRC, SRC_LENGTH);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: the result from calling 'memcpy' is not null-terminated [bugprone-not-null-terminated-result]
+ // CHECK-FIXES: char dest05[SRC_LENGTH + 1];
+ // CHECK-FIXES-NEXT: strcpy(dest05, SRC);
+}
+
+void good_memcpy_macro() {
+ char dst05[SRC_LENGTH + 1];
+ strcpy(dst05, SRC);
+}
diff --git a/clang-tools-extra/test/clang-tidy/bugprone-not-null-terminated-result-memcpy-safe.c b/clang-tools-extra/test/clang-tidy/bugprone-not-null-terminated-result-memcpy-safe.c
new file mode 100644
index 00000000000..9a2d48fcae2
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/bugprone-not-null-terminated-result-memcpy-safe.c
@@ -0,0 +1,124 @@
+// RUN: %check_clang_tidy %s bugprone-not-null-terminated-result %t -- \
+// RUN: -- -std=c11 -I %S/Inputs/bugprone-not-null-terminated-result
+
+#include "not-null-terminated-result-c.h"
+
+#define __STDC_LIB_EXT1__ 1
+#define __STDC_WANT_LIB_EXT1__ 1
+
+//===----------------------------------------------------------------------===//
+// memcpy() - destination array tests
+//===----------------------------------------------------------------------===//
+
+void bad_memcpy_not_just_char_dest(const char *src) {
+ unsigned char dest00[13];
+ memcpy(dest00, src, strlen(src));
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: the result from calling 'memcpy' is not null-terminated [bugprone-not-null-terminated-result]
+ // CHECK-FIXES: unsigned char dest00[14];
+ // CHECK-FIXES-NEXT: strcpy_s((char *)dest00, 14, src);
+}
+
+void good_memcpy_not_just_char_dest(const char *src) {
+ unsigned char dst00[14];
+ strcpy_s((char *)dst00, 14, src);
+}
+
+void bad_memcpy_known_dest(const char *src) {
+ char dest01[13];
+ memcpy(dest01, src, strlen(src));
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: the result from calling 'memcpy' is not null-terminated [bugprone-not-null-terminated-result]
+ // CHECK-FIXES: char dest01[14];
+ // CHECK-FIXES: strcpy_s(dest01, 14, src);
+}
+
+void good_memcpy_known_dest(const char *src) {
+ char dst01[14];
+ strcpy_s(dst01, 14, src);
+}
+
+//===----------------------------------------------------------------------===//
+// memcpy() - length tests
+//===----------------------------------------------------------------------===//
+
+void bad_memcpy_full_source_length(const char *src) {
+ char dest20[13];
+ memcpy(dest20, src, strlen(src));
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: the result from calling 'memcpy' is not null-terminated [bugprone-not-null-terminated-result]
+ // CHECK-FIXES: char dest20[14];
+ // CHECK-FIXES-NEXT: strcpy_s(dest20, 14, src);
+}
+
+void good_memcpy_full_source_length(const char *src) {
+ char dst20[14];
+ strcpy_s(dst20, 14, src);
+}
+
+void bad_memcpy_partial_source_length(const char *src) {
+ char dest21[13];
+ memcpy(dest21, src, strlen(src) - 1);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: the result from calling 'memcpy' is not null-terminated [bugprone-not-null-terminated-result]
+ // CHECK-FIXES: char dest21[14];
+ // CHECK-FIXES-NEXT: strncpy_s(dest21, 14, src, strlen(src) - 1);
+}
+
+void good__memcpy_partial_source_length(const char *src) {
+ char dst21[14];
+ strncpy_s(dst21, 14, src, strlen(src) - 1);
+}
+
+//===----------------------------------------------------------------------===//
+// memcpy_s() - destination array tests
+//===----------------------------------------------------------------------===//
+
+void bad_memcpy_s_unknown_dest(char *dest40, const char *src) {
+ memcpy_s(dest40, 13, src, strlen(src));
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: the result from calling 'memcpy_s' is not null-terminated [bugprone-not-null-terminated-result]
+ // CHECK-FIXES: strcpy_s(dest40, 13, src);
+}
+
+void good_memcpy_s_unknown_dest(char *dst40, const char *src) {
+ strcpy_s(dst40, 13, src);
+}
+
+void bad_memcpy_s_known_dest(const char *src) {
+ char dest41[13];
+ memcpy_s(dest41, 13, src, strlen(src));
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: the result from calling 'memcpy_s' is not null-terminated [bugprone-not-null-terminated-result]
+ // CHECK-FIXES: char dest41[14];
+ // CHECK-FIXES-NEXT: strcpy_s(dest41, 14, src);
+}
+
+void good_memcpy_s_known_dest(const char *src) {
+ char dst41[14];
+ strcpy_s(dst41, 14, src);
+}
+
+//===----------------------------------------------------------------------===//
+// memcpy_s() - length tests
+//===----------------------------------------------------------------------===//
+
+void bad_memcpy_s_full_source_length(const char *src) {
+ char dest60[13];
+ memcpy_s(dest60, 13, src, strlen(src));
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: the result from calling 'memcpy_s' is not null-terminated [bugprone-not-null-terminated-result]
+ // CHECK-FIXES: char dest60[14];
+ // CHECK-FIXES-NEXT: strcpy_s(dest60, 14, src);
+}
+
+void good_memcpy_s_full_source_length(const char *src) {
+ char dst60[14];
+ strcpy_s(dst60, 14, src);
+}
+
+void bad_memcpy_s_partial_source_length(const char *src) {
+ char dest61[13];
+ memcpy_s(dest61, 13, src, strlen(src) - 1);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: the result from calling 'memcpy_s' is not null-terminated [bugprone-not-null-terminated-result]
+ // CHECK-FIXES: char dest61[14];
+ // CHECK-FIXES-NEXT: strncpy_s(dest61, 14, src, strlen(src) - 1);
+}
+
+void good_memcpy_s_partial_source_length(const char *src) {
+ char dst61[14];
+ strncpy_s(dst61, 14, src, strlen(src) - 1);
+}
diff --git a/clang-tools-extra/test/clang-tidy/bugprone-not-null-terminated-result-strlen.c b/clang-tools-extra/test/clang-tidy/bugprone-not-null-terminated-result-strlen.c
new file mode 100644
index 00000000000..48f8c278c86
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/bugprone-not-null-terminated-result-strlen.c
@@ -0,0 +1,118 @@
+// RUN: %check_clang_tidy %s bugprone-not-null-terminated-result %t -- \
+// RUN: -- -std=c11 -I %S/Inputs/bugprone-not-null-terminated-result
+
+#include "not-null-terminated-result-c.h"
+
+#define __STDC_LIB_EXT1__ 1
+#define __STDC_WANT_LIB_EXT1__ 1
+
+void bad_memchr_1(char *position, const char *src) {
+ position = (char *)memchr(src, '\0', strlen(src));
+ // CHECK-MESSAGES: :[[@LINE-1]]:40: warning: the length is too short to include the null terminator [bugprone-not-null-terminated-result]
+ // CHECK-FIXES: position = strchr(src, '\0');
+}
+
+void good_memchr_1(char *pos, const char *src) {
+ pos = strchr(src, '\0');
+}
+
+void bad_memchr_2(char *position) {
+ position = (char *)memchr("foobar", '\0', 6);
+ // CHECK-MESSAGES: :[[@LINE-1]]:45: warning: the length is too short to include the null terminator [bugprone-not-null-terminated-result]
+ // CHECK-FIXES: position = strchr("foobar", '\0');
+}
+
+void good_memchr_2(char *pos) {
+ pos = strchr("foobar", '\0');
+}
+
+void bad_memmove(const char *src) {
+ char dest[13];
+ memmove(dest, src, strlen(src));
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: the result from calling 'memmove' is not null-terminated [bugprone-not-null-terminated-result]
+ // CHECK-FIXES: char dest[14];
+ // CHECK-FIXES-NEXT: memmove_s(dest, 14, src, strlen(src) + 1);
+}
+
+void good_memmove(const char *src) {
+ char dst[14];
+ memmove_s(dst, 13, src, strlen(src) + 1);
+}
+
+void bad_memmove_s(char *dest, const char *src) {
+ memmove_s(dest, 13, src, strlen(src));
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: the result from calling 'memmove_s' is not null-terminated [bugprone-not-null-terminated-result]
+ // CHECK-FIXES: memmove_s(dest, 13, src, strlen(src) + 1);
+}
+
+void good_memmove_s_1(char *dest, const char *src) {
+ memmove_s(dest, 13, src, strlen(src) + 1);
+}
+
+void bad_strerror_s(int errno) {
+ char dest[13];
+ strerror_s(dest, strlen(strerror(errno)), errno);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: the result from calling 'strerror_s' is not null-terminated and missing the last character of the error message [bugprone-not-null-terminated-result]
+ // CHECK-FIXES: char dest[14];
+ // CHECK-FIXES-NEXT: strerror_s(dest, strlen(strerror(errno)) + 1, errno);
+}
+
+void good_strerror_s(int errno) {
+ char dst[14];
+ strerror_s(dst, strlen(strerror(errno)) + 1, errno);
+}
+
+int bad_strncmp_1(char *str0, const char *str1) {
+ return strncmp(str0, str1, (strlen(str0) + 1));
+ // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: comparison length is too long and might lead to a buffer overflow [bugprone-not-null-terminated-result]
+ // CHECK-FIXES: strncmp(str0, str1, (strlen(str0)));
+}
+
+int bad_strncmp_2(char *str2, const char *str3) {
+ return strncmp(str2, str3, 1 + strlen(str2));
+ // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: comparison length is too long and might lead to a buffer overflow [bugprone-not-null-terminated-result]
+ // CHECK-FIXES: strncmp(str2, str3, strlen(str2));
+}
+
+int good_strncmp_1_2(char *str4, const char *str5) {
+ return strncmp(str4, str5, strlen(str4));
+}
+
+int bad_strncmp_3(char *str6) {
+ return strncmp(str6, "string", 7);
+ // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: comparison length is too long and might lead to a buffer overflow [bugprone-not-null-terminated-result]
+ // CHECK-FIXES: strncmp(str6, "string", 6);
+}
+
+int good_strncmp_3(char *str7) {
+ return strncmp(str7, "string", 6);
+}
+
+void bad_strxfrm_1(const char *long_source_name) {
+ char long_destination_array_name[13];
+ strxfrm(long_destination_array_name, long_source_name,
+ strlen(long_source_name));
+ // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: the result from calling 'strxfrm' is not null-terminated [bugprone-not-null-terminated-result]
+ // CHECK-FIXES: char long_destination_array_name[14];
+ // CHECK-FIXES-NEXT: strxfrm(long_destination_array_name, long_source_name,
+ // CHECK-FIXES-NEXT: strlen(long_source_name) + 1);
+}
+
+void good_strxfrm_1(const char *long_source_name) {
+ char long_destination_array_name[14];
+ strxfrm(long_destination_array_name, long_source_name,
+ strlen(long_source_name) + 1);
+}
+
+void bad_strxfrm_2() {
+ char long_destination_array_name1[16];
+ strxfrm(long_destination_array_name1, "long_source_name", 16);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: the result from calling 'strxfrm' is not null-terminated [bugprone-not-null-terminated-result]
+ // CHECK-FIXES: char long_destination_array_name1[17];
+ // CHECK-FIXES: strxfrm(long_destination_array_name1, "long_source_name", 17);
+}
+
+void good_strxfrm_2() {
+ char long_destination_array_name2[17];
+ strxfrm(long_destination_array_name2, "long_source_name", 17);
+}
diff --git a/clang-tools-extra/test/clang-tidy/bugprone-not-null-terminated-result-wcslen.cpp b/clang-tools-extra/test/clang-tidy/bugprone-not-null-terminated-result-wcslen.cpp
new file mode 100644
index 00000000000..b8ac76cc901
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/bugprone-not-null-terminated-result-wcslen.cpp
@@ -0,0 +1,106 @@
+// RUN: %check_clang_tidy %s bugprone-not-null-terminated-result %t -- \
+// RUN: -- -std=c++11 -I %S/Inputs/bugprone-not-null-terminated-result
+
+#include "not-null-terminated-result-cxx.h"
+
+#define __STDC_LIB_EXT1__ 1
+#define __STDC_WANT_LIB_EXT1__ 1
+
+void bad_wmemchr_1(wchar_t *position, const wchar_t *src) {
+ position = (wchar_t *)wmemchr(src, L'\0', wcslen(src));
+ // CHECK-MESSAGES: :[[@LINE-1]]:45: warning: the length is too short to include the null terminator [bugprone-not-null-terminated-result]
+ // CHECK-FIXES: position = wcschr(src, L'\0');
+}
+
+void good_wmemchr_1(wchar_t *pos, const wchar_t *src) {
+ pos = wcschr(src, L'\0');
+}
+
+void bad_wmemchr_2(wchar_t *position) {
+ position = (wchar_t *)wmemchr(L"foobar", L'\0', 6);
+ // CHECK-MESSAGES: :[[@LINE-1]]:51: warning: the length is too short to include the null terminator [bugprone-not-null-terminated-result]
+ // CHECK-FIXES: position = wcschr(L"foobar", L'\0');
+}
+
+void good_wmemchr_2(wchar_t *pos) {
+ pos = wcschr(L"foobar", L'\0');
+}
+
+
+void bad_wmemmove(const wchar_t *src) {
+ wchar_t dest[13];
+ wmemmove(dest, src, wcslen(src));
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: the result from calling 'wmemmove' is not null-terminated [bugprone-not-null-terminated-result]
+ // CHECK-FIXES: wchar_t dest[14];
+ // CHECK-FIXES-NEXT: wmemmove_s(dest, 14, src, wcslen(src) + 1);
+}
+
+void good_wmemmove(const wchar_t *src) {
+ wchar_t dst[14];
+ wmemmove_s(dst, 13, src, wcslen(src) + 1);
+}
+
+void bad_wmemmove_s(wchar_t *dest, const wchar_t *src) {
+ wmemmove_s(dest, 13, src, wcslen(src));
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: the result from calling 'wmemmove_s' is not null-terminated [bugprone-not-null-terminated-result]
+ // CHECK-FIXES: wmemmove_s(dest, 13, src, wcslen(src) + 1);
+}
+
+void good_wmemmove_s_1(wchar_t *dest, const wchar_t *src) {
+ wmemmove_s(dest, 13, src, wcslen(src) + 1);
+}
+
+int bad_wcsncmp_1(wchar_t *wcs0, const wchar_t *wcs1) {
+ return wcsncmp(wcs0, wcs1, (wcslen(wcs0) + 1));
+ // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: comparison length is too long and might lead to a buffer overflow [bugprone-not-null-terminated-result]
+ // CHECK-FIXES: wcsncmp(wcs0, wcs1, (wcslen(wcs0)));
+}
+
+int bad_wcsncmp_2(wchar_t *wcs2, const wchar_t *wcs3) {
+ return wcsncmp(wcs2, wcs3, 1 + wcslen(wcs2));
+ // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: comparison length is too long and might lead to a buffer overflow [bugprone-not-null-terminated-result]
+ // CHECK-FIXES: wcsncmp(wcs2, wcs3, wcslen(wcs2));
+}
+
+int good_wcsncmp_1_2(wchar_t *wcs4, const wchar_t *wcs5) {
+ return wcsncmp(wcs4, wcs5, wcslen(wcs4));
+}
+
+int bad_wcsncmp_3(wchar_t *wcs6) {
+ return wcsncmp(wcs6, L"string", 7);
+ // CHECK-MESSAGES: :[[@LINE-1]]:35: warning: comparison length is too long and might lead to a buffer overflow [bugprone-not-null-terminated-result]
+ // CHECK-FIXES: wcsncmp(wcs6, L"string", 6);
+}
+
+int good_wcsncmp_3(wchar_t *wcs7) {
+ return wcsncmp(wcs7, L"string", 6);
+}
+
+void bad_wcsxfrm_1(const wchar_t *long_source_name) {
+ wchar_t long_destination_array_name[13];
+ wcsxfrm(long_destination_array_name, long_source_name,
+ wcslen(long_source_name));
+ // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: the result from calling 'wcsxfrm' is not null-terminated [bugprone-not-null-terminated-result]
+ // CHECK-FIXES: wchar_t long_destination_array_name[14];
+ // CHECK-FIXES-NEXT: wcsxfrm(long_destination_array_name, long_source_name,
+ // CHECK-FIXES-NEXT: wcslen(long_source_name) + 1);
+}
+
+void good_wcsxfrm_1(const wchar_t *long_source_name) {
+ wchar_t long_destination_array_name[14];
+ wcsxfrm(long_destination_array_name, long_source_name,
+ wcslen(long_source_name) + 1);
+}
+
+void bad_wcsxfrm_2() {
+ wchar_t long_destination_array_name1[16];
+ wcsxfrm(long_destination_array_name1, L"long_source_name", 16);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: the result from calling 'wcsxfrm' is not null-terminated [bugprone-not-null-terminated-result]
+ // CHECK-FIXES: wchar_t long_destination_array_name1[17];
+ // CHECK-FIXES: wcsxfrm(long_destination_array_name1, L"long_source_name", 17);
+}
+
+void good_wcsxfrm_2() {
+ wchar_t long_destination_array_name2[17];
+ wcsxfrm(long_destination_array_name2, L"long_source_name", 17);
+}
diff --git a/clang-tools-extra/test/clang-tidy/bugprone-not-null-terminated-result-wmemcpy-safe-cxx.cpp b/clang-tools-extra/test/clang-tidy/bugprone-not-null-terminated-result-wmemcpy-safe-cxx.cpp
new file mode 100644
index 00000000000..6c8aee0af13
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/bugprone-not-null-terminated-result-wmemcpy-safe-cxx.cpp
@@ -0,0 +1,111 @@
+// RUN: %check_clang_tidy %s bugprone-not-null-terminated-result %t -- \
+// RUN: -- -std=c++11 -I %S/Inputs/bugprone-not-null-terminated-result
+
+#include "not-null-terminated-result-cxx.h"
+
+#define __STDC_LIB_EXT1__ 1
+#define __STDC_WANT_LIB_EXT1__ 1
+
+//===----------------------------------------------------------------------===//
+// wmemcpy() - destination array tests
+//===----------------------------------------------------------------------===//
+
+void bad_wmemcpy_known_dest(const wchar_t *src) {
+ wchar_t dest01[13];
+ wmemcpy(dest01, src, wcslen(src));
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: the result from calling 'wmemcpy' is not null-terminated [bugprone-not-null-terminated-result]
+ // CHECK-FIXES: wchar_t dest01[14];
+ // CHECK-FIXES-NEXT: wcscpy_s(dest01, src);
+}
+
+void good_wmemcpy_known_dest(const wchar_t *src) {
+ wchar_t dst01[14];
+ wcscpy_s(dst01, src);
+}
+
+//===----------------------------------------------------------------------===//
+// wmemcpy() - length tests
+//===----------------------------------------------------------------------===//
+
+void bad_wmemcpy_full_source_length(const wchar_t *src) {
+ wchar_t dest20[13];
+ wmemcpy(dest20, src, wcslen(src));
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: the result from calling 'wmemcpy' is not null-terminated [bugprone-not-null-terminated-result]
+ // CHECK-FIXES: wchar_t dest20[14];
+ // CHECK-FIXES-NEXT: wcscpy_s(dest20, src);
+}
+
+void good_wmemcpy_full_source_length(const wchar_t *src) {
+ wchar_t dst20[14];
+ wcscpy_s(dst20, src);
+}
+
+void bad_wmemcpy_partial_source_length(const wchar_t *src) {
+ wchar_t dest21[13];
+ wmemcpy(dest21, src, wcslen(src) - 1);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: the result from calling 'wmemcpy' is not null-terminated [bugprone-not-null-terminated-result]
+ // CHECK-FIXES: wchar_t dest21[14];
+ // CHECK-FIXES-NEXT: wcsncpy_s(dest21, src, wcslen(src) - 1);
+}
+
+void good_wmemcpy_partial_source_length(const wchar_t *src) {
+ wchar_t dst21[14];
+ wcsncpy_s(dst21, src, wcslen(src) - 1);
+}
+
+//===----------------------------------------------------------------------===//
+// wmemcpy_s() - destination array tests
+//===----------------------------------------------------------------------===//
+
+void bad_wmemcpy_s_unknown_dest(wchar_t *dest40, const wchar_t *src) {
+ wmemcpy_s(dest40, 13, src, wcslen(src));
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: the result from calling 'wmemcpy_s' is not null-terminated [bugprone-not-null-terminated-result]
+ // CHECK-FIXES: wcscpy_s(dest40, 13, src);
+}
+
+void good_wmemcpy_s_unknown_dest(wchar_t *dst40, const wchar_t *src) {
+ wcscpy_s(dst40, 13, src);
+}
+
+void bad_wmemcpy_s_known_dest(const wchar_t *src) {
+ wchar_t dest41[13];
+ wmemcpy_s(dest41, 13, src, wcslen(src));
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: the result from calling 'wmemcpy_s' is not null-terminated [bugprone-not-null-terminated-result]
+ // CHECK-FIXES: wchar_t dest41[14];
+ // CHECK-FIXES-NEXT: wcscpy_s(dest41, src);
+}
+
+void good_wmemcpy_s_known_dest(const wchar_t *src) {
+ wchar_t dst41[13];
+ wcscpy_s(dst41, src);
+}
+
+//===----------------------------------------------------------------------===//
+// wmemcpy_s() - length tests
+//===----------------------------------------------------------------------===//
+
+void bad_wmemcpy_s_full_source_length(const wchar_t *src) {
+ wchar_t dest60[13];
+ wmemcpy_s(dest60, 13, src, wcslen(src));
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: the result from calling 'wmemcpy_s' is not null-terminated [bugprone-not-null-terminated-result]
+ // CHECK-FIXES: wchar_t dest60[14];
+ // CHECK-FIXES-NEXT: wcscpy_s(dest60, src);
+}
+
+void good_wmemcpy_s_full_source_length(const wchar_t *src) {
+ wchar_t dst60[13];
+ wcscpy_s(dst60, src);
+}
+
+void bad_wmemcpy_s_partial_source_length(const wchar_t *src) {
+ wchar_t dest61[13];
+ wmemcpy_s(dest61, 13, src, wcslen(src) - 1);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: the result from calling 'wmemcpy_s' is not null-terminated [bugprone-not-null-terminated-result]
+ // CHECK-FIXES: wchar_t dest61[14];
+ // CHECK-FIXES-NEXT: wcsncpy_s(dest61, src, wcslen(src) - 1);
+}
+
+void good_wmemcpy_s_partial_source_length(const wchar_t *src) {
+ wchar_t dst61[13];
+ wcsncpy_s(dst61, src, wcslen(src) - 1);
+}
OpenPOWER on IntegriCloud