Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Android/bionic/bionic/tests/   (Android Betriebssystem Version 17©)  Datei vom 26.5.2026 mit Größe 10 kB image not shown  

Impressum sys_mman_test.cpp

  Sprache: C
 

/*
 * Copyright (C) 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


#include <fcntl.h>
#include <sys/mman.h>
#include <sys/user.h>
#include <sys/types.h>
#include <unistd.h>

#include <android-base/file.h>
#include <gtest/gtest.h>

#include "utils.h"

static const size_t kPageSize = getpagesize();

TEST(sys_mman, mmap_std) {
  void* map = mmap(nullptr, 4096, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -10);
  ASSERT_NE(MAP_FAILED, map);
  ASSERT_EQ(0, munmap(map, 4096));
}

TEST(sys_mman, mmap64_std) {
  void* map = mmap64(nullptr, 4096, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -10);
  ASSERT_NE(MAP_FAILED, map);
  ASSERT_EQ(0, munmap(map, 4096));
}

TEST(sys_mman, mmap_file_bad_offset) {
  TemporaryFile tf;

  void* map = mmap(nullptr, 100, PROT_READ, MAP_SHARED, tf.fd, 1);
  ASSERT_EQ(MAP_FAILED, map);
}

TEST(sys_mman, mmap64_file_bad_offset) {
  TemporaryFile tf;

  void* map = mmap64(nullptr, 100, PROT_READ, MAP_SHARED, tf.fd, 1);
  ASSERT_EQ(MAP_FAILED, map);
}

#define STR_SSIZE(str) static_cast<ssize_t>(sizeof(str))

#define STRING_MSG  "012345678\nabcdefgh\n"
#define INITIAL_MSG "000000000\n00000000\n"

TEST(sys_mman, mmap_file_read) {
  TemporaryFile tf;

  ASSERT_EQ(STR_SSIZE(STRING_MSG), write(tf.fd, STRING_MSG, sizeof(STRING_MSG)));

  void* map = mmap(nullptr, sizeof(STRING_MSG), PROT_READ, MAP_SHARED, tf.fd, 0);
  ASSERT_NE(MAP_FAILED, map);

  char* data = reinterpret_cast<char*>(map);
  ASSERT_STREQ(STRING_MSG, data);

  ASSERT_EQ(0, munmap(map, sizeof(STRING_MSG)));
}

TEST(sys_mman, mmap_file_write) {
  TemporaryFile tf;

  ASSERT_EQ(STR_SSIZE(INITIAL_MSG), write(tf.fd, INITIAL_MSG, sizeof(INITIAL_MSG)));
  lseek(tf.fd, 0, SEEK_SET);

  void* map = mmap(nullptr, sizeof(STRING_MSG), PROT_WRITE, MAP_SHARED, tf.fd, 0);
  ASSERT_NE(MAP_FAILED, map);
  close(tf.fd);

  memcpy(map, STRING_MSG, sizeof(STRING_MSG));

  ASSERT_EQ(0, munmap(map, sizeof(STRING_MSG)));

  tf.fd = open(tf.path, O_RDWR);
  char buf[sizeof(STRING_MSG)];
  memset(buf, 0sizeof(STRING_MSG));
  ASSERT_EQ(STR_SSIZE(STRING_MSG), read(tf.fd, buf, sizeof(STRING_MSG)));

  ASSERT_STREQ(STRING_MSG, buf);
}

#define PAGE0_MSG "00PAGE00"
#define PAGE1_MSG "111PAGE111"
#define PAGE2_MSG "2222PAGE2222"
#define END_MSG "E"

TEST(sys_mman, mmap_file_read_at_offset) {
  TemporaryFile tf;
  size_t pagesize = sysconf(_SC_PAGESIZE);

  // Create the file with three pages worth of data.
  ASSERT_EQ(STR_SSIZE(PAGE0_MSG), write(tf.fd, PAGE0_MSG, sizeof(PAGE0_MSG)));
  ASSERT_NE(-1, lseek(tf.fd, pagesize, SEEK_SET));
  ASSERT_EQ(STR_SSIZE(PAGE1_MSG), write(tf.fd, PAGE1_MSG, sizeof(PAGE1_MSG)));
  ASSERT_NE(-1, lseek(tf.fd, 2 * pagesize, SEEK_SET));
  ASSERT_EQ(STR_SSIZE(PAGE2_MSG), write(tf.fd, PAGE2_MSG, sizeof(PAGE2_MSG)));
  ASSERT_NE(-1, lseek(tf.fd, 3 * pagesize - sizeof(END_MSG), SEEK_SET));
  ASSERT_EQ(STR_SSIZE(END_MSG), write(tf.fd, END_MSG, sizeof(END_MSG)));

  ASSERT_NE(-1, lseek(tf.fd, 0, SEEK_SET));

  void* map = mmap(nullptr, pagesize, PROT_READ, MAP_SHARED, tf.fd, pagesize);
  ASSERT_NE(MAP_FAILED, map);

  char* data = reinterpret_cast<char*>(map);
  ASSERT_STREQ(PAGE1_MSG, data);

  ASSERT_EQ(0, munmap(map, pagesize));

  map = mmap(nullptr, pagesize, PROT_READ, MAP_SHARED, tf.fd, 2 * pagesize);
  ASSERT_NE(MAP_FAILED, map);

  data = reinterpret_cast<char*>(map);
  ASSERT_STREQ(PAGE2_MSG, data);
  ASSERT_STREQ(END_MSG, data+pagesize-sizeof(END_MSG));

  ASSERT_EQ(0, munmap(map, pagesize));
}

#define NEWPAGE1_MSG "1NEW1PAGE1"
#define NEWPAGE2_MSG "22NEW22PAGE22"

TEST(sys_mman, mmap_file_write_at_offset) {
  TemporaryFile tf;
  size_t pagesize = sysconf(_SC_PAGESIZE);

  // Create the file with three pages worth of data.
  ASSERT_EQ(STR_SSIZE(PAGE0_MSG), write(tf.fd, PAGE0_MSG, sizeof(PAGE0_MSG)));
  ASSERT_NE(-1, lseek(tf.fd, pagesize, SEEK_SET));
  ASSERT_EQ(STR_SSIZE(PAGE1_MSG), write(tf.fd, PAGE1_MSG, sizeof(PAGE1_MSG)));
  ASSERT_NE(-1, lseek(tf.fd, 2 * pagesize, SEEK_SET));
  ASSERT_EQ(STR_SSIZE(PAGE2_MSG), write(tf.fd, PAGE2_MSG, sizeof(PAGE2_MSG)));
  ASSERT_NE(-1, lseek(tf.fd, 3 * pagesize - sizeof(END_MSG), SEEK_SET));
  ASSERT_EQ(STR_SSIZE(END_MSG), write(tf.fd, END_MSG, sizeof(END_MSG)));

  ASSERT_NE(-1, lseek(tf.fd, 0, SEEK_SET));

  void* map = mmap(nullptr, pagesize, PROT_WRITE, MAP_SHARED, tf.fd, pagesize);
  ASSERT_NE(MAP_FAILED, map);
  close(tf.fd);

  memcpy(map, NEWPAGE1_MSG, sizeof(NEWPAGE1_MSG));
  ASSERT_EQ(0, munmap(map, pagesize));

  tf.fd = open(tf.path, O_RDWR);
  map = mmap(nullptr, pagesize, PROT_WRITE, MAP_SHARED, tf.fd, 2 * pagesize);
  ASSERT_NE(MAP_FAILED, map);
  close(tf.fd);

  memcpy(map, NEWPAGE2_MSG, sizeof(NEWPAGE2_MSG));
  ASSERT_EQ(0, munmap(map, pagesize));

  tf.fd = open(tf.path, O_RDWR);
  char buf[pagesize];
  ASSERT_EQ(static_cast<ssize_t>(pagesize), read(tf.fd, buf, pagesize));
  ASSERT_STREQ(PAGE0_MSG, buf);
  ASSERT_NE(-1, lseek(tf.fd, pagesize, SEEK_SET));
  ASSERT_EQ(static_cast<ssize_t>(pagesize), read(tf.fd, buf, pagesize));
  ASSERT_STREQ(NEWPAGE1_MSG, buf);
  ASSERT_NE(-1, lseek(tf.fd, 2 * pagesize, SEEK_SET));
  ASSERT_EQ(static_cast<ssize_t>(pagesize), read(tf.fd, buf, pagesize));
  ASSERT_STREQ(NEWPAGE2_MSG, buf);
  ASSERT_STREQ(END_MSG, buf+pagesize-sizeof(END_MSG));
}

TEST(sys_mman, posix_madvise) {
  TemporaryFile tempfile;
  size_t pagesize = sysconf(_SC_PAGESIZE);
  char buf[pagesize];

  // Prepare environment.
  ASSERT_EQ(static_cast<ssize_t>(pagesize), write(tempfile.fd, buf, pagesize));
  void* map = mmap(nullptr, pagesize, PROT_READ | PROT_WRITE, MAP_SHARED, tempfile.fd, 0);
  ASSERT_NE(MAP_FAILED, map);

  // Verify different options of posix_madvise.
  ASSERT_EQ(0, posix_madvise(map, pagesize, POSIX_MADV_NORMAL));
  ASSERT_EQ(0, posix_madvise(map, pagesize, POSIX_MADV_SEQUENTIAL));
  ASSERT_EQ(0, posix_madvise(map, pagesize, POSIX_MADV_RANDOM));
  ASSERT_EQ(0, posix_madvise(map, pagesize, POSIX_MADV_WILLNEED));

  ASSERT_EQ(0, munmap(map, pagesize));
}

// Verify that memory can still access after posix_madvise(POSIX_MADV_DONTNEED).
// We should test on MAP_ANONYMOUS memory to verify whether the memory is discarded,
// because the content of non MAP_ANONYMOUS memory can be reread from file.
TEST(sys_mman, posix_madvise_POSIX_MADV_DONTNEED) {
  size_t pagesize = sysconf(_SC_PAGESIZE);

  void* map = mmap(nullptr, pagesize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -10);
  ASSERT_NE(MAP_FAILED, map);

  int* int_ptr = reinterpret_cast<int*>(map);
  for (int i = 0; i < static_cast<int>(pagesize / sizeof(int)); ++i) {
    *int_ptr++ = i;
  }

  ASSERT_EQ(0, posix_madvise(map, pagesize, POSIX_MADV_DONTNEED));

  int_ptr = reinterpret_cast<int*>(map);
  for (int i = 0; i < static_cast<int>(pagesize / sizeof(int)); ++i) {
    ASSERT_EQ(i, *int_ptr++);
  }

  ASSERT_EQ(0, munmap(map, pagesize));
}

TEST(sys_mman, mremap) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wnonnull"
  ASSERT_EQ(MAP_FAILED, mremap(nullptr, 000));
#pragma clang diagnostic pop
}

constexpr size_t kHuge = size_t(PTRDIFF_MAX) + 1;

TEST(sys_mman, mmap_PTRDIFF_MAX) {
  ASSERT_EQ(MAP_FAILED, mmap(nullptr, kHuge, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -10));
}

TEST(sys_mman, mremap_PTRDIFF_MAX) {
  void* map = mmap(nullptr, kPageSize, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -10);
  ASSERT_NE(MAP_FAILED, map);

  ASSERT_EQ(MAP_FAILED, mremap(map, kPageSize, kHuge, MREMAP_MAYMOVE));

  ASSERT_EQ(0, munmap(map, kPageSize));
}

TEST(sys_mman, mremap_MREMAP_FIXED) {
  // We're not trying to test the kernel here; that's external/ltp's job.
  // We just want to check that optional argument (mremap() is varargs)
  // gets passed through in an MREMAP_FIXED call.
  void* vma1 = mmap(NULL, getpagesize(), PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, -10);
  ASSERT_NE(MAP_FAILED, vma1);

  void* vma2 = mmap(NULL, getpagesize(), PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, -10);
  ASSERT_NE(MAP_FAILED, vma2);

  void* vma3 = mremap(vma1, getpagesize(), getpagesize(), MREMAP_FIXED | MREMAP_MAYMOVE, vma2);
  ASSERT_EQ(vma2, vma3);
}

TEST(sys_mman, mmap_bug_27265969) {
  char* base = reinterpret_cast<char*>(
      mmap(nullptr, kPageSize * 2, PROT_EXEC | PROT_READ, MAP_ANONYMOUS | MAP_PRIVATE, -10));
  // Some kernels had bugs that would cause segfaults here...
  __builtin___clear_cache(base, base + (kPageSize * 2));
}

TEST(sys_mman, mlock) {
  void* map = mmap(nullptr, kPageSize, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -10);
  ASSERT_NE(MAP_FAILED, map);

  // Not really anything we can assert about this.
  mlock(map, kPageSize);

  ASSERT_EQ(0, munmap(map, kPageSize));
}

TEST(sys_mman, mlock2) {
#if defined(__GLIBC__)
  GTEST_SKIP() << "needs glibc 2.27";
#else
  void* map = mmap(nullptr, kPageSize, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -10);
  ASSERT_NE(MAP_FAILED, map);

  // Not really anything we can assert about this.
  mlock2(map, kPageSize, MLOCK_ONFAULT);

  ASSERT_EQ(0, munmap(map, kPageSize));
#endif
}

TEST(sys_mman, memfd_create) {
#if defined(__GLIBC__)
  GTEST_SKIP() << "needs glibc 2.27";
#else
  // Is the MFD_CLOEXEC flag obeyed?
  errno = 0;
  int fd = memfd_create("doesn't matter"0);
  ASSERT_NE(-1, fd) << strerror(errno);

  int f = fcntl(fd, F_GETFD);
  ASSERT_NE(-1, f);
  ASSERT_FALSE(f & FD_CLOEXEC);
  close(fd);

  errno = 0;
  fd = memfd_create("doesn't matter", MFD_CLOEXEC);
  f = fcntl(fd, F_GETFD);
  ASSERT_NE(-1, f);
  ASSERT_TRUE(f & FD_CLOEXEC);

  // Can we read and write?
  std::string expected("hello, world!");
  ASSERT_TRUE(android::base::WriteStringToFd(expected, fd));
  ASSERT_EQ(0, lseek(fd, 0, SEEK_SET));
  std::string actual;
  ASSERT_TRUE(android::base::ReadFdToString(fd, &actual));
  ASSERT_EQ(expected, actual);

  close(fd);
#endif
}

TEST(sys_mseal, mseal) {
#if defined(__GLIBC__)
  GTEST_SKIP() << "needs glibc 2.40";
#else
  void* map = mmap(nullptr, kPageSize, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -10);
  ASSERT_NE(MAP_FAILED, map);

#if defined(__LP64__)
  int rc = mseal(map, kPageSize, 0);
  if (rc == -1) {
    ASSERT_ERRNO(ENOSYS);
    GTEST_SKIP() << "needs kernel with mseal(2)";
  }
  ASSERT_ERRNO_FAILURE(EPERM, -1, mprotect(map, kPageSize, PROT_READ));
#else
  // No mseal() for ILP32.
  ASSERT_ERRNO_FAILURE(ENOSYS, -1, mseal(map, kPageSize, 0));
  GTEST_SKIP() << "mseal(2) is LP64-only";
#endif

  // We can't munmap() our test mapping if mseal() actually succeeded :-)
#endif
}

Messung V0.5 in Prozent
C=90 H=86 G=87

¤ Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.0.13Bemerkung:  (vorverarbeitet am  2026-06-28) ¤

*Bot Zugriff






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.