From 11404af34c5e3d5aa334e1cfd8edee82fb9dc9a4 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Fri, 13 Jun 2014 19:18:13 -0400 Subject: [PATCH 1/3] sanity: autoconf check for sys/select.h --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index d8521ad3ad..81a32f9fb7 100644 --- a/configure.ac +++ b/configure.ac @@ -368,7 +368,7 @@ if test x$TARGET_OS = xdarwin; then AX_CHECK_LINK_FLAG([[-Wl,-dead_strip]], [LDFLAGS="$LDFLAGS -Wl,-dead_strip"]) fi -AC_CHECK_HEADERS([stdio.h stdlib.h unistd.h strings.h sys/types.h sys/stat.h]) +AC_CHECK_HEADERS([stdio.h stdlib.h unistd.h strings.h sys/types.h sys/stat.h sys/select.h]) dnl Check for MSG_NOSIGNAL AC_MSG_CHECKING(for MSG_NOSIGNAL) From 679240d0e92f71b38cefd23e3d99e8ebf63c2508 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Fri, 13 Jun 2014 19:19:35 -0400 Subject: [PATCH 2/3] sanity: add libc/stdlib sanity checks These are meant to test our back-compat stubs, but they are enabled for all builds for the sake of consistency. --- src/Makefile.am | 5 ++- src/compat/glibc_sanity.cpp | 61 +++++++++++++++++++++++++++++++++++ src/compat/glibcxx_sanity.cpp | 61 +++++++++++++++++++++++++++++++++++ src/compat/sanity.h | 7 ++++ 4 files changed, 133 insertions(+), 1 deletion(-) create mode 100644 src/compat/glibc_sanity.cpp create mode 100644 src/compat/glibcxx_sanity.cpp create mode 100644 src/compat/sanity.h diff --git a/src/Makefile.am b/src/Makefile.am index 0a76829197..e1542203f8 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -85,7 +85,8 @@ BITCOIN_CORE_H = \ util.h \ version.h \ walletdb.h \ - wallet.h + wallet.h \ + compat/sanity.h JSON_H = \ json/json_spirit.h \ @@ -154,6 +155,8 @@ libbitcoin_common_a_SOURCES = \ sync.cpp \ util.cpp \ version.cpp \ + compat/glibc_sanity.cpp \ + compat/glibcxx_sanity.cpp \ $(BITCOIN_CORE_H) if GLIBC_BACK_COMPAT diff --git a/src/compat/glibc_sanity.cpp b/src/compat/glibc_sanity.cpp new file mode 100644 index 0000000000..1f64df9e33 --- /dev/null +++ b/src/compat/glibc_sanity.cpp @@ -0,0 +1,61 @@ +#include "bitcoin-config.h" + +#include +#if defined(HAVE_SYS_SELECT_H) +#include +#endif + +extern "C" void* memcpy(void* a, const void* b, size_t c); +void* memcpy_int(void* a, const void* b, size_t c) +{ + return memcpy(a,b,c); +} + +namespace { +// trigger: Use the memcpy_int wrapper which calls our internal memcpy. +// A direct call to memcpy may be optimized away by the compiler. +// test: Fill an array with a sequence of integers. memcpy to a new empty array. +// Verify that the arrays are equal. Use an odd size to decrease the odds of +// the call being optimized away. +template +bool sanity_test_memcpy() +{ + unsigned int memcpy_test[T]; + unsigned int memcpy_verify[T] = {}; + for (unsigned int i = 0; i != T; ++i) + memcpy_test[i] = i; + + memcpy_int(memcpy_verify,memcpy_test,sizeof(memcpy_test)); + + for (unsigned int i = 0; i != T; ++i) + { + if(memcpy_verify[i] != i) + return false; + } + return true; +} + +#if defined(HAVE_SYS_SELECT_H) +// trigger: Call FD_SET to trigger __fdelt_chk. FORTIFY_SOURCE must be defined +// as >0 and optimizations must be set to at least -O2. +// test: Add a file descriptor to an empty fd_set. Verify that it has been +// correctly added. +bool sanity_test_fdelt() +{ + fd_set fds; + FD_ZERO(&fds); + FD_SET(0, &fds); + return FD_ISSET(0,&fds); +} +#endif + +} // anon namespace + +bool glibc_sanity_test() +{ +#if defined(HAVE_SYS_SELECT_H) + if (!sanity_test_fdelt()) + return false; +#endif + return sanity_test_memcpy<1025>(); +} diff --git a/src/compat/glibcxx_sanity.cpp b/src/compat/glibcxx_sanity.cpp new file mode 100644 index 0000000000..2ff70948fd --- /dev/null +++ b/src/compat/glibcxx_sanity.cpp @@ -0,0 +1,61 @@ +#include +#include +#include + +namespace{ + +// trigger: use ctype::widen to trigger ctype::_M_widen_init(). +// test: convert a char from narrow to wide and back. Verify that the result +// matches the original. +bool sanity_test_widen(char testchar) +{ + const std::ctype& test(std::use_facet< std::ctype >(std::locale())); + return test.narrow(test.widen(testchar),'b') == testchar; +} + +// trigger: use list::push_back and list::pop_back to trigger _M_hook and +// _M_unhook. +// test: Push a sequence of integers into a list. Pop them off and verify that +// they match the original sequence. +bool sanity_test_list(unsigned int size) +{ + std::list test; + for (unsigned int i = 0; i != size; ++i) + test.push_back(i+1); + + if (test.size() != size) + return false; + + while (!test.empty()) + { + if(test.back() != test.size()) + return false; + test.pop_back(); + } + return true; +} + +} // anon namespace + +// trigger: string::at(x) on an empty string to trigger __throw_out_of_range_fmt. +// test: force std::string to throw an out_of_range exception. Verify that +// it's caught correctly. +bool sanity_test_range_fmt() +{ + std::string test; + try + { + test.at(1); + } + catch (const std::out_of_range&) + { + return true; + } + catch (...){} + return false; +} + +bool glibcxx_sanity_test() +{ + return sanity_test_widen('a') && sanity_test_list(100) && sanity_test_range_fmt(); +} diff --git a/src/compat/sanity.h b/src/compat/sanity.h new file mode 100644 index 0000000000..a221f69dfc --- /dev/null +++ b/src/compat/sanity.h @@ -0,0 +1,7 @@ +#ifndef BITCON_COMPAT_SANITY_H +#define BITCON_COMPAT_SANITY_H + +bool glibc_sanity_test(); +bool glibcxx_sanity_test(); + +#endif From 92a6220711b3f98c3daad8a8dcdf13f09ce484fd Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Fri, 13 Jun 2014 19:23:01 -0400 Subject: [PATCH 3/3] sanity: hook up sanity checks --- src/init.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index 39453da9c8..f3df3cb375 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -31,6 +31,7 @@ #ifndef WIN32 #include #endif +#include "compat/sanity.h" #include #include @@ -417,8 +418,8 @@ bool InitSanityCheck(void) "information, visit https://en.bitcoin.it/wiki/OpenSSL_and_EC_Libraries"); return false; } - - // TODO: remaining sanity checks, see #4081 + if (!glibc_sanity_test() || !glibcxx_sanity_test()) + return false; return true; }