Add new tests for memory/string routines.
Create a few generic testing functions to allow any memory/string tests
to be created.
Add alignment tests for memcpy/memset/strcat/strcpy/strlen.
Add an overread test for memcpy/strcat/strcpy/strlen. This test attempts
to verify that the functions do not read past the end of their buffers
(src buffer in the case of src/dst functions).
Bug: 9797008
Change-Id: Ib3223ca1b99e729ae8229adc2d03f4dc3103d97c
diff --git a/tests/string_test.cpp b/tests/string_test.cpp
index ef43f5d..be46dc9 100644
--- a/tests/string_test.cpp
+++ b/tests/string_test.cpp
@@ -20,8 +20,11 @@
#include <math.h>
#include <string.h>
+#include "buffer_tests.h"
+
#define KB 1024
#define SMALL 1*KB
+#define MEDIUM 4*KB
#define LARGE 64*KB
static int signum(int i) {
@@ -885,3 +888,122 @@
ASSERT_EQ(0, memcmp(state.ptr1, state.ptr2, state.MAX_LEN));
}
}
+
+static void DoMemcpyTest(uint8_t* src, uint8_t* dst, size_t len) {
+ memset(src, (len % 255) + 1, len);
+ memset(dst, 0, len);
+
+ ASSERT_EQ(dst, memcpy(dst, src, len));
+ ASSERT_TRUE(memcmp(src, dst, len) == 0);
+}
+
+TEST(string, memcpy_align) {
+ RunSrcDstBufferAlignTest(LARGE, DoMemcpyTest);
+}
+
+TEST(string, memcpy_overread) {
+ RunSrcDstBufferOverreadTest(DoMemcpyTest);
+}
+
+static void DoMemsetTest(uint8_t* buf, size_t len) {
+ for (size_t i = 0; i < len; i++) {
+ buf[i] = 0;
+ }
+ int value = (len % 255) + 1;
+ ASSERT_EQ(buf, memset(buf, value, len));
+ for (size_t i = 0; i < len; i++) {
+ ASSERT_EQ(value, buf[i]);
+ }
+}
+
+TEST(string, memset_align) {
+ RunSingleBufferAlignTest(LARGE, DoMemsetTest);
+}
+
+static void DoStrlenTest(uint8_t* buf, size_t len) {
+ if (len >= 1) {
+ memset(buf, (32 + (len % 96)), len - 1);
+ buf[len-1] = '\0';
+ ASSERT_EQ(len-1, strlen(reinterpret_cast<char*>(buf)));
+ }
+}
+
+TEST(string, strlen_align) {
+ RunSingleBufferAlignTest(LARGE, DoStrlenTest);
+}
+
+TEST(string, strlen_overread) {
+ RunSingleBufferOverreadTest(DoStrlenTest);
+}
+
+static void DoStrcpyTest(uint8_t* src, uint8_t* dst, size_t len) {
+ if (len >= 1) {
+ memset(src, (32 + (len % 96)), len - 1);
+ src[len-1] = '\0';
+ memset(dst, 0, len);
+ ASSERT_EQ(dst, reinterpret_cast<uint8_t*>(strcpy(reinterpret_cast<char*>(dst),
+ reinterpret_cast<char*>(src))));
+ ASSERT_TRUE(memcmp(src, dst, len) == 0);
+ }
+}
+
+TEST(string, strcpy_align) {
+ RunSrcDstBufferAlignTest(LARGE, DoStrcpyTest);
+}
+
+TEST(string, strcpy_overread) {
+ RunSrcDstBufferOverreadTest(DoStrcpyTest);
+}
+
+// Use our own incrementer to cut down on the total number of calls.
+static size_t StrcatSetIncrement(size_t len) {
+ if (len >= 4096) {
+ return 4096;
+ } else if (len >= 1024) {
+ return 1024;
+ } else if (len >= 256) {
+ return 256;
+ }
+ return 1;
+}
+
+#define STRCAT_DST_LEN 128
+
+static void DoStrcatTest(uint8_t* src, uint8_t* dst, size_t len) {
+ if (len >= 1) {
+ int value = 32 + (len % 96);
+ memset(src, value, len - 1);
+ src[len-1] = '\0';
+
+ if (len >= STRCAT_DST_LEN) {
+ // Create a small buffer for doing quick compares in each loop.
+ uint8_t cmp_buf[STRCAT_DST_LEN];
+ // Make sure dst string contains a different value then the src string.
+ int value2 = 32 + (value + 2) % 96;
+ memset(cmp_buf, value2, sizeof(cmp_buf));
+
+ for (size_t i = 1; i <= STRCAT_DST_LEN; i++) {
+ memset(dst, value2, i-1);
+ memset(dst+i-1, 0, len-i);
+ src[len-i] = '\0';
+ ASSERT_EQ(dst, reinterpret_cast<uint8_t*>(strcat(reinterpret_cast<char*>(dst),
+ reinterpret_cast<char*>(src))));
+ ASSERT_TRUE(memcmp(dst, cmp_buf, i-1) == 0);
+ ASSERT_TRUE(memcmp(src, dst+i-1, len-i+1) == 0);
+ }
+ } else {
+ dst[0] = '\0';
+ ASSERT_EQ(dst, reinterpret_cast<uint8_t*>(strcat(reinterpret_cast<char*>(dst),
+ reinterpret_cast<char*>(src))));
+ ASSERT_TRUE(memcmp(src, dst, len) == 0);
+ }
+ }
+}
+
+TEST(string, strcat_align) {
+ RunSrcDstBufferAlignTest(MEDIUM, DoStrcatTest, StrcatSetIncrement);
+}
+
+TEST(string, strcat_overread) {
+ RunSrcDstBufferOverreadTest(DoStrcatTest);
+}