Unverified Commit 6ecd99b2 authored by Kenton Varda's avatar Kenton Varda Committed by GitHub

Merge pull request #724 from capnproto/fixups-for-0.7

Fixups for 0.7
parents a0d44664 6fe9a3f4
...@@ -31,8 +31,15 @@ EXTRA_DIST = \ ...@@ -31,8 +31,15 @@ EXTRA_DIST = \
src/capnp/testdata/pretty.txt \ src/capnp/testdata/pretty.txt \
src/capnp/testdata/lists.binary \ src/capnp/testdata/lists.binary \
src/capnp/testdata/packedflat \ src/capnp/testdata/packedflat \
src/capnp/testdata/pretty.json \
src/capnp/testdata/short.json \
src/capnp/testdata/annotated-json.binary \
src/capnp/testdata/annotated.json \
CMakeLists.txt \ CMakeLists.txt \
cmake/FindCapnProto.cmake \ cmake/CapnProtoMacros.cmake \
cmake/CapnProtoTargets.cmake \
cmake/CapnProtoConfig.cmake.in \
cmake/CapnProtoConfigVersion.cmake.in \
src/CMakeLists.txt \ src/CMakeLists.txt \
src/kj/CMakeLists.txt \ src/kj/CMakeLists.txt \
src/capnp/CMakeLists.txt src/capnp/CMakeLists.txt
...@@ -120,7 +127,8 @@ cmakeconfig_DATA = $(CAPNP_CMAKE_CONFIG_FILES) \ ...@@ -120,7 +127,8 @@ cmakeconfig_DATA = $(CAPNP_CMAKE_CONFIG_FILES) \
cmake/CapnProtoTargets.cmake cmake/CapnProtoTargets.cmake
noinst_HEADERS = \ noinst_HEADERS = \
src/kj/miniposix.h src/kj/miniposix.h \
src/kj/async-io-internal.h
includekj_HEADERS = \ includekj_HEADERS = \
src/kj/common.h \ src/kj/common.h \
...@@ -168,7 +176,10 @@ includekjstd_HEADERS = \ ...@@ -168,7 +176,10 @@ includekjstd_HEADERS = \
includekjcompat_HEADERS = \ includekjcompat_HEADERS = \
src/kj/compat/gtest.h \ src/kj/compat/gtest.h \
src/kj/compat/url.h \ src/kj/compat/url.h \
src/kj/compat/http.h src/kj/compat/http.h \
src/kj/compat/gzip.h \
src/kj/compat/readiness-io.h \
src/kj/compat/tls.h
includecapnp_HEADERS = \ includecapnp_HEADERS = \
src/capnp/c++.capnp.h \ src/capnp/c++.capnp.h \
...@@ -208,10 +219,20 @@ includecapnpcompat_HEADERS = \ ...@@ -208,10 +219,20 @@ includecapnpcompat_HEADERS = \
src/capnp/compat/json.h \ src/capnp/compat/json.h \
src/capnp/compat/json.capnp.h src/capnp/compat/json.capnp.h
if BUILD_KJ_TLS
MAYBE_KJ_TLS_LA=libkj-tls.la
MAYBE_KJ_TLS_TESTS= \
src/kj/compat/readiness-io-test.c++ \
src/kj/compat/tls-test.c++
else
MAYBE_KJ_TLS_LA=
MAYBE_KJ_TLS_TESTS=
endif
if LITE_MODE if LITE_MODE
lib_LTLIBRARIES = libkj.la libkj-test.la libcapnp.la lib_LTLIBRARIES = libkj.la libkj-test.la libcapnp.la
else else
lib_LTLIBRARIES = libkj.la libkj-test.la libkj-async.la libkj-http.la libcapnp.la libcapnp-rpc.la libcapnp-json.la libcapnpc.la lib_LTLIBRARIES = libkj.la libkj-test.la libkj-async.la libkj-http.la $(MAYBE_KJ_TLS_LA) libcapnp.la libcapnp-rpc.la libcapnp-json.la libcapnpc.la
endif endif
# Don't include security release in soname -- we want to replace old binaries # Don't include security release in soname -- we want to replace old binaries
...@@ -265,7 +286,15 @@ libkj_http_la_LIBADD = libkj-async.la libkj.la $(ASYNC_LIBS) $(PTHREAD_LIBS) ...@@ -265,7 +286,15 @@ libkj_http_la_LIBADD = libkj-async.la libkj.la $(ASYNC_LIBS) $(PTHREAD_LIBS)
libkj_http_la_LDFLAGS = -release $(SO_VERSION) -no-undefined libkj_http_la_LDFLAGS = -release $(SO_VERSION) -no-undefined
libkj_http_la_SOURCES= \ libkj_http_la_SOURCES= \
src/kj/compat/url.c++ \ src/kj/compat/url.c++ \
src/kj/compat/http.c++ src/kj/compat/http.c++ \
src/kj/compat/gzip.c++
libkj_tls_la_LIBADD = libkj-async.la libkj.la -lssl -lcrypto $(ASYNC_LIBS) $(PTHREAD_LIBS)
libkj_tls_la_LDFLAGS = -release $(SO_VERSION) -no-undefined
libkj_tls_la_SOURCES= \
src/kj/compat/readiness-io.c++ \
src/kj/compat/tls.c++
endif !LITE_MODE endif !LITE_MODE
if !LITE_MODE if !LITE_MODE
...@@ -438,6 +467,8 @@ heavy_tests = \ ...@@ -438,6 +467,8 @@ heavy_tests = \
src/kj/std/iostream-test.c++ \ src/kj/std/iostream-test.c++ \
src/kj/compat/url-test.c++ \ src/kj/compat/url-test.c++ \
src/kj/compat/http-test.c++ \ src/kj/compat/http-test.c++ \
src/kj/compat/gzip-test.c++ \
$(MAYBE_KJ_TLS_TESTS) \
src/capnp/canonicalize-test.c++ \ src/capnp/canonicalize-test.c++ \
src/capnp/capability-test.c++ \ src/capnp/capability-test.c++ \
src/capnp/membrane-test.c++ \ src/capnp/membrane-test.c++ \
...@@ -461,6 +492,7 @@ capnp_test_LDADD = \ ...@@ -461,6 +492,7 @@ capnp_test_LDADD = \
libcapnp-json.la \ libcapnp-json.la \
libcapnp.la \ libcapnp.la \
libkj-http.la \ libkj-http.la \
$(MAYBE_KJ_TLS_LA) \
libkj-async.la \ libkj-async.la \
libkj-test.la \ libkj-test.la \
libkj.la \ libkj.la \
......
...@@ -22,6 +22,11 @@ AC_ARG_WITH([external-capnp], ...@@ -22,6 +22,11 @@ AC_ARG_WITH([external-capnp],
one (useful for cross-compiling)])], one (useful for cross-compiling)])],
[external_capnp=yes],[external_capnp=no]) [external_capnp=yes],[external_capnp=no])
AC_ARG_WITH([openssl],
[AS_HELP_STRING([--with-openssl],
[build libkj-tls by linking against openssl @<:@default=check@:>@])],
[],[with_openssl=check])
AC_ARG_ENABLE([reflection], [ AC_ARG_ENABLE([reflection], [
AS_HELP_STRING([--disable-reflection], [ AS_HELP_STRING([--disable-reflection], [
compile Cap'n Proto in "lite mode", in which all reflection APIs (schema.h, dynamic.h, etc.) compile Cap'n Proto in "lite mode", in which all reflection APIs (schema.h, dynamic.h, etc.)
...@@ -135,5 +140,27 @@ AC_SUBST([PACKAGE_CMAKE_INSTALL_FULL_INCLUDEDIR]) ...@@ -135,5 +140,27 @@ AC_SUBST([PACKAGE_CMAKE_INSTALL_FULL_INCLUDEDIR])
AC_CHECK_SIZEOF([void *]) AC_CHECK_SIZEOF([void *])
AC_SUBST(CMAKE_SIZEOF_VOID_P, $ac_cv_sizeof_void_p) AC_SUBST(CMAKE_SIZEOF_VOID_P, $ac_cv_sizeof_void_p)
# Detect presence of OpenSSL, if it was not specified explicitly.
AS_IF([test "$with_openssl" = check], [
AC_CHECK_LIB(crypto, CRYPTO_new_ex_data, [:], [
with_openssl=no
])
AC_CHECK_LIB(ssl, OPENSSL_init_ssl, [:], [
with_openssl=no
], [-lcrypto])
AC_CHECK_HEADER([openssl/ssl.h], [:], [
with_openssl=no
])
AS_IF([test "$with_openssl" = no], [
AC_MSG_WARN("could not find OpenSSL -- won't build libkj-tls")
], [
with_openssl=yes
])
])
AS_IF([test "$with_openssl" != no], [
CXXFLAGS="$CXXFLAGS -DKJ_HAS_OPENSSL"
])
AM_CONDITIONAL([BUILD_KJ_TLS], [test "$with_openssl" != no])
AC_CONFIG_FILES([Makefile] CAPNP_PKG_CONFIG_FILES CAPNP_CMAKE_CONFIG_FILES) AC_CONFIG_FILES([Makefile] CAPNP_PKG_CONFIG_FILES CAPNP_CMAKE_CONFIG_FILES)
AC_OUTPUT AC_OUTPUT
...@@ -336,16 +336,28 @@ struct MessageSize { ...@@ -336,16 +336,28 @@ struct MessageSize {
using kj::byte; using kj::byte;
class word { uint64_t content KJ_UNUSED_MEMBER; KJ_DISALLOW_COPY(word); public: word() = default; }; class word {
// word is an opaque type with size of 64 bits. This type is useful only to make pointer // word is an opaque type with size of 64 bits. This type is useful only to make pointer
// arithmetic clearer. Since the contents are private, the only way to access them is to first // arithmetic clearer. Since the contents are private, the only way to access them is to first
// reinterpret_cast to some other pointer type. // reinterpret_cast to some other pointer type.
// //
// Copying is disallowed because you should always use memcpy(). Otherwise, you may run afoul of // Copying is disallowed because you should always use memcpy(). Otherwise, you may run afoul of
// aliasing rules. // aliasing rules.
// //
// A pointer of type word* should always be word-aligned even if won't actually be dereferenced as // A pointer of type word* should always be word-aligned even if won't actually be dereferenced
// that type. // as that type.
public:
word() = default;
private:
uint64_t content KJ_UNUSED_MEMBER;
#if __GNUC__ < 8 || __clang__
// GCC 8's -Wclass-memaccess complains whenever we try to memcpy() a `word` if we've disallowed
// the copy constructor. We don't want to disable the warning becaues it's a useful warning and
// we'd have to disable it for all applications that include this header. Instead we allow `word`
// to be copyable on GCC.
KJ_DISALLOW_COPY(word);
#endif
};
static_assert(sizeof(byte) == 1, "uint8_t is not one byte?"); static_assert(sizeof(byte) == 1, "uint8_t is not one byte?");
static_assert(sizeof(word) == 8, "uint64_t is not 8 bytes?"); static_assert(sizeof(word) == 8, "uint64_t is not 8 bytes?");
......
...@@ -382,7 +382,7 @@ Orphan<DynamicList> JsonCodec::decodeArray(List<JsonValue>::Reader input, ListSc ...@@ -382,7 +382,7 @@ Orphan<DynamicList> JsonCodec::decodeArray(List<JsonValue>::Reader input, ListSc
} }
void JsonCodec::decodeObject(JsonValue::Reader input, StructSchema type, Orphanage orphanage, DynamicStruct::Builder output) const { void JsonCodec::decodeObject(JsonValue::Reader input, StructSchema type, Orphanage orphanage, DynamicStruct::Builder output) const {
KJ_REQUIRE(input.isObject(), "Expected object value"); KJ_REQUIRE(input.isObject(), "Expected object value") { return; }
for (auto field: input.getObject()) { for (auto field: input.getObject()) {
KJ_IF_MAYBE(fieldSchema, type.findFieldByName(field.getName())) { KJ_IF_MAYBE(fieldSchema, type.findFieldByName(field.getName())) {
decodeField(*fieldSchema, field.getValue(), orphanage, output); decodeField(*fieldSchema, field.getValue(), orphanage, output);
...@@ -495,14 +495,16 @@ Orphan<DynamicValue> JsonCodec::decode( ...@@ -495,14 +495,16 @@ Orphan<DynamicValue> JsonCodec::decode(
case JsonValue::ARRAY: case JsonValue::ARRAY:
return decodeArray(input.getArray(), type.asList(), orphanage); return decodeArray(input.getArray(), type.asList(), orphanage);
default: default:
KJ_FAIL_REQUIRE("Expected list value"); KJ_FAIL_REQUIRE("Expected list value") { break; }
return orphanage.newOrphan(type.asList(), 0);
} }
case schema::Type::ENUM: case schema::Type::ENUM:
switch (input.which()) { switch (input.which()) {
case JsonValue::STRING: case JsonValue::STRING:
return DynamicEnum(type.asEnum().getEnumerantByName(input.getString())); return DynamicEnum(type.asEnum().getEnumerantByName(input.getString()));
default: default:
KJ_FAIL_REQUIRE("Expected enum value"); KJ_FAIL_REQUIRE("Expected enum value") { break; }
return DynamicEnum(type.asEnum(), 0);
} }
case schema::Type::STRUCT: { case schema::Type::STRUCT: {
auto structType = type.asStruct(); auto structType = type.asStruct();
......
...@@ -72,6 +72,16 @@ namespace _ { // private ...@@ -72,6 +72,16 @@ namespace _ { // private
// ======================================================================================= // =======================================================================================
#if __GNUC__ >= 8 && !__clang__
// GCC 8 introduced a warning which complains whenever we try to memset() or memcpy() a
// WirePointer, becaues we deleted the regular copy constructor / assignment operator. Weirdly, if
// I remove those deletions, GCC *still* complains that WirePointer is non-trivial. I don't
// understand why -- maybe because WireValue has private members? We don't want to make WireValue's
// member public, but memset() and memcpy() on it are certainly valid and desirable, so we'll just
// have to disable the warning I guess.
#pragma GCC diagnostic ignored "-Wclass-memaccess"
#endif
struct WirePointer { struct WirePointer {
// A pointer, in exactly the format in which it appears on the wire. // A pointer, in exactly the format in which it appears on the wire.
......
...@@ -362,14 +362,20 @@ KJ_TEST("revoke membrane") { ...@@ -362,14 +362,20 @@ KJ_TEST("revoke membrane") {
paf.fulfiller->reject(KJ_EXCEPTION(DISCONNECTED, "foobar")); paf.fulfiller->reject(KJ_EXCEPTION(DISCONNECTED, "foobar"));
// TRICKY: We need to use .ignoreResult().wait() below because when compiling with
// -fno-exceptions, void waits throw recoverable exceptions while non-void waits necessarily
// throw fatal exceptions... but testing for fatal exceptions when exceptions are disabled
// involves fork()ing the process to run the code so if it has side effects on file descriptors
// then we'll get in a bad state...
KJ_ASSERT(callPromise.poll(env.io.waitScope)); KJ_ASSERT(callPromise.poll(env.io.waitScope));
KJ_EXPECT_THROW_MESSAGE("foobar", callPromise.wait(env.io.waitScope)); KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("foobar", callPromise.ignoreResult().wait(env.io.waitScope));
KJ_EXPECT_THROW_MESSAGE("foobar", KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("foobar",
env.membraned.makeThingRequest().send().wait(env.io.waitScope)); env.membraned.makeThingRequest().send().ignoreResult().wait(env.io.waitScope));
KJ_EXPECT_THROW_MESSAGE("foobar", KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("foobar",
thing.passThroughRequest().send().wait(env.io.waitScope)); thing.passThroughRequest().send().ignoreResult().wait(env.io.waitScope));
} }
} // namespace } // namespace
......
...@@ -249,6 +249,13 @@ private: ...@@ -249,6 +249,13 @@ private:
// ------------------------------------------------------------------- // -------------------------------------------------------------------
#if __GNUC__ >= 8 && !__clang__
// GCC 8's class-memaccess warning rightly does not like the memcpy()'s below, but there's no
// "legal" way for us to extract the contetn of a PTMF so too bad.
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wclass-memaccess"
#endif
class PtmfHelper { class PtmfHelper {
// This class is a private helper for GetFunctorStartAddress. The class represents the internal // This class is a private helper for GetFunctorStartAddress. The class represents the internal
// representation of a pointer-to-member-function. // representation of a pointer-to-member-function.
...@@ -310,6 +317,10 @@ class PtmfHelper { ...@@ -310,6 +317,10 @@ class PtmfHelper {
#undef BODY #undef BODY
}; };
#if __GNUC__ >= 8 && !__clang__
#pragma GCC diagnostic pop
#endif
template <typename... ParamTypes> template <typename... ParamTypes>
struct GetFunctorStartAddress { struct GetFunctorStartAddress {
// Given a functor (any object defining operator()), return the start address of the function, // Given a functor (any object defining operator()), return the start address of the function,
......
...@@ -910,7 +910,7 @@ KJ_TEST("Userland pipe with limit") { ...@@ -910,7 +910,7 @@ KJ_TEST("Userland pipe with limit") {
KJ_EXPECT(!promise.poll(ws)); KJ_EXPECT(!promise.poll(ws));
auto promise2 = pipe.out->write("barbaz", 6); auto promise2 = pipe.out->write("barbaz", 6);
KJ_EXPECT(promise.wait(ws) == "bar"); KJ_EXPECT(promise.wait(ws) == "bar");
KJ_EXPECT_THROW_MESSAGE("read end of pipe was aborted", promise2.wait(ws)); KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("read end of pipe was aborted", promise2.wait(ws));
} }
// Further writes throw and reads return EOF. // Further writes throw and reads return EOF.
...@@ -939,7 +939,7 @@ KJ_TEST("Userland pipe pumpTo with limit") { ...@@ -939,7 +939,7 @@ KJ_TEST("Userland pipe pumpTo with limit") {
auto promise2 = pipe.out->write("barbaz", 6); auto promise2 = pipe.out->write("barbaz", 6);
promise.wait(ws); promise.wait(ws);
pumpPromise.wait(ws); pumpPromise.wait(ws);
KJ_EXPECT_THROW_MESSAGE("read end of pipe was aborted", promise2.wait(ws)); KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("read end of pipe was aborted", promise2.wait(ws));
} }
// Further writes throw. // Further writes throw.
......
...@@ -782,8 +782,10 @@ public: ...@@ -782,8 +782,10 @@ public:
} }
private: private:
SocketAddress(): addrlen(0) { SocketAddress() {
memset(&addr, 0, sizeof(addr)); // We need to memset the whole object 0 otherwise Valgrind gets unhappy when we write it to a
// pipe, due to the padding bytes being uninitialized.
memset(this, 0, sizeof(*this));
} }
socklen_t addrlen; socklen_t addrlen;
...@@ -906,7 +908,6 @@ Promise<Array<SocketAddress>> SocketAddress::lookupHost( ...@@ -906,7 +908,6 @@ Promise<Array<SocketAddress>> SocketAddress::lookupHost(
} }
SocketAddress addr; SocketAddress addr;
memset(&addr, 0, sizeof(addr)); // mollify valgrind
if (params.host == "*") { if (params.host == "*") {
// Set up a wildcard SocketAddress. Only use the port number returned by getaddrinfo(). // Set up a wildcard SocketAddress. Only use the port number returned by getaddrinfo().
addr.wildcard = true; addr.wildcard = true;
......
...@@ -597,7 +597,7 @@ TEST(Async, Canceler) { ...@@ -597,7 +597,7 @@ TEST(Async, Canceler) {
canceler.cancel("foobar"); canceler.cancel("foobar");
KJ_EXPECT_THROW_MESSAGE("foobar", never.wait(waitScope)); KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("foobar", never.wait(waitScope));
now.wait(waitScope); now.wait(waitScope);
KJ_EXPECT_THROW_MESSAGE("foobar", neverI.wait(waitScope)); KJ_EXPECT_THROW_MESSAGE("foobar", neverI.wait(waitScope));
KJ_EXPECT(nowI.wait(waitScope) == 123u); KJ_EXPECT(nowI.wait(waitScope) == 123u);
......
...@@ -1730,7 +1730,7 @@ KJ_TEST("WebSocket pump disconnect on send") { ...@@ -1730,7 +1730,7 @@ KJ_TEST("WebSocket pump disconnect on send") {
pipe2.ends[1] = nullptr; pipe2.ends[1] = nullptr;
// Pump throws disconnected. // Pump throws disconnected.
KJ_EXPECT_THROW(DISCONNECTED, pumpTask.wait(waitScope)); KJ_EXPECT_THROW_RECOVERABLE(DISCONNECTED, pumpTask.wait(waitScope));
// client1 managed to send its whole message into the pump, though. // client1 managed to send its whole message into the pump, though.
sendTask.wait(waitScope); sendTask.wait(waitScope);
...@@ -2659,7 +2659,9 @@ public: ...@@ -2659,7 +2659,9 @@ public:
HttpMethod method, kj::StringPtr url, const HttpHeaders& headers, HttpMethod method, kj::StringPtr url, const HttpHeaders& headers,
kj::AsyncInputStream& requestBody, Response& response) override { kj::AsyncInputStream& requestBody, Response& response) override {
if (!headers.isWebSocket()) { if (!headers.isWebSocket()) {
KJ_ASSERT(url != "/throw"); if (url == "/throw") {
return KJ_EXCEPTION(FAILED, "client requested failure");
}
auto body = kj::str(headers.get(HttpHeaderId::HOST).orDefault("null"), ":", url); auto body = kj::str(headers.get(HttpHeaderId::HOST).orDefault("null"), ":", url);
auto stream = response.send(200, "OK", HttpHeaders(headerTable), body.size()); auto stream = response.send(200, "OK", HttpHeaders(headerTable), body.size());
......
...@@ -75,6 +75,7 @@ void X509_up_ref(X509* x509) { ...@@ -75,6 +75,7 @@ void X509_up_ref(X509* x509) {
#endif #endif
#if OPENSSL_VERSION_NUMBER < 0x10100000L
class OpenSslInit { class OpenSslInit {
// Initializes the OpenSSL library. // Initializes the OpenSSL library.
public: public:
...@@ -89,6 +90,11 @@ void ensureOpenSslInitialized() { ...@@ -89,6 +90,11 @@ void ensureOpenSslInitialized() {
// Initializes the OpenSSL library the first time it is called. // Initializes the OpenSSL library the first time it is called.
static OpenSslInit init; static OpenSslInit init;
} }
#else
inline void ensureOpenSslInitialized() {
// As of 1.1.0, no initialization is needed.
}
#endif
// ======================================================================================= // =======================================================================================
// Implementation of kj::AsyncIoStream that applies TLS on top of some other AsyncIoStream. // Implementation of kj::AsyncIoStream that applies TLS on top of some other AsyncIoStream.
......
...@@ -249,6 +249,13 @@ EncodingResult<String> decodeUtf32(ArrayPtr<const char32_t> utf16) { ...@@ -249,6 +249,13 @@ EncodingResult<String> decodeUtf32(ArrayPtr<const char32_t> utf16) {
namespace { namespace {
#if __GNUC__ >= 8 && !__clang__
// GCC 8's new class-memaccess warning rightly dislikes the following hacks, but we're really sure
// we want to allow them so disable the warning.
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wclass-memaccess"
#endif
template <typename To, typename From> template <typename To, typename From>
Array<To> coerceTo(Array<From>&& array) { Array<To> coerceTo(Array<From>&& array) {
static_assert(sizeof(To) == sizeof(From), "incompatible coercion"); static_assert(sizeof(To) == sizeof(From), "incompatible coercion");
...@@ -269,6 +276,10 @@ EncodingResult<Array<To>> coerceTo(EncodingResult<Array<From>>&& result) { ...@@ -269,6 +276,10 @@ EncodingResult<Array<To>> coerceTo(EncodingResult<Array<From>>&& result) {
return { coerceTo<To>(Array<From>(kj::mv(result))), result.hadErrors }; return { coerceTo<To>(Array<From>(kj::mv(result))), result.hadErrors };
} }
#if __GNUC__ >= 8 && !__clang__
#pragma GCC diagnostic pop
#endif
template <size_t s> template <size_t s>
struct WideConverter; struct WideConverter;
......
...@@ -41,10 +41,10 @@ ...@@ -41,10 +41,10 @@
#if !KJ_NO_RTTI #if !KJ_NO_RTTI
#include <typeinfo> #include <typeinfo>
#endif
#if __GNUC__ #if __GNUC__
#include <cxxabi.h> #include <cxxabi.h>
#endif #endif
#endif
#if (__linux__ && __GLIBC__ && !__UCLIBC__) || __APPLE__ #if (__linux__ && __GLIBC__ && !__UCLIBC__) || __APPLE__
#define KJ_HAS_BACKTRACE 1 #define KJ_HAS_BACKTRACE 1
......
...@@ -410,7 +410,7 @@ KJ_TEST("DiskDirectory") { ...@@ -410,7 +410,7 @@ KJ_TEST("DiskDirectory") {
KJ_EXPECT(dir->tryOpenFile(Path({"foo", "bar"}), WriteMode::MODIFY) == nullptr); KJ_EXPECT(dir->tryOpenFile(Path({"foo", "bar"}), WriteMode::MODIFY) == nullptr);
KJ_EXPECT(dir->tryOpenFile(Path({"bar", "baz"}), WriteMode::MODIFY) == nullptr); KJ_EXPECT(dir->tryOpenFile(Path({"bar", "baz"}), WriteMode::MODIFY) == nullptr);
KJ_EXPECT_THROW_MESSAGE("parent is not a directory", KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("parent is not a directory",
dir->tryOpenFile(Path({"bar", "baz"}), WriteMode::CREATE)); dir->tryOpenFile(Path({"bar", "baz"}), WriteMode::CREATE));
{ {
...@@ -537,9 +537,9 @@ KJ_TEST("DiskDirectory symlinks") { ...@@ -537,9 +537,9 @@ KJ_TEST("DiskDirectory symlinks") {
KJ_EXPECT(dir->tryOpenFile(Path("foo")) == nullptr); KJ_EXPECT(dir->tryOpenFile(Path("foo")) == nullptr);
KJ_EXPECT(dir->tryOpenFile(Path("foo"), WriteMode::CREATE) == nullptr); KJ_EXPECT(dir->tryOpenFile(Path("foo"), WriteMode::CREATE) == nullptr);
KJ_EXPECT(dir->tryOpenFile(Path("foo"), WriteMode::MODIFY) == nullptr); KJ_EXPECT(dir->tryOpenFile(Path("foo"), WriteMode::MODIFY) == nullptr);
KJ_EXPECT_THROW_MESSAGE("parent is not a directory", KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("parent is not a directory",
dir->tryOpenFile(Path("foo"), WriteMode::CREATE | WriteMode::MODIFY)); dir->tryOpenFile(Path("foo"), WriteMode::CREATE | WriteMode::MODIFY));
KJ_EXPECT_THROW_MESSAGE("parent is not a directory", KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("parent is not a directory",
dir->tryOpenFile(Path("foo"), dir->tryOpenFile(Path("foo"),
WriteMode::CREATE | WriteMode::MODIFY | WriteMode::CREATE_PARENT)); WriteMode::CREATE | WriteMode::MODIFY | WriteMode::CREATE_PARENT));
......
...@@ -133,18 +133,23 @@ KJ_TEST("Path exceptions") { ...@@ -133,18 +133,23 @@ KJ_TEST("Path exceptions") {
KJ_EXPECT_THROW_MESSAGE("invalid path component", Path("..")); KJ_EXPECT_THROW_MESSAGE("invalid path component", Path(".."));
KJ_EXPECT_THROW_MESSAGE("NUL character", Path(StringPtr("foo\0bar", 7))); KJ_EXPECT_THROW_MESSAGE("NUL character", Path(StringPtr("foo\0bar", 7)));
KJ_EXPECT_THROW_MESSAGE("break out of starting", Path::parse("..")); KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("break out of starting", Path::parse(".."));
KJ_EXPECT_THROW_MESSAGE("break out of starting", Path::parse("../foo")); KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("break out of starting", Path::parse("../foo"));
KJ_EXPECT_THROW_MESSAGE("break out of starting", Path::parse("foo/../..")); KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("break out of starting", Path::parse("foo/../.."));
KJ_EXPECT_THROW_MESSAGE("expected a relative path", Path::parse("/foo")); KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("expected a relative path", Path::parse("/foo"));
KJ_EXPECT_THROW_MESSAGE("NUL character", Path::parse(kj::StringPtr("foo\0bar", 7))); KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("NUL character", Path::parse(kj::StringPtr("foo\0bar", 7)));
KJ_EXPECT_THROW_MESSAGE("break out of starting", Path({"foo", "bar"}).eval("../../..")); KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("break out of starting",
KJ_EXPECT_THROW_MESSAGE("break out of starting", Path({"foo", "bar"}).eval("../baz/../../..")); Path({"foo", "bar"}).eval("../../.."));
KJ_EXPECT_THROW_MESSAGE("break out of starting", Path({"foo", "bar"}).eval("baz/../../../..")); KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("break out of starting",
KJ_EXPECT_THROW_MESSAGE("break out of starting", Path({"foo", "bar"}).eval("/..")); Path({"foo", "bar"}).eval("../baz/../../.."));
KJ_EXPECT_THROW_MESSAGE("break out of starting", Path({"foo", "bar"}).eval("/baz/../..")); KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("break out of starting",
Path({"foo", "bar"}).eval("baz/../../../.."));
KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("break out of starting",
Path({"foo", "bar"}).eval("/.."));
KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("break out of starting",
Path({"foo", "bar"}).eval("/baz/../.."));
KJ_EXPECT_THROW_MESSAGE("root path has no basename", Path(nullptr).basename()); KJ_EXPECT_THROW_MESSAGE("root path has no basename", Path(nullptr).basename());
KJ_EXPECT_THROW_MESSAGE("root path has no parent", Path(nullptr).parent()); KJ_EXPECT_THROW_MESSAGE("root path has no parent", Path(nullptr).parent());
...@@ -210,28 +215,35 @@ KJ_TEST("Win32 Path") { ...@@ -210,28 +215,35 @@ KJ_TEST("Win32 Path") {
} }
KJ_TEST("Win32 Path exceptions") { KJ_TEST("Win32 Path exceptions") {
KJ_EXPECT_THROW_MESSAGE("colons are prohibited", Path({"c:", "foo", "bar"}).toWin32String()); KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("colons are prohibited",
KJ_EXPECT_THROW_MESSAGE("colons are prohibited", Path({"c:", "foo:bar"}).toWin32String(true)); Path({"c:", "foo", "bar"}).toWin32String());
KJ_EXPECT_THROW_MESSAGE("DOS reserved name", Path({"con"}).toWin32String()); KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("colons are prohibited",
KJ_EXPECT_THROW_MESSAGE("DOS reserved name", Path({"CON", "bar"}).toWin32String()); Path({"c:", "foo:bar"}).toWin32String(true));
KJ_EXPECT_THROW_MESSAGE("DOS reserved name", Path({"foo", "cOn"}).toWin32String()); KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("DOS reserved name", Path({"con"}).toWin32String());
KJ_EXPECT_THROW_MESSAGE("DOS reserved name", Path({"prn"}).toWin32String()); KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("DOS reserved name", Path({"CON", "bar"}).toWin32String());
KJ_EXPECT_THROW_MESSAGE("DOS reserved name", Path({"aux"}).toWin32String()); KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("DOS reserved name", Path({"foo", "cOn"}).toWin32String());
KJ_EXPECT_THROW_MESSAGE("DOS reserved name", Path({"NUL"}).toWin32String()); KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("DOS reserved name", Path({"prn"}).toWin32String());
KJ_EXPECT_THROW_MESSAGE("DOS reserved name", Path({"nul.txt"}).toWin32String()); KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("DOS reserved name", Path({"aux"}).toWin32String());
KJ_EXPECT_THROW_MESSAGE("DOS reserved name", Path({"com3"}).toWin32String()); KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("DOS reserved name", Path({"NUL"}).toWin32String());
KJ_EXPECT_THROW_MESSAGE("DOS reserved name", Path({"lpt9"}).toWin32String()); KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("DOS reserved name", Path({"nul.txt"}).toWin32String());
KJ_EXPECT_THROW_MESSAGE("DOS reserved name", Path({"com1.hello"}).toWin32String()); KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("DOS reserved name", Path({"com3"}).toWin32String());
KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("DOS reserved name", Path({"lpt9"}).toWin32String());
KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("DOS reserved name", Path({"com1.hello"}).toWin32String());
KJ_EXPECT_THROW_MESSAGE("drive letter or netbios", Path({"?", "foo"}).toWin32String(true)); KJ_EXPECT_THROW_MESSAGE("drive letter or netbios", Path({"?", "foo"}).toWin32String(true));
KJ_EXPECT_THROW_MESSAGE("break out of starting", Path({"foo", "bar"}).evalWin32("../../..")); KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("break out of starting",
KJ_EXPECT_THROW_MESSAGE("break out of starting", Path({"foo", "bar"}).evalWin32("../baz/../../..")); Path({"foo", "bar"}).evalWin32("../../.."));
KJ_EXPECT_THROW_MESSAGE("break out of starting", Path({"foo", "bar"}).evalWin32("baz/../../../..")); KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("break out of starting",
KJ_EXPECT_THROW_MESSAGE("break out of starting", Path({"foo", "bar"}).evalWin32("c:\\..\\..")); Path({"foo", "bar"}).evalWin32("../baz/../../.."));
KJ_EXPECT_THROW_MESSAGE("break out of starting", KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("break out of starting",
Path({"foo", "bar"}).evalWin32("baz/../../../.."));
KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("break out of starting",
Path({"foo", "bar"}).evalWin32("c:\\..\\.."));
KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("break out of starting",
Path({"c:", "foo", "bar"}).evalWin32("/baz/../../..")); Path({"c:", "foo", "bar"}).evalWin32("/baz/../../.."));
KJ_EXPECT_THROW_MESSAGE("must specify drive letter", Path({"foo"}).evalWin32("\\baz\\qux")); KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("must specify drive letter",
Path({"foo"}).evalWin32("\\baz\\qux"));
} }
KJ_TEST("WriteMode operators") { KJ_TEST("WriteMode operators") {
...@@ -482,7 +494,7 @@ KJ_TEST("InMemoryDirectory") { ...@@ -482,7 +494,7 @@ KJ_TEST("InMemoryDirectory") {
KJ_EXPECT(dir->tryOpenFile(Path({"foo", "bar"}), WriteMode::MODIFY) == nullptr); KJ_EXPECT(dir->tryOpenFile(Path({"foo", "bar"}), WriteMode::MODIFY) == nullptr);
KJ_EXPECT(dir->tryOpenFile(Path({"bar", "baz"}), WriteMode::MODIFY) == nullptr); KJ_EXPECT(dir->tryOpenFile(Path({"bar", "baz"}), WriteMode::MODIFY) == nullptr);
KJ_EXPECT_THROW_MESSAGE("parent is not a directory", KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("parent is not a directory",
dir->tryOpenFile(Path({"bar", "baz"}), WriteMode::CREATE)); dir->tryOpenFile(Path({"bar", "baz"}), WriteMode::CREATE));
clock.expectUnchanged(*dir); clock.expectUnchanged(*dir);
...@@ -628,9 +640,9 @@ KJ_TEST("InMemoryDirectory symlinks") { ...@@ -628,9 +640,9 @@ KJ_TEST("InMemoryDirectory symlinks") {
KJ_EXPECT(dir->tryOpenFile(Path("foo")) == nullptr); KJ_EXPECT(dir->tryOpenFile(Path("foo")) == nullptr);
KJ_EXPECT(dir->tryOpenFile(Path("foo"), WriteMode::CREATE) == nullptr); KJ_EXPECT(dir->tryOpenFile(Path("foo"), WriteMode::CREATE) == nullptr);
KJ_EXPECT(dir->tryOpenFile(Path("foo"), WriteMode::MODIFY) == nullptr); KJ_EXPECT(dir->tryOpenFile(Path("foo"), WriteMode::MODIFY) == nullptr);
KJ_EXPECT_THROW_MESSAGE("parent is not a directory", KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("parent is not a directory",
dir->tryOpenFile(Path("foo"), WriteMode::CREATE | WriteMode::MODIFY)); dir->tryOpenFile(Path("foo"), WriteMode::CREATE | WriteMode::MODIFY));
KJ_EXPECT_THROW_MESSAGE("parent is not a directory", KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("parent is not a directory",
dir->tryOpenFile(Path("foo"), dir->tryOpenFile(Path("foo"),
WriteMode::CREATE | WriteMode::MODIFY | WriteMode::CREATE_PARENT)); WriteMode::CREATE | WriteMode::MODIFY | WriteMode::CREATE_PARENT));
......
...@@ -251,11 +251,12 @@ String PathPtr::toWin32StringImpl(bool absolute, bool forApi) const { ...@@ -251,11 +251,12 @@ String PathPtr::toWin32StringImpl(bool absolute, bool forApi) const {
for (size_t i = 0; i < p.size(); i++) { for (size_t i = 0; i < p.size(); i++) {
*ptr++ = '|'; *ptr++ = '|';
} }
continue; goto skip;
} }
memcpy(ptr, p.begin(), p.size()); memcpy(ptr, p.begin(), p.size());
ptr += p.size(); ptr += p.size();
skip:;
} }
KJ_ASSERT(ptr == result.end()); KJ_ASSERT(ptr == result.end());
...@@ -274,6 +275,7 @@ String PathPtr::toWin32StringImpl(bool absolute, bool forApi) const { ...@@ -274,6 +275,7 @@ String PathPtr::toWin32StringImpl(bool absolute, bool forApi) const {
result) { result) {
// Recover by using a different character which we know Win32 syscalls will reject. // Recover by using a different character which we know Win32 syscalls will reject.
result[i] = '|'; result[i] = '|';
break;
} }
} }
} }
......
...@@ -809,7 +809,7 @@ const InsertionOrderIndex::Link InsertionOrderIndex::EMPTY_LINK = { 0, 0 }; ...@@ -809,7 +809,7 @@ const InsertionOrderIndex::Link InsertionOrderIndex::EMPTY_LINK = { 0, 0 };
InsertionOrderIndex::InsertionOrderIndex(): capacity(0), links(const_cast<Link*>(&EMPTY_LINK)) {} InsertionOrderIndex::InsertionOrderIndex(): capacity(0), links(const_cast<Link*>(&EMPTY_LINK)) {}
InsertionOrderIndex::~InsertionOrderIndex() noexcept(false) { InsertionOrderIndex::~InsertionOrderIndex() noexcept(false) {
if (links != &EMPTY_LINK) delete links; if (links != &EMPTY_LINK) delete[] links;
} }
void InsertionOrderIndex::reserve(size_t size) { void InsertionOrderIndex::reserve(size_t size) {
......
...@@ -98,7 +98,7 @@ private: ...@@ -98,7 +98,7 @@ private:
#if KJ_NO_EXCEPTIONS #if KJ_NO_EXCEPTIONS
#define KJ_EXPECT_THROW(type, code) \ #define KJ_EXPECT_THROW(type, code) \
do { \ do { \
KJ_EXPECT(::kj::_::expectFatalThrow(type, nullptr, [&]() { code; })); \ KJ_EXPECT(::kj::_::expectFatalThrow(::kj::Exception::Type::type, nullptr, [&]() { code; })); \
} while (false) } while (false)
#define KJ_EXPECT_THROW_MESSAGE(message, code) \ #define KJ_EXPECT_THROW_MESSAGE(message, code) \
do { \ do { \
......
...@@ -451,7 +451,7 @@ if [ "x`uname -m`" = "xx86_64" ]; then ...@@ -451,7 +451,7 @@ if [ "x`uname -m`" = "xx86_64" ]; then
doit make distclean doit make distclean
elif [ "x${CXX:-g++}" != "xg++-4.8" ]; then elif [ "x${CXX:-g++}" != "xg++-4.8" ]; then
doit ./configure CXX="${CXX:-g++} -m32" --disable-shared doit ./configure CXX="${CXX:-g++} -m32" CXXFLAGS="$CXXFLAGS ${ADDL_M32_FLAGS:-}" --disable-shared
doit make -j$PARALLEL check doit make -j$PARALLEL check
doit make distclean doit make distclean
fi fi
...@@ -516,7 +516,7 @@ if [ "x`uname`" != xDarwin ] && which valgrind > /dev/null; then ...@@ -516,7 +516,7 @@ if [ "x`uname`" != xDarwin ] && which valgrind > /dev/null; then
# Running the fuzz tests under Valgrind is a great thing to do -- but it takes # Running the fuzz tests under Valgrind is a great thing to do -- but it takes
# some 40 minutes. So, it needs to be done as a separate step of the release # some 40 minutes. So, it needs to be done as a separate step of the release
# process, perhaps along with the AFL tests. # process, perhaps along with the AFL tests.
CAPNP_SKIP_FUZZ_TEST=1 doit valgrind --leak-check=full --track-fds=yes --error-exitcode=1 ./capnp-test CAPNP_SKIP_FUZZ_TEST=1 doit valgrind --leak-check=full --track-fds=yes --error-exitcode=1 --child-silent-after-fork=yes --sim-hints=lax-ioctls ./capnp-test
fi fi
doit make maintainer-clean doit make maintainer-clean
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment