1341588afadc46bf6f0dc7babd6d531209aba5202Alexander Potapenko//===-- sanitizer_libc_test.cc --------------------------------------------===//
2341588afadc46bf6f0dc7babd6d531209aba5202Alexander Potapenko//
3341588afadc46bf6f0dc7babd6d531209aba5202Alexander Potapenko//                     The LLVM Compiler Infrastructure
4341588afadc46bf6f0dc7babd6d531209aba5202Alexander Potapenko//
5341588afadc46bf6f0dc7babd6d531209aba5202Alexander Potapenko// This file is distributed under the University of Illinois Open Source
6341588afadc46bf6f0dc7babd6d531209aba5202Alexander Potapenko// License. See LICENSE.TXT for details.
7341588afadc46bf6f0dc7babd6d531209aba5202Alexander Potapenko//
8341588afadc46bf6f0dc7babd6d531209aba5202Alexander Potapenko//===----------------------------------------------------------------------===//
9341588afadc46bf6f0dc7babd6d531209aba5202Alexander Potapenko// Tests for sanitizer_libc.h.
10341588afadc46bf6f0dc7babd6d531209aba5202Alexander Potapenko//===----------------------------------------------------------------------===//
11341588afadc46bf6f0dc7babd6d531209aba5202Alexander Potapenko
124c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov#include "sanitizer_common/sanitizer_common.h"
13341588afadc46bf6f0dc7babd6d531209aba5202Alexander Potapenko#include "sanitizer_common/sanitizer_libc.h"
14a615b26e3e3c2da0b2f950f506f6c2c220430c19Sergey Matveev#include "sanitizer_common/sanitizer_platform.h"
15341588afadc46bf6f0dc7babd6d531209aba5202Alexander Potapenko#include "gtest/gtest.h"
16341588afadc46bf6f0dc7babd6d531209aba5202Alexander Potapenko
17a615b26e3e3c2da0b2f950f506f6c2c220430c19Sergey Matveev#if SANITIZER_LINUX || SANITIZER_MAC
184c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov# define SANITIZER_TEST_HAS_STAT_H 1
194c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov# include <sys/stat.h>
20909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar# include "sanitizer_common/sanitizer_posix.h"
214c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov#else
224c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov# define SANITIZER_TEST_HAS_STAT_H 0
234c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov#endif
244c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov
25341588afadc46bf6f0dc7babd6d531209aba5202Alexander Potapenko// A regression test for internal_memmove() implementation.
26341588afadc46bf6f0dc7babd6d531209aba5202Alexander PotapenkoTEST(SanitizerCommon, InternalMemmoveRegression) {
27341588afadc46bf6f0dc7babd6d531209aba5202Alexander Potapenko  char src[] = "Hello World";
28341588afadc46bf6f0dc7babd6d531209aba5202Alexander Potapenko  char *dest = src + 6;
29341588afadc46bf6f0dc7babd6d531209aba5202Alexander Potapenko  __sanitizer::internal_memmove(dest, src, 5);
30341588afadc46bf6f0dc7babd6d531209aba5202Alexander Potapenko  EXPECT_EQ(dest[0], src[0]);
31341588afadc46bf6f0dc7babd6d531209aba5202Alexander Potapenko  EXPECT_EQ(dest[4], src[4]);
32341588afadc46bf6f0dc7babd6d531209aba5202Alexander Potapenko}
33eb2809311c94b73c269ccef8d68ae368642e5754Kostya Serebryany
34eb2809311c94b73c269ccef8d68ae368642e5754Kostya SerebryanyTEST(SanitizerCommon, mem_is_zero) {
35eb2809311c94b73c269ccef8d68ae368642e5754Kostya Serebryany  size_t size = 128;
36eb2809311c94b73c269ccef8d68ae368642e5754Kostya Serebryany  char *x = new char[size];
37eb2809311c94b73c269ccef8d68ae368642e5754Kostya Serebryany  memset(x, 0, size);
38eb2809311c94b73c269ccef8d68ae368642e5754Kostya Serebryany  for (size_t pos = 0; pos < size; pos++) {
39eb2809311c94b73c269ccef8d68ae368642e5754Kostya Serebryany    x[pos] = 1;
40eb2809311c94b73c269ccef8d68ae368642e5754Kostya Serebryany    for (size_t beg = 0; beg < size; beg++) {
41eb2809311c94b73c269ccef8d68ae368642e5754Kostya Serebryany      for (size_t end = beg; end < size; end++) {
42eb2809311c94b73c269ccef8d68ae368642e5754Kostya Serebryany        // fprintf(stderr, "pos %zd beg %zd end %zd \n", pos, beg, end);
43eb2809311c94b73c269ccef8d68ae368642e5754Kostya Serebryany        if (beg <= pos && pos < end)
44eb2809311c94b73c269ccef8d68ae368642e5754Kostya Serebryany          EXPECT_FALSE(__sanitizer::mem_is_zero(x + beg, end - beg));
45eb2809311c94b73c269ccef8d68ae368642e5754Kostya Serebryany        else
46eb2809311c94b73c269ccef8d68ae368642e5754Kostya Serebryany          EXPECT_TRUE(__sanitizer::mem_is_zero(x + beg, end - beg));
47eb2809311c94b73c269ccef8d68ae368642e5754Kostya Serebryany      }
48eb2809311c94b73c269ccef8d68ae368642e5754Kostya Serebryany    }
49eb2809311c94b73c269ccef8d68ae368642e5754Kostya Serebryany    x[pos] = 0;
50eb2809311c94b73c269ccef8d68ae368642e5754Kostya Serebryany  }
51eb2809311c94b73c269ccef8d68ae368642e5754Kostya Serebryany  delete [] x;
52eb2809311c94b73c269ccef8d68ae368642e5754Kostya Serebryany}
534c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov
542be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanovstruct stat_and_more {
552be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  struct stat st;
562be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  unsigned char z;
572be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov};
582be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov
5986277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesstatic void temp_file_name(char *buf, size_t bufsize, const char *prefix) {
6086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  const char *tmpdir = "/tmp";
6186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#if SANITIZER_ANDROID
6286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  // I don't know a way to query temp directory location on Android without
6386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  // going through Java interfaces. The code below is not ideal, but should
6486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  // work. May require "adb root", but it is needed for almost any use of ASan
6586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  // on Android already.
6686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  tmpdir = GetEnv("EXTERNAL_STORAGE");
6786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#endif
6886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  u32 uid = GetUid();
6986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  internal_snprintf(buf, bufsize, "%s/%s%d", tmpdir, prefix, uid);
7086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
7186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
722d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// FIXME: File manipulations are not yet supported on Windows
732d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if !defined(_WIN32)
744c9317a7b61e136f832d2ede70f557963fd46bceAlexey SamsonovTEST(SanitizerCommon, FileOps) {
754c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov  const char *str1 = "qwerty";
764c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov  uptr len1 = internal_strlen(str1);
774c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov  const char *str2 = "zxcv";
784c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov  uptr len2 = internal_strlen(str2);
794c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov
8086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  char tmpfile[128];
8186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  temp_file_name(tmpfile, sizeof(tmpfile), "sanitizer_common.fileops.tmp.");
82909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar  fd_t fd = OpenFile(tmpfile, WrOnly);
83909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar  ASSERT_NE(fd, kInvalidFd);
844c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov  EXPECT_EQ(len1, internal_write(fd, str1, len1));
854c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov  EXPECT_EQ(len2, internal_write(fd, str2, len2));
86909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar  CloseFile(fd);
874c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov
88909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar  fd = OpenFile(tmpfile, RdOnly);
89909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar  ASSERT_NE(fd, kInvalidFd);
904c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov  uptr fsize = internal_filesize(fd);
914c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov  EXPECT_EQ(len1 + len2, fsize);
924c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov
934c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov#if SANITIZER_TEST_HAS_STAT_H
944c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov  struct stat st1, st2, st3;
9586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  EXPECT_EQ(0u, internal_stat(tmpfile, &st1));
9686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  EXPECT_EQ(0u, internal_lstat(tmpfile, &st2));
979578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne  EXPECT_EQ(0u, internal_fstat(fd, &st3));
984c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov  EXPECT_EQ(fsize, (uptr)st3.st_size);
992be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov
1002be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  // Verify that internal_fstat does not write beyond the end of the supplied
1012be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  // buffer.
1022be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  struct stat_and_more sam;
1032be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  memset(&sam, 0xAB, sizeof(sam));
1049578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne  EXPECT_EQ(0u, internal_fstat(fd, &sam.st));
1052be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  EXPECT_EQ(0xAB, sam.z);
1062be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  EXPECT_NE(0xAB, sam.st.st_size);
1072be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov  EXPECT_NE(0, sam.st.st_size);
1084c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov#endif
1094c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov
1104c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov  char buf[64] = {};
1114c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov  EXPECT_EQ(len1, internal_read(fd, buf, len1));
1124c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov  EXPECT_EQ(0, internal_memcmp(buf, str1, len1));
1134c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov  EXPECT_EQ((char)0, buf[len1 + 1]);
1144c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov  internal_memset(buf, 0, len1);
1154c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov  EXPECT_EQ(len2, internal_read(fd, buf, len2));
1164c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov  EXPECT_EQ(0, internal_memcmp(buf, str2, len2));
117909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar  CloseFile(fd);
11886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  internal_unlink(tmpfile);
1194c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov}
1202d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
1212be3a283939d4fc14ad86f6cd8be34b1468f22baEvgeniy Stepanov
12272870db5f2e0e83b2e925eef594dacfae275a8deAlexey SamsonovTEST(SanitizerCommon, InternalStrFunctions) {
12372870db5f2e0e83b2e925eef594dacfae275a8deAlexey Samsonov  const char *haystack = "haystack";
12472870db5f2e0e83b2e925eef594dacfae275a8deAlexey Samsonov  EXPECT_EQ(haystack + 2, internal_strchr(haystack, 'y'));
12572870db5f2e0e83b2e925eef594dacfae275a8deAlexey Samsonov  EXPECT_EQ(haystack + 2, internal_strchrnul(haystack, 'y'));
12672870db5f2e0e83b2e925eef594dacfae275a8deAlexey Samsonov  EXPECT_EQ(0, internal_strchr(haystack, 'z'));
12772870db5f2e0e83b2e925eef594dacfae275a8deAlexey Samsonov  EXPECT_EQ(haystack + 8, internal_strchrnul(haystack, 'z'));
12872870db5f2e0e83b2e925eef594dacfae275a8deAlexey Samsonov}
12986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
13086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// FIXME: File manipulations are not yet supported on Windows
13186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#if !defined(_WIN32) && !SANITIZER_MAC
13286277eb844c4983c81de62d7c050e92fe7155788Stephen HinesTEST(SanitizerCommon, InternalMmapWithOffset) {
13386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  char tmpfile[128];
13486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  temp_file_name(tmpfile, sizeof(tmpfile),
13586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines                 "sanitizer_common.internalmmapwithoffset.tmp.");
136909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar  fd_t fd = OpenFile(tmpfile, RdWr);
137909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar  ASSERT_NE(fd, kInvalidFd);
13886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
13986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  uptr page_size = GetPageSizeCached();
140909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar  uptr res = internal_ftruncate(fd, page_size * 2);
14186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  ASSERT_FALSE(internal_iserror(res));
14286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
14386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  res = internal_lseek(fd, page_size, SEEK_SET);
14486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  ASSERT_FALSE(internal_iserror(res));
14586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
14686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  res = internal_write(fd, "AB", 2);
14786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  ASSERT_FALSE(internal_iserror(res));
14886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
14986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  char *p = (char *)MapWritableFileToMemory(nullptr, page_size, fd, page_size);
15086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  ASSERT_NE(nullptr, p);
15186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
15286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  ASSERT_EQ('A', p[0]);
15386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  ASSERT_EQ('B', p[1]);
15486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
155909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar  CloseFile(fd);
156909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar  UnmapOrDie(p, page_size);
15786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  internal_unlink(tmpfile);
15886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
15986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#endif
160