2013-04-29 23:07:06 +02:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2013 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 <gtest/gtest.h>
|
2013-12-21 03:43:21 +01:00
|
|
|
#include <signal.h>
|
2013-04-29 23:07:06 +02:00
|
|
|
#include <string.h>
|
2013-06-27 17:58:14 +02:00
|
|
|
#include <stdarg.h>
|
2013-06-29 17:15:25 +02:00
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/stat.h>
|
2013-09-25 01:32:07 +02:00
|
|
|
#include <sys/socket.h>
|
2013-10-02 23:14:40 +02:00
|
|
|
#include <malloc.h>
|
2013-10-10 05:16:34 +02:00
|
|
|
#include <fcntl.h>
|
2013-04-29 23:07:06 +02:00
|
|
|
|
2013-06-28 19:34:09 +02:00
|
|
|
// We have to say "DeathTest" here so gtest knows to run this test (which exits)
|
|
|
|
// in its own process. Unfortunately, the C preprocessor doesn't give us an
|
|
|
|
// easy way to concatenate strings, so we need to use the complicated method
|
|
|
|
// below. *sigh*
|
|
|
|
#define DEATHTEST_PASTER(name) name##_DeathTest
|
|
|
|
#define DEATHTEST_EVALUATOR(name) DEATHTEST_PASTER(name)
|
|
|
|
#define DEATHTEST DEATHTEST_EVALUATOR(TEST_NAME)
|
|
|
|
|
|
|
|
#if defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE == 2
|
2013-04-29 23:07:06 +02:00
|
|
|
struct foo {
|
2013-06-03 19:58:06 +02:00
|
|
|
char empty[0];
|
|
|
|
char one[1];
|
2013-04-29 23:07:06 +02:00
|
|
|
char a[10];
|
|
|
|
char b[10];
|
|
|
|
};
|
|
|
|
|
2014-04-04 23:38:18 +02:00
|
|
|
#ifndef __clang__
|
|
|
|
// This test is disabled in clang because clang doesn't properly detect
|
|
|
|
// this buffer overflow. TODO: Fix clang.
|
|
|
|
TEST(DEATHTEST, stpncpy_fortified2) {
|
|
|
|
::testing::FLAGS_gtest_death_test_style = "threadsafe";
|
|
|
|
foo myfoo;
|
|
|
|
int copy_amt = atoi("11");
|
|
|
|
ASSERT_EXIT(stpncpy(myfoo.a, "01234567890", copy_amt),
|
|
|
|
testing::KilledBySignal(SIGABRT), "");
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef __clang__
|
|
|
|
// This test is disabled in clang because clang doesn't properly detect
|
|
|
|
// this buffer overflow. TODO: Fix clang.
|
|
|
|
TEST(DEATHTEST, stpncpy2_fortified2) {
|
|
|
|
::testing::FLAGS_gtest_death_test_style = "threadsafe";
|
|
|
|
foo myfoo;
|
|
|
|
memset(&myfoo, 0, sizeof(myfoo));
|
|
|
|
myfoo.one[0] = 'A'; // not null terminated string
|
|
|
|
ASSERT_EXIT(stpncpy(myfoo.b, myfoo.one, sizeof(myfoo.b)),
|
|
|
|
testing::KilledBySignal(SIGABRT), "");
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2013-06-28 19:34:09 +02:00
|
|
|
#ifndef __clang__
|
|
|
|
// This test is disabled in clang because clang doesn't properly detect
|
|
|
|
// this buffer overflow. TODO: Fix clang.
|
|
|
|
TEST(DEATHTEST, strncpy_fortified2) {
|
2013-04-29 23:07:06 +02:00
|
|
|
::testing::FLAGS_gtest_death_test_style = "threadsafe";
|
|
|
|
foo myfoo;
|
|
|
|
int copy_amt = atoi("11");
|
|
|
|
ASSERT_EXIT(strncpy(myfoo.a, "01234567890", copy_amt),
|
2013-06-12 00:45:23 +02:00
|
|
|
testing::KilledBySignal(SIGABRT), "");
|
2013-04-29 23:07:06 +02:00
|
|
|
}
|
2013-06-28 19:34:09 +02:00
|
|
|
#endif
|
2013-04-29 23:07:06 +02:00
|
|
|
|
2013-08-28 19:47:43 +02:00
|
|
|
#ifndef __clang__
|
|
|
|
// This test is disabled in clang because clang doesn't properly detect
|
|
|
|
// this buffer overflow. TODO: Fix clang.
|
|
|
|
TEST(DEATHTEST, strncpy2_fortified2) {
|
|
|
|
::testing::FLAGS_gtest_death_test_style = "threadsafe";
|
|
|
|
foo myfoo;
|
|
|
|
memset(&myfoo, 0, sizeof(myfoo));
|
|
|
|
myfoo.one[0] = 'A'; // not null terminated string
|
|
|
|
ASSERT_EXIT(strncpy(myfoo.b, myfoo.one, sizeof(myfoo.b)),
|
|
|
|
testing::KilledBySignal(SIGABRT), "");
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2013-06-28 19:34:09 +02:00
|
|
|
#ifndef __clang__
|
|
|
|
// This test is disabled in clang because clang doesn't properly detect
|
|
|
|
// this buffer overflow. TODO: Fix clang.
|
|
|
|
TEST(DEATHTEST, sprintf_fortified2) {
|
2013-04-30 01:29:37 +02:00
|
|
|
::testing::FLAGS_gtest_death_test_style = "threadsafe";
|
|
|
|
foo myfoo;
|
|
|
|
char source_buf[15];
|
|
|
|
memcpy(source_buf, "12345678901234", 15);
|
|
|
|
ASSERT_EXIT(sprintf(myfoo.a, "%s", source_buf),
|
2013-06-12 00:45:23 +02:00
|
|
|
testing::KilledBySignal(SIGABRT), "");
|
2013-04-30 01:29:37 +02:00
|
|
|
}
|
2013-06-28 19:34:09 +02:00
|
|
|
#endif
|
2013-04-30 01:29:37 +02:00
|
|
|
|
2013-06-28 19:34:09 +02:00
|
|
|
#ifndef __clang__
|
|
|
|
// This test is disabled in clang because clang doesn't properly detect
|
|
|
|
// this buffer overflow. TODO: Fix clang.
|
|
|
|
TEST(DEATHTEST, sprintf2_fortified2) {
|
2013-06-24 20:44:00 +02:00
|
|
|
::testing::FLAGS_gtest_death_test_style = "threadsafe";
|
|
|
|
foo myfoo;
|
|
|
|
ASSERT_EXIT(sprintf(myfoo.a, "0123456789"),
|
|
|
|
testing::KilledBySignal(SIGABRT), "");
|
|
|
|
}
|
2013-06-28 19:34:09 +02:00
|
|
|
#endif
|
2013-06-24 20:44:00 +02:00
|
|
|
|
2013-06-28 19:34:09 +02:00
|
|
|
#ifndef __clang__
|
|
|
|
// These tests are disabled in clang because clang doesn't properly detect
|
|
|
|
// this buffer overflow. TODO: Fix clang.
|
2013-06-27 17:58:14 +02:00
|
|
|
static int vsprintf_helper2(const char *fmt, ...) {
|
|
|
|
foo myfoo;
|
|
|
|
va_list va;
|
|
|
|
int result;
|
|
|
|
|
|
|
|
va_start(va, fmt);
|
|
|
|
result = vsprintf(myfoo.a, fmt, va); // should crash here
|
|
|
|
va_end(va);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2013-06-28 19:34:09 +02:00
|
|
|
TEST(DEATHTEST, vsprintf_fortified2) {
|
2013-06-27 17:58:14 +02:00
|
|
|
::testing::FLAGS_gtest_death_test_style = "threadsafe";
|
|
|
|
ASSERT_EXIT(vsprintf_helper2("%s", "0123456789"), testing::KilledBySignal(SIGABRT), "");
|
|
|
|
}
|
|
|
|
|
2013-06-28 19:34:09 +02:00
|
|
|
TEST(DEATHTEST, vsprintf2_fortified2) {
|
2013-06-27 17:58:14 +02:00
|
|
|
::testing::FLAGS_gtest_death_test_style = "threadsafe";
|
|
|
|
ASSERT_EXIT(vsprintf_helper2("0123456789"), testing::KilledBySignal(SIGABRT), "");
|
|
|
|
}
|
2013-06-28 19:34:09 +02:00
|
|
|
#endif
|
2013-06-27 17:58:14 +02:00
|
|
|
|
2013-06-28 19:34:09 +02:00
|
|
|
#ifndef __clang__
|
|
|
|
// These tests are disabled in clang because clang doesn't properly detect
|
|
|
|
// this buffer overflow. TODO: Fix clang.
|
2013-06-27 17:58:14 +02:00
|
|
|
static int vsnprintf_helper2(const char *fmt, ...) {
|
|
|
|
foo myfoo;
|
|
|
|
va_list va;
|
|
|
|
int result;
|
|
|
|
size_t size = atoi("11");
|
|
|
|
|
|
|
|
va_start(va, fmt);
|
|
|
|
result = vsnprintf(myfoo.a, size, fmt, va); // should crash here
|
|
|
|
va_end(va);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2013-06-28 19:34:09 +02:00
|
|
|
TEST(DEATHTEST, vsnprintf_fortified2) {
|
2013-06-27 17:58:14 +02:00
|
|
|
::testing::FLAGS_gtest_death_test_style = "threadsafe";
|
|
|
|
ASSERT_EXIT(vsnprintf_helper2("%s", "0123456789"), testing::KilledBySignal(SIGABRT), "");
|
|
|
|
}
|
|
|
|
|
2013-06-28 19:34:09 +02:00
|
|
|
TEST(DEATHTEST, vsnprintf2_fortified2) {
|
2013-06-27 17:58:14 +02:00
|
|
|
::testing::FLAGS_gtest_death_test_style = "threadsafe";
|
|
|
|
ASSERT_EXIT(vsnprintf_helper2("0123456789"), testing::KilledBySignal(SIGABRT), "");
|
|
|
|
}
|
2013-06-28 19:34:09 +02:00
|
|
|
#endif
|
2013-06-27 17:58:14 +02:00
|
|
|
|
2014-04-04 23:38:18 +02:00
|
|
|
#ifndef __clang__
|
|
|
|
// zero sized target with "\0" source (should fail)
|
|
|
|
// This test is disabled in clang because clang doesn't properly detect
|
|
|
|
// this buffer overflow. TODO: Fix clang.
|
|
|
|
TEST(DEATHTEST, stpcpy_fortified2) {
|
|
|
|
#if defined(__BIONIC__)
|
|
|
|
::testing::FLAGS_gtest_death_test_style = "threadsafe";
|
|
|
|
foo myfoo;
|
|
|
|
char* src = strdup("");
|
|
|
|
ASSERT_EXIT(stpcpy(myfoo.empty, src),
|
|
|
|
testing::KilledBySignal(SIGABRT), "");
|
|
|
|
free(src);
|
|
|
|
#else // __BIONIC__
|
|
|
|
GTEST_LOG_(INFO) << "This test does nothing.\n";
|
|
|
|
#endif // __BIONIC__
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2013-06-28 19:34:09 +02:00
|
|
|
#ifndef __clang__
|
2013-06-03 19:58:06 +02:00
|
|
|
// zero sized target with "\0" source (should fail)
|
2013-06-28 19:34:09 +02:00
|
|
|
// This test is disabled in clang because clang doesn't properly detect
|
|
|
|
// this buffer overflow. TODO: Fix clang.
|
|
|
|
TEST(DEATHTEST, strcpy_fortified2) {
|
2013-12-21 03:43:21 +01:00
|
|
|
#if defined(__BIONIC__)
|
2013-06-03 19:58:06 +02:00
|
|
|
::testing::FLAGS_gtest_death_test_style = "threadsafe";
|
|
|
|
foo myfoo;
|
|
|
|
char* src = strdup("");
|
|
|
|
ASSERT_EXIT(strcpy(myfoo.empty, src),
|
2013-06-12 00:45:23 +02:00
|
|
|
testing::KilledBySignal(SIGABRT), "");
|
2013-06-03 19:58:06 +02:00
|
|
|
free(src);
|
2013-12-21 03:43:21 +01:00
|
|
|
#else // __BIONIC__
|
|
|
|
GTEST_LOG_(INFO) << "This test does nothing.\n";
|
|
|
|
#endif // __BIONIC__
|
2013-06-03 19:58:06 +02:00
|
|
|
}
|
2013-06-28 19:34:09 +02:00
|
|
|
#endif
|
2013-06-03 19:58:06 +02:00
|
|
|
|
2013-06-28 19:34:09 +02:00
|
|
|
#ifndef __clang__
|
2013-06-03 19:58:06 +02:00
|
|
|
// zero sized target with longer source (should fail)
|
2013-06-28 19:34:09 +02:00
|
|
|
// This test is disabled in clang because clang doesn't properly detect
|
|
|
|
// this buffer overflow. TODO: Fix clang.
|
|
|
|
TEST(DEATHTEST, strcpy2_fortified2) {
|
2013-12-21 03:43:21 +01:00
|
|
|
#if defined(__BIONIC__)
|
2013-06-03 19:58:06 +02:00
|
|
|
::testing::FLAGS_gtest_death_test_style = "threadsafe";
|
|
|
|
foo myfoo;
|
|
|
|
char* src = strdup("1");
|
|
|
|
ASSERT_EXIT(strcpy(myfoo.empty, src),
|
2013-06-12 00:45:23 +02:00
|
|
|
testing::KilledBySignal(SIGABRT), "");
|
2013-06-03 19:58:06 +02:00
|
|
|
free(src);
|
2013-12-21 03:43:21 +01:00
|
|
|
#else // __BIONIC__
|
|
|
|
GTEST_LOG_(INFO) << "This test does nothing.\n";
|
|
|
|
#endif // __BIONIC__
|
2013-06-03 19:58:06 +02:00
|
|
|
}
|
2013-06-28 19:34:09 +02:00
|
|
|
#endif
|
2013-06-03 19:58:06 +02:00
|
|
|
|
2013-06-28 19:34:09 +02:00
|
|
|
#ifndef __clang__
|
2013-06-03 19:58:06 +02:00
|
|
|
// one byte target with longer source (should fail)
|
2013-06-28 19:34:09 +02:00
|
|
|
// This test is disabled in clang because clang doesn't properly detect
|
|
|
|
// this buffer overflow. TODO: Fix clang.
|
|
|
|
TEST(DEATHTEST, strcpy3_fortified2) {
|
2013-12-21 03:43:21 +01:00
|
|
|
#if defined(__BIONIC__)
|
2013-06-03 19:58:06 +02:00
|
|
|
::testing::FLAGS_gtest_death_test_style = "threadsafe";
|
|
|
|
foo myfoo;
|
|
|
|
char* src = strdup("12");
|
|
|
|
ASSERT_EXIT(strcpy(myfoo.one, src),
|
2013-06-12 00:45:23 +02:00
|
|
|
testing::KilledBySignal(SIGABRT), "");
|
2013-06-03 19:58:06 +02:00
|
|
|
free(src);
|
2013-12-21 03:43:21 +01:00
|
|
|
#else // __BIONIC__
|
|
|
|
GTEST_LOG_(INFO) << "This test does nothing.\n";
|
|
|
|
#endif // __BIONIC__
|
2013-06-03 19:58:06 +02:00
|
|
|
}
|
2013-06-28 19:34:09 +02:00
|
|
|
#endif
|
2013-06-03 19:58:06 +02:00
|
|
|
|
2013-06-28 19:34:09 +02:00
|
|
|
#ifndef __clang__
|
|
|
|
// This test is disabled in clang because clang doesn't properly detect
|
|
|
|
// this buffer overflow. TODO: Fix clang.
|
|
|
|
TEST(DEATHTEST, strchr_fortified2) {
|
2013-12-21 03:43:21 +01:00
|
|
|
#if defined(__BIONIC__)
|
2013-04-20 01:54:22 +02:00
|
|
|
::testing::FLAGS_gtest_death_test_style = "threadsafe";
|
|
|
|
foo myfoo;
|
|
|
|
memcpy(myfoo.a, "0123456789", sizeof(myfoo.a));
|
|
|
|
myfoo.b[0] = '\0';
|
|
|
|
ASSERT_EXIT(printf("%s", strchr(myfoo.a, 'a')),
|
2013-06-12 00:45:23 +02:00
|
|
|
testing::KilledBySignal(SIGABRT), "");
|
2013-12-21 03:43:21 +01:00
|
|
|
#else // __BIONIC__
|
|
|
|
GTEST_LOG_(INFO) << "This test does nothing.\n";
|
|
|
|
#endif // __BIONIC__
|
2013-04-20 01:54:22 +02:00
|
|
|
}
|
2013-06-28 19:34:09 +02:00
|
|
|
#endif
|
2013-04-20 01:54:22 +02:00
|
|
|
|
2013-06-28 19:34:09 +02:00
|
|
|
#ifndef __clang__
|
|
|
|
// This test is disabled in clang because clang doesn't properly detect
|
|
|
|
// this buffer overflow. TODO: Fix clang.
|
|
|
|
TEST(DEATHTEST, strrchr_fortified2) {
|
2013-12-21 03:43:21 +01:00
|
|
|
#if defined(__BIONIC__)
|
2013-05-01 23:55:33 +02:00
|
|
|
::testing::FLAGS_gtest_death_test_style = "threadsafe";
|
|
|
|
foo myfoo;
|
|
|
|
memcpy(myfoo.a, "0123456789", 10);
|
|
|
|
memcpy(myfoo.b, "01234", 6);
|
|
|
|
ASSERT_EXIT(printf("%s", strrchr(myfoo.a, 'a')),
|
2013-06-12 00:45:23 +02:00
|
|
|
testing::KilledBySignal(SIGABRT), "");
|
2013-12-21 03:43:21 +01:00
|
|
|
#else // __BIONIC__
|
|
|
|
GTEST_LOG_(INFO) << "This test does nothing.\n";
|
|
|
|
#endif // __BIONIC__
|
2013-05-01 23:55:33 +02:00
|
|
|
}
|
2013-06-28 19:34:09 +02:00
|
|
|
#endif
|
2013-06-20 21:17:44 +02:00
|
|
|
|
2013-06-28 19:34:09 +02:00
|
|
|
#ifndef __clang__
|
|
|
|
// This test is disabled in clang because clang doesn't properly detect
|
|
|
|
// this buffer overflow. TODO: Fix clang.
|
|
|
|
TEST(DEATHTEST, strlcpy_fortified2) {
|
2013-12-21 03:43:21 +01:00
|
|
|
#if defined(__BIONIC__)
|
2013-06-20 21:17:44 +02:00
|
|
|
::testing::FLAGS_gtest_death_test_style = "threadsafe";
|
|
|
|
foo myfoo;
|
|
|
|
strcpy(myfoo.a, "01");
|
|
|
|
size_t n = strlen(myfoo.a);
|
|
|
|
ASSERT_EXIT(strlcpy(myfoo.one, myfoo.a, n),
|
|
|
|
testing::KilledBySignal(SIGABRT), "");
|
2013-12-21 03:43:21 +01:00
|
|
|
#else // __BIONIC__
|
|
|
|
GTEST_LOG_(INFO) << "This test does nothing.\n";
|
|
|
|
#endif // __BIONIC__
|
2013-06-20 21:17:44 +02:00
|
|
|
}
|
2013-05-01 23:55:33 +02:00
|
|
|
#endif
|
|
|
|
|
2013-06-29 17:15:25 +02:00
|
|
|
#ifndef __clang__
|
|
|
|
// This test is disabled in clang because clang doesn't properly detect
|
|
|
|
// this buffer overflow. TODO: Fix clang.
|
|
|
|
TEST(DEATHTEST, strlcat_fortified2) {
|
2013-12-21 03:43:21 +01:00
|
|
|
#if defined(__BIONIC__)
|
2013-06-29 17:15:25 +02:00
|
|
|
::testing::FLAGS_gtest_death_test_style = "threadsafe";
|
|
|
|
foo myfoo;
|
|
|
|
strcpy(myfoo.a, "01");
|
|
|
|
myfoo.one[0] = '\0';
|
|
|
|
size_t n = strlen(myfoo.a);
|
|
|
|
ASSERT_EXIT(strlcat(myfoo.one, myfoo.a, n),
|
|
|
|
testing::KilledBySignal(SIGABRT), "");
|
2013-12-21 03:43:21 +01:00
|
|
|
#else // __BIONIC__
|
|
|
|
GTEST_LOG_(INFO) << "This test does nothing.\n";
|
|
|
|
#endif // __BIONIC__
|
2013-06-29 17:15:25 +02:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2013-06-28 19:34:09 +02:00
|
|
|
#ifndef __clang__
|
|
|
|
// This test is disabled in clang because clang doesn't properly detect
|
|
|
|
// this buffer overflow. TODO: Fix clang.
|
|
|
|
TEST(DEATHTEST, strncat_fortified2) {
|
2013-05-30 22:21:14 +02:00
|
|
|
::testing::FLAGS_gtest_death_test_style = "threadsafe";
|
|
|
|
foo myfoo;
|
|
|
|
size_t n = atoi("10"); // avoid compiler optimizations
|
|
|
|
strncpy(myfoo.a, "012345678", n);
|
2013-06-12 00:45:23 +02:00
|
|
|
ASSERT_EXIT(strncat(myfoo.a, "9", n), testing::KilledBySignal(SIGABRT), "");
|
2013-05-30 22:21:14 +02:00
|
|
|
}
|
2013-06-28 19:34:09 +02:00
|
|
|
#endif
|
2013-05-30 22:21:14 +02:00
|
|
|
|
2013-06-28 19:34:09 +02:00
|
|
|
#ifndef __clang__
|
|
|
|
// This test is disabled in clang because clang doesn't properly detect
|
|
|
|
// this buffer overflow. TODO: Fix clang.
|
|
|
|
TEST(DEATHTEST, strncat2_fortified2) {
|
2013-05-30 22:21:14 +02:00
|
|
|
::testing::FLAGS_gtest_death_test_style = "threadsafe";
|
|
|
|
foo myfoo;
|
|
|
|
myfoo.a[0] = '\0';
|
|
|
|
size_t n = atoi("10"); // avoid compiler optimizations
|
2013-06-12 00:45:23 +02:00
|
|
|
ASSERT_EXIT(strncat(myfoo.a, "0123456789", n), testing::KilledBySignal(SIGABRT), "");
|
2013-05-30 22:21:14 +02:00
|
|
|
}
|
2013-06-28 19:34:09 +02:00
|
|
|
#endif
|
2013-05-30 22:21:14 +02:00
|
|
|
|
2013-06-28 19:34:09 +02:00
|
|
|
TEST(DEATHTEST, strncat3_fortified2) {
|
2013-05-31 01:48:53 +02:00
|
|
|
::testing::FLAGS_gtest_death_test_style = "threadsafe";
|
|
|
|
foo myfoo;
|
|
|
|
memcpy(myfoo.a, "0123456789", sizeof(myfoo.a)); // unterminated string
|
|
|
|
myfoo.b[0] = '\0';
|
|
|
|
size_t n = atoi("10"); // avoid compiler optimizations
|
2013-06-12 00:45:23 +02:00
|
|
|
ASSERT_EXIT(strncat(myfoo.b, myfoo.a, n), testing::KilledBySignal(SIGABRT), "");
|
2013-05-31 01:48:53 +02:00
|
|
|
}
|
|
|
|
|
2013-06-28 19:34:09 +02:00
|
|
|
#ifndef __clang__
|
|
|
|
// This test is disabled in clang because clang doesn't properly detect
|
|
|
|
// this buffer overflow. TODO: Fix clang.
|
|
|
|
TEST(DEATHTEST, strcat_fortified2) {
|
2013-05-31 01:48:53 +02:00
|
|
|
::testing::FLAGS_gtest_death_test_style = "threadsafe";
|
|
|
|
char src[11];
|
|
|
|
strcpy(src, "0123456789");
|
|
|
|
foo myfoo;
|
|
|
|
myfoo.a[0] = '\0';
|
2013-06-12 00:45:23 +02:00
|
|
|
ASSERT_EXIT(strcat(myfoo.a, src), testing::KilledBySignal(SIGABRT), "");
|
2013-05-31 01:48:53 +02:00
|
|
|
}
|
2013-06-28 19:34:09 +02:00
|
|
|
#endif
|
2013-05-31 01:48:53 +02:00
|
|
|
|
2013-06-28 19:34:09 +02:00
|
|
|
TEST(DEATHTEST, strcat2_fortified2) {
|
2013-05-31 01:48:53 +02:00
|
|
|
::testing::FLAGS_gtest_death_test_style = "threadsafe";
|
|
|
|
foo myfoo;
|
|
|
|
memcpy(myfoo.a, "0123456789", sizeof(myfoo.a)); // unterminated string
|
|
|
|
myfoo.b[0] = '\0';
|
2013-06-12 00:45:23 +02:00
|
|
|
ASSERT_EXIT(strcat(myfoo.b, myfoo.a), testing::KilledBySignal(SIGABRT), "");
|
2013-05-31 01:48:53 +02:00
|
|
|
}
|
|
|
|
|
2013-06-28 19:34:09 +02:00
|
|
|
TEST(DEATHTEST, snprintf_fortified2) {
|
2013-06-25 19:02:35 +02:00
|
|
|
::testing::FLAGS_gtest_death_test_style = "threadsafe";
|
|
|
|
foo myfoo;
|
|
|
|
strcpy(myfoo.a, "012345678");
|
|
|
|
size_t n = strlen(myfoo.a) + 2;
|
|
|
|
ASSERT_EXIT(snprintf(myfoo.b, n, "a%s", myfoo.a), testing::KilledBySignal(SIGABRT), "");
|
|
|
|
}
|
|
|
|
|
2013-06-29 17:15:25 +02:00
|
|
|
TEST(DEATHTEST, bzero_fortified2) {
|
|
|
|
::testing::FLAGS_gtest_death_test_style = "threadsafe";
|
|
|
|
foo myfoo;
|
|
|
|
memcpy(myfoo.b, "0123456789", sizeof(myfoo.b));
|
|
|
|
size_t n = atoi("11");
|
|
|
|
ASSERT_EXIT(bzero(myfoo.b, n), testing::KilledBySignal(SIGABRT), "");
|
|
|
|
}
|
|
|
|
|
2013-06-28 19:34:09 +02:00
|
|
|
#endif /* defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE=2 */
|
2013-04-30 01:29:37 +02:00
|
|
|
|
2013-06-03 19:58:06 +02:00
|
|
|
// multibyte target where we over fill (should fail)
|
2013-06-28 19:34:09 +02:00
|
|
|
TEST(DEATHTEST, strcpy_fortified) {
|
2013-12-21 03:43:21 +01:00
|
|
|
#if defined(__BIONIC__)
|
2013-04-29 23:07:06 +02:00
|
|
|
::testing::FLAGS_gtest_death_test_style = "threadsafe";
|
|
|
|
char buf[10];
|
|
|
|
char *orig = strdup("0123456789");
|
2013-06-12 00:45:23 +02:00
|
|
|
ASSERT_EXIT(strcpy(buf, orig), testing::KilledBySignal(SIGABRT), "");
|
2013-04-29 23:07:06 +02:00
|
|
|
free(orig);
|
2013-12-21 03:43:21 +01:00
|
|
|
#else // __BIONIC__
|
|
|
|
GTEST_LOG_(INFO) << "This test does nothing.\n";
|
|
|
|
#endif // __BIONIC__
|
2013-04-29 23:07:06 +02:00
|
|
|
}
|
|
|
|
|
2013-06-03 19:58:06 +02:00
|
|
|
// zero sized target with "\0" source (should fail)
|
2013-06-28 19:34:09 +02:00
|
|
|
TEST(DEATHTEST, strcpy2_fortified) {
|
2013-12-21 03:43:21 +01:00
|
|
|
#if defined(__BIONIC__)
|
2013-06-03 19:58:06 +02:00
|
|
|
::testing::FLAGS_gtest_death_test_style = "threadsafe";
|
|
|
|
char buf[0];
|
|
|
|
char *orig = strdup("");
|
2013-06-12 00:45:23 +02:00
|
|
|
ASSERT_EXIT(strcpy(buf, orig), testing::KilledBySignal(SIGABRT), "");
|
2013-06-03 19:58:06 +02:00
|
|
|
free(orig);
|
2013-12-21 03:43:21 +01:00
|
|
|
#else // __BIONIC__
|
|
|
|
GTEST_LOG_(INFO) << "This test does nothing.\n";
|
|
|
|
#endif // __BIONIC__
|
2013-06-03 19:58:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// zero sized target with longer source (should fail)
|
2013-06-28 19:34:09 +02:00
|
|
|
TEST(DEATHTEST, strcpy3_fortified) {
|
2013-12-21 03:43:21 +01:00
|
|
|
#if defined(__BIONIC__)
|
2013-06-03 19:58:06 +02:00
|
|
|
::testing::FLAGS_gtest_death_test_style = "threadsafe";
|
|
|
|
char buf[0];
|
|
|
|
char *orig = strdup("1");
|
2013-06-12 00:45:23 +02:00
|
|
|
ASSERT_EXIT(strcpy(buf, orig), testing::KilledBySignal(SIGABRT), "");
|
2013-06-03 19:58:06 +02:00
|
|
|
free(orig);
|
2013-12-21 03:43:21 +01:00
|
|
|
#else // __BIONIC__
|
|
|
|
GTEST_LOG_(INFO) << "This test does nothing.\n";
|
|
|
|
#endif // __BIONIC__
|
2013-06-03 19:58:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// one byte target with longer source (should fail)
|
2013-06-28 19:34:09 +02:00
|
|
|
TEST(DEATHTEST, strcpy4_fortified) {
|
2013-12-21 03:43:21 +01:00
|
|
|
#if defined(__BIONIC__)
|
2013-06-03 19:58:06 +02:00
|
|
|
::testing::FLAGS_gtest_death_test_style = "threadsafe";
|
|
|
|
char buf[1];
|
|
|
|
char *orig = strdup("12");
|
2013-06-12 00:45:23 +02:00
|
|
|
ASSERT_EXIT(strcpy(buf, orig), testing::KilledBySignal(SIGABRT), "");
|
2013-06-03 19:58:06 +02:00
|
|
|
free(orig);
|
2013-12-21 03:43:21 +01:00
|
|
|
#else // __BIONIC__
|
|
|
|
GTEST_LOG_(INFO) << "This test does nothing.\n";
|
|
|
|
#endif // __BIONIC__
|
2013-06-03 19:58:06 +02:00
|
|
|
}
|
|
|
|
|
2013-06-28 19:34:09 +02:00
|
|
|
TEST(DEATHTEST, strlen_fortified) {
|
2013-12-21 03:43:21 +01:00
|
|
|
#if defined(__BIONIC__)
|
2013-04-29 23:07:06 +02:00
|
|
|
::testing::FLAGS_gtest_death_test_style = "threadsafe";
|
|
|
|
char buf[10];
|
|
|
|
memcpy(buf, "0123456789", sizeof(buf));
|
2013-10-03 01:59:05 +02:00
|
|
|
ASSERT_EXIT(printf("%zd", strlen(buf)), testing::KilledBySignal(SIGABRT), "");
|
2013-12-21 03:43:21 +01:00
|
|
|
#else // __BIONIC__
|
|
|
|
GTEST_LOG_(INFO) << "This test does nothing.\n";
|
|
|
|
#endif // __BIONIC__
|
2013-04-29 23:07:06 +02:00
|
|
|
}
|
|
|
|
|
2013-06-28 19:34:09 +02:00
|
|
|
TEST(DEATHTEST, strchr_fortified) {
|
2013-12-21 03:43:21 +01:00
|
|
|
#if defined(__BIONIC__)
|
2013-04-29 23:07:06 +02:00
|
|
|
::testing::FLAGS_gtest_death_test_style = "threadsafe";
|
|
|
|
char buf[10];
|
|
|
|
memcpy(buf, "0123456789", sizeof(buf));
|
2013-06-12 00:45:23 +02:00
|
|
|
ASSERT_EXIT(printf("%s", strchr(buf, 'a')), testing::KilledBySignal(SIGABRT), "");
|
2013-12-21 03:43:21 +01:00
|
|
|
#else // __BIONIC__
|
|
|
|
GTEST_LOG_(INFO) << "This test does nothing.\n";
|
|
|
|
#endif // __BIONIC__
|
2013-04-29 23:07:06 +02:00
|
|
|
}
|
|
|
|
|
2013-06-28 19:34:09 +02:00
|
|
|
TEST(DEATHTEST, strrchr_fortified) {
|
2013-12-21 03:43:21 +01:00
|
|
|
#if defined(__BIONIC__)
|
2013-04-29 23:07:06 +02:00
|
|
|
::testing::FLAGS_gtest_death_test_style = "threadsafe";
|
|
|
|
char buf[10];
|
|
|
|
memcpy(buf, "0123456789", sizeof(buf));
|
2013-06-12 00:45:23 +02:00
|
|
|
ASSERT_EXIT(printf("%s", strrchr(buf, 'a')), testing::KilledBySignal(SIGABRT), "");
|
2013-12-21 03:43:21 +01:00
|
|
|
#else // __BIONIC__
|
|
|
|
GTEST_LOG_(INFO) << "This test does nothing.\n";
|
|
|
|
#endif // __BIONIC__
|
2013-04-29 23:07:06 +02:00
|
|
|
}
|
2013-06-20 21:17:44 +02:00
|
|
|
|
2013-06-28 19:34:09 +02:00
|
|
|
TEST(DEATHTEST, strlcpy_fortified) {
|
2013-12-21 03:43:21 +01:00
|
|
|
#if defined(__BIONIC__)
|
2013-06-20 21:17:44 +02:00
|
|
|
::testing::FLAGS_gtest_death_test_style = "threadsafe";
|
|
|
|
char bufa[15];
|
|
|
|
char bufb[10];
|
|
|
|
strcpy(bufa, "01234567890123");
|
|
|
|
size_t n = strlen(bufa);
|
|
|
|
ASSERT_EXIT(strlcpy(bufb, bufa, n), testing::KilledBySignal(SIGABRT), "");
|
2013-12-21 03:43:21 +01:00
|
|
|
#else // __BIONIC__
|
|
|
|
GTEST_LOG_(INFO) << "This test does nothing.\n";
|
|
|
|
#endif // __BIONIC__
|
2013-06-20 21:17:44 +02:00
|
|
|
}
|
|
|
|
|
2013-06-29 17:15:25 +02:00
|
|
|
TEST(DEATHTEST, strlcat_fortified) {
|
2013-12-21 03:43:21 +01:00
|
|
|
#if defined(__BIONIC__)
|
2013-06-29 17:15:25 +02:00
|
|
|
::testing::FLAGS_gtest_death_test_style = "threadsafe";
|
|
|
|
char bufa[15];
|
|
|
|
char bufb[10];
|
|
|
|
bufb[0] = '\0';
|
|
|
|
strcpy(bufa, "01234567890123");
|
|
|
|
size_t n = strlen(bufa);
|
|
|
|
ASSERT_EXIT(strlcat(bufb, bufa, n), testing::KilledBySignal(SIGABRT), "");
|
2013-12-21 03:43:21 +01:00
|
|
|
#else // __BIONIC__
|
|
|
|
GTEST_LOG_(INFO) << "This test does nothing.\n";
|
|
|
|
#endif // __BIONIC__
|
2013-06-29 17:15:25 +02:00
|
|
|
}
|
|
|
|
|
2013-06-28 19:34:09 +02:00
|
|
|
TEST(DEATHTEST, sprintf_fortified) {
|
2013-04-30 01:29:37 +02:00
|
|
|
::testing::FLAGS_gtest_death_test_style = "threadsafe";
|
|
|
|
char buf[10];
|
|
|
|
char source_buf[15];
|
|
|
|
memcpy(source_buf, "12345678901234", 15);
|
2013-06-12 00:45:23 +02:00
|
|
|
ASSERT_EXIT(sprintf(buf, "%s", source_buf), testing::KilledBySignal(SIGABRT), "");
|
2013-04-30 01:29:37 +02:00
|
|
|
}
|
2013-05-30 22:21:14 +02:00
|
|
|
|
2013-10-02 23:14:40 +02:00
|
|
|
#ifndef __clang__
|
|
|
|
// This test is disabled in clang because clang doesn't properly detect
|
|
|
|
// this buffer overflow. TODO: Fix clang.
|
|
|
|
TEST(DEATHTEST, sprintf_malloc_fortified) {
|
|
|
|
::testing::FLAGS_gtest_death_test_style = "threadsafe";
|
|
|
|
char* buf = (char *) malloc(10);
|
|
|
|
char source_buf[11];
|
|
|
|
memcpy(source_buf, "1234567890", 11);
|
|
|
|
ASSERT_EXIT(sprintf(buf, "%s", source_buf), testing::KilledBySignal(SIGABRT), "");
|
|
|
|
free(buf);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2013-06-28 19:34:09 +02:00
|
|
|
TEST(DEATHTEST, sprintf2_fortified) {
|
2013-06-24 20:44:00 +02:00
|
|
|
::testing::FLAGS_gtest_death_test_style = "threadsafe";
|
|
|
|
char buf[5];
|
|
|
|
ASSERT_EXIT(sprintf(buf, "aaaaa"), testing::KilledBySignal(SIGABRT), "");
|
|
|
|
}
|
|
|
|
|
2013-06-27 17:58:14 +02:00
|
|
|
static int vsprintf_helper(const char *fmt, ...) {
|
|
|
|
char buf[10];
|
|
|
|
va_list va;
|
|
|
|
int result;
|
|
|
|
|
|
|
|
va_start(va, fmt);
|
|
|
|
result = vsprintf(buf, fmt, va); // should crash here
|
|
|
|
va_end(va);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2013-06-28 19:34:09 +02:00
|
|
|
TEST(DEATHTEST, vsprintf_fortified) {
|
2013-06-27 17:58:14 +02:00
|
|
|
::testing::FLAGS_gtest_death_test_style = "threadsafe";
|
|
|
|
ASSERT_EXIT(vsprintf_helper("%s", "0123456789"), testing::KilledBySignal(SIGABRT), "");
|
|
|
|
}
|
|
|
|
|
2013-06-28 19:34:09 +02:00
|
|
|
TEST(DEATHTEST, vsprintf2_fortified) {
|
2013-06-27 17:58:14 +02:00
|
|
|
::testing::FLAGS_gtest_death_test_style = "threadsafe";
|
|
|
|
ASSERT_EXIT(vsprintf_helper("0123456789"), testing::KilledBySignal(SIGABRT), "");
|
|
|
|
}
|
|
|
|
|
|
|
|
static int vsnprintf_helper(const char *fmt, ...) {
|
|
|
|
char buf[10];
|
|
|
|
va_list va;
|
|
|
|
int result;
|
|
|
|
size_t size = atoi("11");
|
|
|
|
|
|
|
|
va_start(va, fmt);
|
|
|
|
result = vsnprintf(buf, size, fmt, va); // should crash here
|
|
|
|
va_end(va);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2013-06-28 19:34:09 +02:00
|
|
|
TEST(DEATHTEST, vsnprintf_fortified) {
|
2013-06-27 17:58:14 +02:00
|
|
|
::testing::FLAGS_gtest_death_test_style = "threadsafe";
|
|
|
|
ASSERT_EXIT(vsnprintf_helper("%s", "0123456789"), testing::KilledBySignal(SIGABRT), "");
|
|
|
|
}
|
|
|
|
|
2013-06-28 19:34:09 +02:00
|
|
|
TEST(DEATHTEST, vsnprintf2_fortified) {
|
2013-06-27 17:58:14 +02:00
|
|
|
::testing::FLAGS_gtest_death_test_style = "threadsafe";
|
|
|
|
ASSERT_EXIT(vsnprintf_helper("0123456789"), testing::KilledBySignal(SIGABRT), "");
|
|
|
|
}
|
|
|
|
|
2013-06-28 19:34:09 +02:00
|
|
|
TEST(DEATHTEST, strncat_fortified) {
|
2013-05-30 22:21:14 +02:00
|
|
|
::testing::FLAGS_gtest_death_test_style = "threadsafe";
|
|
|
|
char buf[10];
|
|
|
|
size_t n = atoi("10"); // avoid compiler optimizations
|
|
|
|
strncpy(buf, "012345678", n);
|
2013-06-12 00:45:23 +02:00
|
|
|
ASSERT_EXIT(strncat(buf, "9", n), testing::KilledBySignal(SIGABRT), "");
|
2013-05-30 22:21:14 +02:00
|
|
|
}
|
|
|
|
|
2013-06-28 19:34:09 +02:00
|
|
|
TEST(DEATHTEST, strncat2_fortified) {
|
2013-05-30 22:21:14 +02:00
|
|
|
::testing::FLAGS_gtest_death_test_style = "threadsafe";
|
|
|
|
char buf[10];
|
|
|
|
buf[0] = '\0';
|
|
|
|
size_t n = atoi("10"); // avoid compiler optimizations
|
2013-06-12 00:45:23 +02:00
|
|
|
ASSERT_EXIT(strncat(buf, "0123456789", n), testing::KilledBySignal(SIGABRT), "");
|
2013-05-30 22:21:14 +02:00
|
|
|
}
|
2013-05-31 01:48:53 +02:00
|
|
|
|
2013-06-28 19:34:09 +02:00
|
|
|
TEST(DEATHTEST, strcat_fortified) {
|
2013-05-31 01:48:53 +02:00
|
|
|
::testing::FLAGS_gtest_death_test_style = "threadsafe";
|
|
|
|
char src[11];
|
|
|
|
strcpy(src, "0123456789");
|
|
|
|
char buf[10];
|
|
|
|
buf[0] = '\0';
|
2013-06-12 00:45:23 +02:00
|
|
|
ASSERT_EXIT(strcat(buf, src), testing::KilledBySignal(SIGABRT), "");
|
2013-05-31 01:48:53 +02:00
|
|
|
}
|
libc: add limited FORTIFY_SOURCE support for clang
In 829c089f83ddee37203b52bcb294867a9ae7bdbc, we disabled all
FORTIFY_SOURCE support when compiling under clang. At the time,
we didn't have proper test cases, and couldn't easily create targeted
clang tests.
This change re-enables FORTIFY_SOURCE support under clang for a
limited set of functions, where we have explicit unittests available.
The functions are:
* memcpy
* memmove
* strcpy
* strncpy
* strcat
* strncat
* memset
* strlen (with modifications)
* strchr (with modifications)
* strrchr (with modifications)
It may be possible, in the future, to enable other functions. However,
I need to write unittests first.
For strlen, strchr, and strrchr, clang unconditionally calls the
fortified version of the relevant function. If it doesn't know the
size of the buffer it's dealing with, it passes in ((size_t) -1),
which is the largest possible size_t.
I added two new clang specific unittest files, primarily copied
from fortify?_test.cpp.
I've also rebuild the entire system with these changes, and didn't
observe any obvious problems.
Change-Id: If12a15089bb0ffe93824b485290d05b14355fcaa
2013-06-17 23:49:19 +02:00
|
|
|
|
2013-06-28 19:34:09 +02:00
|
|
|
TEST(DEATHTEST, memmove_fortified) {
|
libc: add limited FORTIFY_SOURCE support for clang
In 829c089f83ddee37203b52bcb294867a9ae7bdbc, we disabled all
FORTIFY_SOURCE support when compiling under clang. At the time,
we didn't have proper test cases, and couldn't easily create targeted
clang tests.
This change re-enables FORTIFY_SOURCE support under clang for a
limited set of functions, where we have explicit unittests available.
The functions are:
* memcpy
* memmove
* strcpy
* strncpy
* strcat
* strncat
* memset
* strlen (with modifications)
* strchr (with modifications)
* strrchr (with modifications)
It may be possible, in the future, to enable other functions. However,
I need to write unittests first.
For strlen, strchr, and strrchr, clang unconditionally calls the
fortified version of the relevant function. If it doesn't know the
size of the buffer it's dealing with, it passes in ((size_t) -1),
which is the largest possible size_t.
I added two new clang specific unittest files, primarily copied
from fortify?_test.cpp.
I've also rebuild the entire system with these changes, and didn't
observe any obvious problems.
Change-Id: If12a15089bb0ffe93824b485290d05b14355fcaa
2013-06-17 23:49:19 +02:00
|
|
|
::testing::FLAGS_gtest_death_test_style = "threadsafe";
|
|
|
|
char buf[20];
|
|
|
|
strcpy(buf, "0123456789");
|
|
|
|
size_t n = atoi("10");
|
|
|
|
ASSERT_EXIT(memmove(buf + 11, buf, n), testing::KilledBySignal(SIGABRT), "");
|
|
|
|
}
|
|
|
|
|
2013-06-28 19:34:09 +02:00
|
|
|
TEST(DEATHTEST, memcpy_fortified) {
|
libc: add limited FORTIFY_SOURCE support for clang
In 829c089f83ddee37203b52bcb294867a9ae7bdbc, we disabled all
FORTIFY_SOURCE support when compiling under clang. At the time,
we didn't have proper test cases, and couldn't easily create targeted
clang tests.
This change re-enables FORTIFY_SOURCE support under clang for a
limited set of functions, where we have explicit unittests available.
The functions are:
* memcpy
* memmove
* strcpy
* strncpy
* strcat
* strncat
* memset
* strlen (with modifications)
* strchr (with modifications)
* strrchr (with modifications)
It may be possible, in the future, to enable other functions. However,
I need to write unittests first.
For strlen, strchr, and strrchr, clang unconditionally calls the
fortified version of the relevant function. If it doesn't know the
size of the buffer it's dealing with, it passes in ((size_t) -1),
which is the largest possible size_t.
I added two new clang specific unittest files, primarily copied
from fortify?_test.cpp.
I've also rebuild the entire system with these changes, and didn't
observe any obvious problems.
Change-Id: If12a15089bb0ffe93824b485290d05b14355fcaa
2013-06-17 23:49:19 +02:00
|
|
|
::testing::FLAGS_gtest_death_test_style = "threadsafe";
|
|
|
|
char bufa[10];
|
|
|
|
char bufb[10];
|
|
|
|
strcpy(bufa, "012345678");
|
|
|
|
size_t n = atoi("11");
|
|
|
|
ASSERT_EXIT(memcpy(bufb, bufa, n), testing::KilledBySignal(SIGABRT), "");
|
|
|
|
}
|
|
|
|
|
2014-04-04 23:38:18 +02:00
|
|
|
TEST(DEATHTEST, stpncpy_fortified) {
|
|
|
|
::testing::FLAGS_gtest_death_test_style = "threadsafe";
|
|
|
|
char bufa[15];
|
|
|
|
char bufb[10];
|
|
|
|
strcpy(bufa, "01234567890123");
|
|
|
|
size_t n = strlen(bufa);
|
|
|
|
ASSERT_EXIT(stpncpy(bufb, bufa, n), testing::KilledBySignal(SIGABRT), "");
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST(DEATHTEST, stpncpy2_fortified) {
|
|
|
|
::testing::FLAGS_gtest_death_test_style = "threadsafe";
|
|
|
|
char dest[11];
|
|
|
|
char src[10];
|
|
|
|
memcpy(src, "0123456789", sizeof(src)); // src is not null terminated
|
|
|
|
ASSERT_EXIT(stpncpy(dest, src, sizeof(dest)), testing::KilledBySignal(SIGABRT), "");
|
|
|
|
}
|
|
|
|
|
2013-06-28 19:34:09 +02:00
|
|
|
TEST(DEATHTEST, strncpy_fortified) {
|
libc: add limited FORTIFY_SOURCE support for clang
In 829c089f83ddee37203b52bcb294867a9ae7bdbc, we disabled all
FORTIFY_SOURCE support when compiling under clang. At the time,
we didn't have proper test cases, and couldn't easily create targeted
clang tests.
This change re-enables FORTIFY_SOURCE support under clang for a
limited set of functions, where we have explicit unittests available.
The functions are:
* memcpy
* memmove
* strcpy
* strncpy
* strcat
* strncat
* memset
* strlen (with modifications)
* strchr (with modifications)
* strrchr (with modifications)
It may be possible, in the future, to enable other functions. However,
I need to write unittests first.
For strlen, strchr, and strrchr, clang unconditionally calls the
fortified version of the relevant function. If it doesn't know the
size of the buffer it's dealing with, it passes in ((size_t) -1),
which is the largest possible size_t.
I added two new clang specific unittest files, primarily copied
from fortify?_test.cpp.
I've also rebuild the entire system with these changes, and didn't
observe any obvious problems.
Change-Id: If12a15089bb0ffe93824b485290d05b14355fcaa
2013-06-17 23:49:19 +02:00
|
|
|
::testing::FLAGS_gtest_death_test_style = "threadsafe";
|
|
|
|
char bufa[15];
|
|
|
|
char bufb[10];
|
|
|
|
strcpy(bufa, "01234567890123");
|
|
|
|
size_t n = strlen(bufa);
|
|
|
|
ASSERT_EXIT(strncpy(bufb, bufa, n), testing::KilledBySignal(SIGABRT), "");
|
|
|
|
}
|
2013-06-25 19:02:35 +02:00
|
|
|
|
2014-04-04 23:38:18 +02:00
|
|
|
|
2013-08-28 19:47:43 +02:00
|
|
|
TEST(DEATHTEST, strncpy2_fortified) {
|
|
|
|
::testing::FLAGS_gtest_death_test_style = "threadsafe";
|
|
|
|
char dest[11];
|
|
|
|
char src[10];
|
|
|
|
memcpy(src, "0123456789", sizeof(src)); // src is not null terminated
|
|
|
|
ASSERT_EXIT(strncpy(dest, src, sizeof(dest)), testing::KilledBySignal(SIGABRT), "");
|
|
|
|
}
|
|
|
|
|
2013-06-28 19:34:09 +02:00
|
|
|
TEST(DEATHTEST, snprintf_fortified) {
|
2013-06-25 19:02:35 +02:00
|
|
|
::testing::FLAGS_gtest_death_test_style = "threadsafe";
|
|
|
|
char bufa[15];
|
|
|
|
char bufb[10];
|
|
|
|
strcpy(bufa, "0123456789");
|
|
|
|
size_t n = strlen(bufa) + 1;
|
|
|
|
ASSERT_EXIT(snprintf(bufb, n, "%s", bufa), testing::KilledBySignal(SIGABRT), "");
|
|
|
|
}
|
2013-06-28 19:34:09 +02:00
|
|
|
|
2013-06-29 17:15:25 +02:00
|
|
|
TEST(DEATHTEST, bzero_fortified) {
|
|
|
|
::testing::FLAGS_gtest_death_test_style = "threadsafe";
|
|
|
|
char buf[10];
|
|
|
|
memcpy(buf, "0123456789", sizeof(buf));
|
|
|
|
size_t n = atoi("11");
|
|
|
|
ASSERT_EXIT(bzero(buf, n), testing::KilledBySignal(SIGABRT), "");
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST(DEATHTEST, umask_fortified) {
|
|
|
|
::testing::FLAGS_gtest_death_test_style = "threadsafe";
|
|
|
|
mode_t mask = atoi("1023"); // 01777 in octal
|
|
|
|
ASSERT_EXIT(umask(mask), testing::KilledBySignal(SIGABRT), "");
|
|
|
|
}
|
|
|
|
|
2013-09-25 01:32:07 +02:00
|
|
|
TEST(DEATHTEST, recv_fortified) {
|
|
|
|
::testing::FLAGS_gtest_death_test_style = "threadsafe";
|
|
|
|
size_t data_len = atoi("11"); // suppress compiler optimizations
|
|
|
|
char buf[10];
|
|
|
|
ASSERT_EXIT(recv(0, buf, data_len, 0), testing::KilledBySignal(SIGABRT), "");
|
|
|
|
}
|
|
|
|
|
2013-10-03 01:11:30 +02:00
|
|
|
TEST(DEATHTEST, FD_ISSET_fortified) {
|
2014-04-24 08:02:43 +02:00
|
|
|
#ifdef __BIONIC__ // glibc catches this at compile-time.
|
2013-10-03 01:11:30 +02:00
|
|
|
::testing::FLAGS_gtest_death_test_style = "threadsafe";
|
|
|
|
fd_set set;
|
|
|
|
memset(&set, 0, sizeof(set));
|
|
|
|
ASSERT_EXIT(FD_ISSET(-1, &set), testing::KilledBySignal(SIGABRT), "");
|
2014-04-24 08:02:43 +02:00
|
|
|
#endif
|
2013-10-03 01:11:30 +02:00
|
|
|
}
|
|
|
|
|
2013-10-03 23:08:39 +02:00
|
|
|
TEST(DEATHTEST, FD_ISSET_2_fortified) {
|
|
|
|
::testing::FLAGS_gtest_death_test_style = "threadsafe";
|
|
|
|
char buf[1];
|
|
|
|
fd_set* set = (fd_set*) buf;
|
|
|
|
ASSERT_EXIT(FD_ISSET(0, set), testing::KilledBySignal(SIGABRT), "");
|
|
|
|
}
|
|
|
|
|
2014-04-24 08:02:43 +02:00
|
|
|
// gtest's ASSERT_EXIT needs a valid expression, but glibc has a do-while macro.
|
|
|
|
static void FD_ZERO_function(fd_set* s) { FD_ZERO(s); }
|
|
|
|
|
2013-10-03 23:08:39 +02:00
|
|
|
TEST(DEATHTEST, FD_ZERO_fortified) {
|
|
|
|
::testing::FLAGS_gtest_death_test_style = "threadsafe";
|
|
|
|
char buf[1];
|
|
|
|
fd_set* set = (fd_set*) buf;
|
2014-04-24 08:02:43 +02:00
|
|
|
ASSERT_EXIT(FD_ZERO_function(set), testing::KilledBySignal(SIGABRT), "");
|
2013-10-03 23:08:39 +02:00
|
|
|
}
|
|
|
|
|
2013-10-10 05:16:34 +02:00
|
|
|
TEST(DEATHTEST, read_fortified) {
|
|
|
|
::testing::FLAGS_gtest_death_test_style = "threadsafe";
|
|
|
|
char buf[1];
|
|
|
|
size_t ct = atoi("2"); // prevent optimizations
|
|
|
|
int fd = open("/dev/null", O_RDONLY);
|
|
|
|
ASSERT_EXIT(read(fd, buf, ct), testing::KilledBySignal(SIGABRT), "");
|
|
|
|
close(fd);
|
|
|
|
}
|
|
|
|
|
2013-06-28 19:34:09 +02:00
|
|
|
extern "C" char* __strncat_chk(char*, const char*, size_t, size_t);
|
|
|
|
extern "C" char* __strcat_chk(char*, const char*, size_t);
|
|
|
|
|
|
|
|
TEST(TEST_NAME, strncat) {
|
|
|
|
char buf[10];
|
|
|
|
memset(buf, 'A', sizeof(buf));
|
|
|
|
buf[0] = 'a';
|
|
|
|
buf[1] = '\0';
|
|
|
|
char* res = __strncat_chk(buf, "01234", sizeof(buf) - strlen(buf) - 1, sizeof(buf));
|
|
|
|
ASSERT_EQ(buf, res);
|
|
|
|
ASSERT_EQ('a', buf[0]);
|
|
|
|
ASSERT_EQ('0', buf[1]);
|
|
|
|
ASSERT_EQ('1', buf[2]);
|
|
|
|
ASSERT_EQ('2', buf[3]);
|
|
|
|
ASSERT_EQ('3', buf[4]);
|
|
|
|
ASSERT_EQ('4', buf[5]);
|
|
|
|
ASSERT_EQ('\0', buf[6]);
|
|
|
|
ASSERT_EQ('A', buf[7]);
|
|
|
|
ASSERT_EQ('A', buf[8]);
|
|
|
|
ASSERT_EQ('A', buf[9]);
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST(TEST_NAME, strncat2) {
|
|
|
|
char buf[10];
|
|
|
|
memset(buf, 'A', sizeof(buf));
|
|
|
|
buf[0] = 'a';
|
|
|
|
buf[1] = '\0';
|
|
|
|
char* res = __strncat_chk(buf, "0123456789", 5, sizeof(buf));
|
|
|
|
ASSERT_EQ(buf, res);
|
|
|
|
ASSERT_EQ('a', buf[0]);
|
|
|
|
ASSERT_EQ('0', buf[1]);
|
|
|
|
ASSERT_EQ('1', buf[2]);
|
|
|
|
ASSERT_EQ('2', buf[3]);
|
|
|
|
ASSERT_EQ('3', buf[4]);
|
|
|
|
ASSERT_EQ('4', buf[5]);
|
|
|
|
ASSERT_EQ('\0', buf[6]);
|
|
|
|
ASSERT_EQ('A', buf[7]);
|
|
|
|
ASSERT_EQ('A', buf[8]);
|
|
|
|
ASSERT_EQ('A', buf[9]);
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST(TEST_NAME, strncat3) {
|
|
|
|
char buf[10];
|
|
|
|
memset(buf, 'A', sizeof(buf));
|
|
|
|
buf[0] = '\0';
|
|
|
|
char* res = __strncat_chk(buf, "0123456789", 5, sizeof(buf));
|
|
|
|
ASSERT_EQ(buf, res);
|
|
|
|
ASSERT_EQ('0', buf[0]);
|
|
|
|
ASSERT_EQ('1', buf[1]);
|
|
|
|
ASSERT_EQ('2', buf[2]);
|
|
|
|
ASSERT_EQ('3', buf[3]);
|
|
|
|
ASSERT_EQ('4', buf[4]);
|
|
|
|
ASSERT_EQ('\0', buf[5]);
|
|
|
|
ASSERT_EQ('A', buf[6]);
|
|
|
|
ASSERT_EQ('A', buf[7]);
|
|
|
|
ASSERT_EQ('A', buf[8]);
|
|
|
|
ASSERT_EQ('A', buf[9]);
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST(TEST_NAME, strncat4) {
|
|
|
|
char buf[10];
|
|
|
|
memset(buf, 'A', sizeof(buf));
|
|
|
|
buf[9] = '\0';
|
|
|
|
char* res = __strncat_chk(buf, "", 5, sizeof(buf));
|
|
|
|
ASSERT_EQ(buf, res);
|
|
|
|
ASSERT_EQ('A', buf[0]);
|
|
|
|
ASSERT_EQ('A', buf[1]);
|
|
|
|
ASSERT_EQ('A', buf[2]);
|
|
|
|
ASSERT_EQ('A', buf[3]);
|
|
|
|
ASSERT_EQ('A', buf[4]);
|
|
|
|
ASSERT_EQ('A', buf[5]);
|
|
|
|
ASSERT_EQ('A', buf[6]);
|
|
|
|
ASSERT_EQ('A', buf[7]);
|
|
|
|
ASSERT_EQ('A', buf[8]);
|
|
|
|
ASSERT_EQ('\0', buf[9]);
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST(TEST_NAME, strncat5) {
|
|
|
|
char buf[10];
|
|
|
|
memset(buf, 'A', sizeof(buf));
|
|
|
|
buf[0] = 'a';
|
|
|
|
buf[1] = '\0';
|
|
|
|
char* res = __strncat_chk(buf, "01234567", 8, sizeof(buf));
|
|
|
|
ASSERT_EQ(buf, res);
|
|
|
|
ASSERT_EQ('a', buf[0]);
|
|
|
|
ASSERT_EQ('0', buf[1]);
|
|
|
|
ASSERT_EQ('1', buf[2]);
|
|
|
|
ASSERT_EQ('2', buf[3]);
|
|
|
|
ASSERT_EQ('3', buf[4]);
|
|
|
|
ASSERT_EQ('4', buf[5]);
|
|
|
|
ASSERT_EQ('5', buf[6]);
|
|
|
|
ASSERT_EQ('6', buf[7]);
|
|
|
|
ASSERT_EQ('7', buf[8]);
|
|
|
|
ASSERT_EQ('\0', buf[9]);
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST(TEST_NAME, strncat6) {
|
|
|
|
char buf[10];
|
|
|
|
memset(buf, 'A', sizeof(buf));
|
|
|
|
buf[0] = 'a';
|
|
|
|
buf[1] = '\0';
|
|
|
|
char* res = __strncat_chk(buf, "01234567", 9, sizeof(buf));
|
|
|
|
ASSERT_EQ(buf, res);
|
|
|
|
ASSERT_EQ('a', buf[0]);
|
|
|
|
ASSERT_EQ('0', buf[1]);
|
|
|
|
ASSERT_EQ('1', buf[2]);
|
|
|
|
ASSERT_EQ('2', buf[3]);
|
|
|
|
ASSERT_EQ('3', buf[4]);
|
|
|
|
ASSERT_EQ('4', buf[5]);
|
|
|
|
ASSERT_EQ('5', buf[6]);
|
|
|
|
ASSERT_EQ('6', buf[7]);
|
|
|
|
ASSERT_EQ('7', buf[8]);
|
|
|
|
ASSERT_EQ('\0', buf[9]);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(TEST_NAME, strcat) {
|
|
|
|
char buf[10];
|
|
|
|
memset(buf, 'A', sizeof(buf));
|
|
|
|
buf[0] = 'a';
|
|
|
|
buf[1] = '\0';
|
|
|
|
char* res = __strcat_chk(buf, "01234", sizeof(buf));
|
|
|
|
ASSERT_EQ(buf, res);
|
|
|
|
ASSERT_EQ('a', buf[0]);
|
|
|
|
ASSERT_EQ('0', buf[1]);
|
|
|
|
ASSERT_EQ('1', buf[2]);
|
|
|
|
ASSERT_EQ('2', buf[3]);
|
|
|
|
ASSERT_EQ('3', buf[4]);
|
|
|
|
ASSERT_EQ('4', buf[5]);
|
|
|
|
ASSERT_EQ('\0', buf[6]);
|
|
|
|
ASSERT_EQ('A', buf[7]);
|
|
|
|
ASSERT_EQ('A', buf[8]);
|
|
|
|
ASSERT_EQ('A', buf[9]);
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST(TEST_NAME, strcat2) {
|
|
|
|
char buf[10];
|
|
|
|
memset(buf, 'A', sizeof(buf));
|
|
|
|
buf[0] = 'a';
|
|
|
|
buf[1] = '\0';
|
|
|
|
char* res = __strcat_chk(buf, "01234567", sizeof(buf));
|
|
|
|
ASSERT_EQ(buf, res);
|
|
|
|
ASSERT_EQ('a', buf[0]);
|
|
|
|
ASSERT_EQ('0', buf[1]);
|
|
|
|
ASSERT_EQ('1', buf[2]);
|
|
|
|
ASSERT_EQ('2', buf[3]);
|
|
|
|
ASSERT_EQ('3', buf[4]);
|
|
|
|
ASSERT_EQ('4', buf[5]);
|
|
|
|
ASSERT_EQ('5', buf[6]);
|
|
|
|
ASSERT_EQ('6', buf[7]);
|
|
|
|
ASSERT_EQ('7', buf[8]);
|
|
|
|
ASSERT_EQ('\0', buf[9]);
|
|
|
|
}
|
2013-08-28 19:47:43 +02:00
|
|
|
|
2014-04-04 23:38:18 +02:00
|
|
|
TEST(TEST_NAME, stpncpy) {
|
|
|
|
char src[10];
|
|
|
|
char dst[10];
|
|
|
|
memcpy(src, "0123456789", sizeof(src)); // non null terminated string
|
|
|
|
stpncpy(dst, src, sizeof(dst));
|
|
|
|
ASSERT_EQ('0', dst[0]);
|
|
|
|
ASSERT_EQ('1', dst[1]);
|
|
|
|
ASSERT_EQ('2', dst[2]);
|
|
|
|
ASSERT_EQ('3', dst[3]);
|
|
|
|
ASSERT_EQ('4', dst[4]);
|
|
|
|
ASSERT_EQ('5', dst[5]);
|
|
|
|
ASSERT_EQ('6', dst[6]);
|
|
|
|
ASSERT_EQ('7', dst[7]);
|
|
|
|
ASSERT_EQ('8', dst[8]);
|
|
|
|
ASSERT_EQ('9', dst[9]);
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST(TEST_NAME, stpncpy2) {
|
|
|
|
char src[10];
|
|
|
|
char dst[15];
|
|
|
|
memcpy(src, "012345678\0", sizeof(src));
|
|
|
|
stpncpy(dst, src, sizeof(dst));
|
|
|
|
ASSERT_EQ('0', dst[0]);
|
|
|
|
ASSERT_EQ('1', dst[1]);
|
|
|
|
ASSERT_EQ('2', dst[2]);
|
|
|
|
ASSERT_EQ('3', dst[3]);
|
|
|
|
ASSERT_EQ('4', dst[4]);
|
|
|
|
ASSERT_EQ('5', dst[5]);
|
|
|
|
ASSERT_EQ('6', dst[6]);
|
|
|
|
ASSERT_EQ('7', dst[7]);
|
|
|
|
ASSERT_EQ('8', dst[8]);
|
|
|
|
ASSERT_EQ('\0', dst[9]);
|
|
|
|
ASSERT_EQ('\0', dst[10]);
|
|
|
|
ASSERT_EQ('\0', dst[11]);
|
|
|
|
ASSERT_EQ('\0', dst[12]);
|
|
|
|
ASSERT_EQ('\0', dst[13]);
|
|
|
|
ASSERT_EQ('\0', dst[14]);
|
|
|
|
}
|
|
|
|
|
2013-08-28 19:47:43 +02:00
|
|
|
TEST(TEST_NAME, strncpy) {
|
|
|
|
char src[10];
|
|
|
|
char dst[10];
|
|
|
|
memcpy(src, "0123456789", sizeof(src)); // non null terminated string
|
|
|
|
strncpy(dst, src, sizeof(dst));
|
|
|
|
ASSERT_EQ('0', dst[0]);
|
|
|
|
ASSERT_EQ('1', dst[1]);
|
|
|
|
ASSERT_EQ('2', dst[2]);
|
|
|
|
ASSERT_EQ('3', dst[3]);
|
|
|
|
ASSERT_EQ('4', dst[4]);
|
|
|
|
ASSERT_EQ('5', dst[5]);
|
|
|
|
ASSERT_EQ('6', dst[6]);
|
|
|
|
ASSERT_EQ('7', dst[7]);
|
|
|
|
ASSERT_EQ('8', dst[8]);
|
|
|
|
ASSERT_EQ('9', dst[9]);
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST(TEST_NAME, strncpy2) {
|
|
|
|
char src[10];
|
|
|
|
char dst[15];
|
|
|
|
memcpy(src, "012345678\0", sizeof(src));
|
|
|
|
strncpy(dst, src, sizeof(dst));
|
|
|
|
ASSERT_EQ('0', dst[0]);
|
|
|
|
ASSERT_EQ('1', dst[1]);
|
|
|
|
ASSERT_EQ('2', dst[2]);
|
|
|
|
ASSERT_EQ('3', dst[3]);
|
|
|
|
ASSERT_EQ('4', dst[4]);
|
|
|
|
ASSERT_EQ('5', dst[5]);
|
|
|
|
ASSERT_EQ('6', dst[6]);
|
|
|
|
ASSERT_EQ('7', dst[7]);
|
|
|
|
ASSERT_EQ('8', dst[8]);
|
|
|
|
ASSERT_EQ('\0', dst[9]);
|
|
|
|
ASSERT_EQ('\0', dst[10]);
|
|
|
|
ASSERT_EQ('\0', dst[11]);
|
|
|
|
ASSERT_EQ('\0', dst[12]);
|
|
|
|
ASSERT_EQ('\0', dst[13]);
|
|
|
|
ASSERT_EQ('\0', dst[14]);
|
|
|
|
}
|
2013-09-11 01:56:34 +02:00
|
|
|
|
|
|
|
TEST(TEST_NAME, strcat_chk_max_int_size) {
|
|
|
|
char buf[10];
|
|
|
|
memset(buf, 'A', sizeof(buf));
|
|
|
|
buf[0] = 'a';
|
|
|
|
buf[1] = '\0';
|
|
|
|
char* res = __strcat_chk(buf, "01234567", (size_t)-1);
|
|
|
|
ASSERT_EQ(buf, res);
|
|
|
|
ASSERT_EQ('a', buf[0]);
|
|
|
|
ASSERT_EQ('0', buf[1]);
|
|
|
|
ASSERT_EQ('1', buf[2]);
|
|
|
|
ASSERT_EQ('2', buf[3]);
|
|
|
|
ASSERT_EQ('3', buf[4]);
|
|
|
|
ASSERT_EQ('4', buf[5]);
|
|
|
|
ASSERT_EQ('5', buf[6]);
|
|
|
|
ASSERT_EQ('6', buf[7]);
|
|
|
|
ASSERT_EQ('7', buf[8]);
|
|
|
|
ASSERT_EQ('\0', buf[9]);
|
|
|
|
}
|
|
|
|
|
2014-04-04 23:38:18 +02:00
|
|
|
extern "C" char* __stpcpy_chk(char*, const char*, size_t);
|
|
|
|
|
|
|
|
TEST(TEST_NAME, stpcpy_chk_max_int_size) {
|
|
|
|
char buf[10];
|
|
|
|
char* res = __stpcpy_chk(buf, "012345678", (size_t)-1);
|
|
|
|
ASSERT_EQ(buf + strlen("012345678"), res);
|
|
|
|
ASSERT_STREQ("012345678", buf);
|
|
|
|
}
|
|
|
|
|
2013-09-11 01:56:34 +02:00
|
|
|
extern "C" char* __strcpy_chk(char*, const char*, size_t);
|
|
|
|
|
|
|
|
TEST(TEST_NAME, strcpy_chk_max_int_size) {
|
|
|
|
char buf[10];
|
|
|
|
char* res = __strcpy_chk(buf, "012345678", (size_t)-1);
|
|
|
|
ASSERT_EQ(buf, res);
|
2014-04-04 23:38:18 +02:00
|
|
|
ASSERT_STREQ("012345678", buf);
|
2013-09-11 01:56:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" void* __memcpy_chk(void*, const void*, size_t, size_t);
|
|
|
|
|
|
|
|
TEST(TEST_NAME, memcpy_chk_max_int_size) {
|
|
|
|
char buf[10];
|
|
|
|
void* res = __memcpy_chk(buf, "012345678", sizeof(buf), (size_t)-1);
|
|
|
|
ASSERT_EQ((void*)buf, res);
|
|
|
|
ASSERT_EQ('0', buf[0]);
|
|
|
|
ASSERT_EQ('1', buf[1]);
|
|
|
|
ASSERT_EQ('2', buf[2]);
|
|
|
|
ASSERT_EQ('3', buf[3]);
|
|
|
|
ASSERT_EQ('4', buf[4]);
|
|
|
|
ASSERT_EQ('5', buf[5]);
|
|
|
|
ASSERT_EQ('6', buf[6]);
|
|
|
|
ASSERT_EQ('7', buf[7]);
|
|
|
|
ASSERT_EQ('8', buf[8]);
|
|
|
|
ASSERT_EQ('\0', buf[9]);
|
|
|
|
}
|
2013-10-11 09:45:24 +02:00
|
|
|
|
|
|
|
// Verify that macro expansion is done properly for sprintf/snprintf (which
|
|
|
|
// are defined as macros in stdio.h under clang).
|
|
|
|
#define CONTENTS "macro expansion"
|
|
|
|
#define BUF_AND_SIZE(A) A, sizeof(A)
|
|
|
|
#define BUF_AND_CONTENTS(A) A, CONTENTS
|
|
|
|
#define BUF_AND_SIZE_AND_CONTENTS(A) A, sizeof(A), CONTENTS
|
|
|
|
TEST(TEST_NAME, s_n_printf_macro_expansion) {
|
|
|
|
char buf[BUFSIZ];
|
|
|
|
snprintf(BUF_AND_SIZE(buf), CONTENTS);
|
|
|
|
EXPECT_STREQ(CONTENTS, buf);
|
|
|
|
|
|
|
|
snprintf(BUF_AND_SIZE_AND_CONTENTS(buf));
|
|
|
|
EXPECT_STREQ(CONTENTS, buf);
|
|
|
|
|
|
|
|
sprintf(BUF_AND_CONTENTS(buf));
|
|
|
|
EXPECT_STREQ(CONTENTS, buf);
|
|
|
|
}
|