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 = \
src/capnp/testdata/pretty.txt \
src/capnp/testdata/lists.binary \
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 \
cmake/FindCapnProto.cmake \
cmake/CapnProtoMacros.cmake \
cmake/CapnProtoTargets.cmake \
cmake/CapnProtoConfig.cmake.in \
cmake/CapnProtoConfigVersion.cmake.in \
src/CMakeLists.txt \
src/kj/CMakeLists.txt \
src/capnp/CMakeLists.txt
......@@ -120,7 +127,8 @@ cmakeconfig_DATA = $(CAPNP_CMAKE_CONFIG_FILES) \
cmake/CapnProtoTargets.cmake
noinst_HEADERS = \
src/kj/miniposix.h
src/kj/miniposix.h \
src/kj/async-io-internal.h
includekj_HEADERS = \
src/kj/common.h \
......@@ -168,7 +176,10 @@ includekjstd_HEADERS = \
includekjcompat_HEADERS = \
src/kj/compat/gtest.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 = \
src/capnp/c++.capnp.h \
......@@ -208,10 +219,20 @@ includecapnpcompat_HEADERS = \
src/capnp/compat/json.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
lib_LTLIBRARIES = libkj.la libkj-test.la libcapnp.la
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
# 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)
libkj_http_la_LDFLAGS = -release $(SO_VERSION) -no-undefined
libkj_http_la_SOURCES= \
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
if !LITE_MODE
......@@ -438,6 +467,8 @@ heavy_tests = \
src/kj/std/iostream-test.c++ \
src/kj/compat/url-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/capability-test.c++ \
src/capnp/membrane-test.c++ \
......@@ -461,6 +492,7 @@ capnp_test_LDADD = \
libcapnp-json.la \
libcapnp.la \
libkj-http.la \
$(MAYBE_KJ_TLS_LA) \
libkj-async.la \
libkj-test.la \
libkj.la \
......
......@@ -22,6 +22,11 @@ AC_ARG_WITH([external-capnp],
one (useful for cross-compiling)])],
[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], [
AS_HELP_STRING([--disable-reflection], [
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])
AC_CHECK_SIZEOF([void *])
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_OUTPUT
......@@ -336,16 +336,28 @@ struct MessageSize {
using kj::byte;
class word { uint64_t content KJ_UNUSED_MEMBER; KJ_DISALLOW_COPY(word); public: word() = default; };
// 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
// reinterpret_cast to some other pointer type.
//
// Copying is disallowed because you should always use memcpy(). Otherwise, you may run afoul of
// aliasing rules.
//
// A pointer of type word* should always be word-aligned even if won't actually be dereferenced as
// that type.
class word {
// 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
// reinterpret_cast to some other pointer type.
//
// Copying is disallowed because you should always use memcpy(). Otherwise, you may run afoul of
// aliasing rules.
//
// A pointer of type word* should always be word-aligned even if won't actually be dereferenced
// 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(word) == 8, "uint64_t is not 8 bytes?");
......
......@@ -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 {
KJ_REQUIRE(input.isObject(), "Expected object value");
KJ_REQUIRE(input.isObject(), "Expected object value") { return; }
for (auto field: input.getObject()) {
KJ_IF_MAYBE(fieldSchema, type.findFieldByName(field.getName())) {
decodeField(*fieldSchema, field.getValue(), orphanage, output);
......@@ -495,14 +495,16 @@ Orphan<DynamicValue> JsonCodec::decode(
case JsonValue::ARRAY:
return decodeArray(input.getArray(), type.asList(), orphanage);
default:
KJ_FAIL_REQUIRE("Expected list value");
KJ_FAIL_REQUIRE("Expected list value") { break; }
return orphanage.newOrphan(type.asList(), 0);
}
case schema::Type::ENUM:
switch (input.which()) {
case JsonValue::STRING:
return DynamicEnum(type.asEnum().getEnumerantByName(input.getString()));
default:
KJ_FAIL_REQUIRE("Expected enum value");
KJ_FAIL_REQUIRE("Expected enum value") { break; }
return DynamicEnum(type.asEnum(), 0);
}
case schema::Type::STRUCT: {
auto structType = type.asStruct();
......
......@@ -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 {
// A pointer, in exactly the format in which it appears on the wire.
......
......@@ -362,14 +362,20 @@ KJ_TEST("revoke membrane") {
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_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",
env.membraned.makeThingRequest().send().wait(env.io.waitScope));
KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("foobar",
env.membraned.makeThingRequest().send().ignoreResult().wait(env.io.waitScope));
KJ_EXPECT_THROW_MESSAGE("foobar",
thing.passThroughRequest().send().wait(env.io.waitScope));
KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("foobar",
thing.passThroughRequest().send().ignoreResult().wait(env.io.waitScope));
}
} // namespace
......
......@@ -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 {
// This class is a private helper for GetFunctorStartAddress. The class represents the internal
// representation of a pointer-to-member-function.
......@@ -310,6 +317,10 @@ class PtmfHelper {
#undef BODY
};
#if __GNUC__ >= 8 && !__clang__
#pragma GCC diagnostic pop
#endif
template <typename... ParamTypes>
struct GetFunctorStartAddress {
// Given a functor (any object defining operator()), return the start address of the function,
......
......@@ -910,7 +910,7 @@ KJ_TEST("Userland pipe with limit") {
KJ_EXPECT(!promise.poll(ws));
auto promise2 = pipe.out->write("barbaz", 6);
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.
......@@ -939,7 +939,7 @@ KJ_TEST("Userland pipe pumpTo with limit") {
auto promise2 = pipe.out->write("barbaz", 6);
promise.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.
......
......@@ -782,8 +782,10 @@ public:
}
private:
SocketAddress(): addrlen(0) {
memset(&addr, 0, sizeof(addr));
SocketAddress() {
// 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;
......@@ -906,7 +908,6 @@ Promise<Array<SocketAddress>> SocketAddress::lookupHost(
}
SocketAddress addr;
memset(&addr, 0, sizeof(addr)); // mollify valgrind
if (params.host == "*") {
// Set up a wildcard SocketAddress. Only use the port number returned by getaddrinfo().
addr.wildcard = true;
......
......@@ -597,7 +597,7 @@ TEST(Async, Canceler) {
canceler.cancel("foobar");
KJ_EXPECT_THROW_MESSAGE("foobar", never.wait(waitScope));
KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("foobar", never.wait(waitScope));
now.wait(waitScope);
KJ_EXPECT_THROW_MESSAGE("foobar", neverI.wait(waitScope));
KJ_EXPECT(nowI.wait(waitScope) == 123u);
......
......@@ -1730,7 +1730,7 @@ KJ_TEST("WebSocket pump disconnect on send") {
pipe2.ends[1] = nullptr;
// 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.
sendTask.wait(waitScope);
......@@ -2659,7 +2659,9 @@ public:
HttpMethod method, kj::StringPtr url, const HttpHeaders& headers,
kj::AsyncInputStream& requestBody, Response& response) override {
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 stream = response.send(200, "OK", HttpHeaders(headerTable), body.size());
......
......@@ -75,6 +75,7 @@ void X509_up_ref(X509* x509) {
#endif
#if OPENSSL_VERSION_NUMBER < 0x10100000L
class OpenSslInit {
// Initializes the OpenSSL library.
public:
......@@ -89,6 +90,11 @@ void ensureOpenSslInitialized() {
// Initializes the OpenSSL library the first time it is called.
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.
......
......@@ -249,6 +249,13 @@ EncodingResult<String> decodeUtf32(ArrayPtr<const char32_t> utf16) {
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>
Array<To> coerceTo(Array<From>&& array) {
static_assert(sizeof(To) == sizeof(From), "incompatible coercion");
......@@ -269,6 +276,10 @@ EncodingResult<Array<To>> coerceTo(EncodingResult<Array<From>>&& result) {
return { coerceTo<To>(Array<From>(kj::mv(result))), result.hadErrors };
}
#if __GNUC__ >= 8 && !__clang__
#pragma GCC diagnostic pop
#endif
template <size_t s>
struct WideConverter;
......
......@@ -41,10 +41,10 @@
#if !KJ_NO_RTTI
#include <typeinfo>
#endif
#if __GNUC__
#include <cxxabi.h>
#endif
#endif
#if (__linux__ && __GLIBC__ && !__UCLIBC__) || __APPLE__
#define KJ_HAS_BACKTRACE 1
......
......@@ -410,7 +410,7 @@ KJ_TEST("DiskDirectory") {
KJ_EXPECT(dir->tryOpenFile(Path({"foo", "bar"}), 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));
{
......@@ -537,9 +537,9 @@ KJ_TEST("DiskDirectory symlinks") {
KJ_EXPECT(dir->tryOpenFile(Path("foo")) == nullptr);
KJ_EXPECT(dir->tryOpenFile(Path("foo"), WriteMode::CREATE) == 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));
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 | WriteMode::CREATE_PARENT));
......
......@@ -133,18 +133,23 @@ KJ_TEST("Path exceptions") {
KJ_EXPECT_THROW_MESSAGE("invalid path component", Path(".."));
KJ_EXPECT_THROW_MESSAGE("NUL character", Path(StringPtr("foo\0bar", 7)));
KJ_EXPECT_THROW_MESSAGE("break out of starting", Path::parse(".."));
KJ_EXPECT_THROW_MESSAGE("break out of starting", Path::parse("../foo"));
KJ_EXPECT_THROW_MESSAGE("break out of starting", Path::parse("foo/../.."));
KJ_EXPECT_THROW_MESSAGE("expected a relative path", Path::parse("/foo"));
KJ_EXPECT_THROW_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_MESSAGE("break out of starting", Path({"foo", "bar"}).eval("../baz/../../.."));
KJ_EXPECT_THROW_MESSAGE("break out of starting", Path({"foo", "bar"}).eval("baz/../../../.."));
KJ_EXPECT_THROW_MESSAGE("break out of starting", 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", Path::parse(".."));
KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("break out of starting", Path::parse("../foo"));
KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("break out of starting", Path::parse("foo/../.."));
KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("expected a relative path", Path::parse("/foo"));
KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("NUL character", Path::parse(kj::StringPtr("foo\0bar", 7)));
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_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 parent", Path(nullptr).parent());
......@@ -210,28 +215,35 @@ KJ_TEST("Win32 Path") {
}
KJ_TEST("Win32 Path exceptions") {
KJ_EXPECT_THROW_MESSAGE("colons are prohibited", Path({"c:", "foo", "bar"}).toWin32String());
KJ_EXPECT_THROW_MESSAGE("colons are prohibited", Path({"c:", "foo:bar"}).toWin32String(true));
KJ_EXPECT_THROW_MESSAGE("DOS reserved name", Path({"con"}).toWin32String());
KJ_EXPECT_THROW_MESSAGE("DOS reserved name", Path({"CON", "bar"}).toWin32String());
KJ_EXPECT_THROW_MESSAGE("DOS reserved name", Path({"foo", "cOn"}).toWin32String());
KJ_EXPECT_THROW_MESSAGE("DOS reserved name", Path({"prn"}).toWin32String());
KJ_EXPECT_THROW_MESSAGE("DOS reserved name", Path({"aux"}).toWin32String());
KJ_EXPECT_THROW_MESSAGE("DOS reserved name", Path({"NUL"}).toWin32String());
KJ_EXPECT_THROW_MESSAGE("DOS reserved name", Path({"nul.txt"}).toWin32String());
KJ_EXPECT_THROW_MESSAGE("DOS reserved name", Path({"com3"}).toWin32String());
KJ_EXPECT_THROW_MESSAGE("DOS reserved name", Path({"lpt9"}).toWin32String());
KJ_EXPECT_THROW_MESSAGE("DOS reserved name", Path({"com1.hello"}).toWin32String());
KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("colons are prohibited",
Path({"c:", "foo", "bar"}).toWin32String());
KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("colons are prohibited",
Path({"c:", "foo:bar"}).toWin32String(true));
KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("DOS reserved name", Path({"con"}).toWin32String());
KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("DOS reserved name", Path({"CON", "bar"}).toWin32String());
KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("DOS reserved name", Path({"foo", "cOn"}).toWin32String());
KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("DOS reserved name", Path({"prn"}).toWin32String());
KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("DOS reserved name", Path({"aux"}).toWin32String());
KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("DOS reserved name", Path({"NUL"}).toWin32String());
KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("DOS reserved name", Path({"nul.txt"}).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("break out of starting", Path({"foo", "bar"}).evalWin32("../../.."));
KJ_EXPECT_THROW_MESSAGE("break out of starting", Path({"foo", "bar"}).evalWin32("../baz/../../.."));
KJ_EXPECT_THROW_MESSAGE("break out of starting", Path({"foo", "bar"}).evalWin32("baz/../../../.."));
KJ_EXPECT_THROW_MESSAGE("break out of starting", Path({"foo", "bar"}).evalWin32("c:\\..\\.."));
KJ_EXPECT_THROW_MESSAGE("break out of starting",
KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("break out of starting",
Path({"foo", "bar"}).evalWin32("../../.."));
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("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/../../.."));
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") {
......@@ -482,7 +494,7 @@ KJ_TEST("InMemoryDirectory") {
KJ_EXPECT(dir->tryOpenFile(Path({"foo", "bar"}), 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));
clock.expectUnchanged(*dir);
......@@ -628,9 +640,9 @@ KJ_TEST("InMemoryDirectory symlinks") {
KJ_EXPECT(dir->tryOpenFile(Path("foo")) == nullptr);
KJ_EXPECT(dir->tryOpenFile(Path("foo"), WriteMode::CREATE) == 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));
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 | WriteMode::CREATE_PARENT));
......
......@@ -251,11 +251,12 @@ String PathPtr::toWin32StringImpl(bool absolute, bool forApi) const {
for (size_t i = 0; i < p.size(); i++) {
*ptr++ = '|';
}
continue;
goto skip;
}
memcpy(ptr, p.begin(), p.size());
ptr += p.size();
skip:;
}
KJ_ASSERT(ptr == result.end());
......@@ -274,6 +275,7 @@ String PathPtr::toWin32StringImpl(bool absolute, bool forApi) const {
result) {
// Recover by using a different character which we know Win32 syscalls will reject.
result[i] = '|';
break;
}
}
}
......
......@@ -809,7 +809,7 @@ const InsertionOrderIndex::Link InsertionOrderIndex::EMPTY_LINK = { 0, 0 };
InsertionOrderIndex::InsertionOrderIndex(): capacity(0), links(const_cast<Link*>(&EMPTY_LINK)) {}
InsertionOrderIndex::~InsertionOrderIndex() noexcept(false) {
if (links != &EMPTY_LINK) delete links;
if (links != &EMPTY_LINK) delete[] links;
}
void InsertionOrderIndex::reserve(size_t size) {
......
......@@ -98,7 +98,7 @@ private:
#if KJ_NO_EXCEPTIONS
#define KJ_EXPECT_THROW(type, code) \
do { \
KJ_EXPECT(::kj::_::expectFatalThrow(type, nullptr, [&]() { code; })); \
KJ_EXPECT(::kj::_::expectFatalThrow(::kj::Exception::Type::type, nullptr, [&]() { code; })); \
} while (false)
#define KJ_EXPECT_THROW_MESSAGE(message, code) \
do { \
......
......@@ -451,7 +451,7 @@ if [ "x`uname -m`" = "xx86_64" ]; then
doit make distclean
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 distclean
fi
......@@ -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
# some 40 minutes. So, it needs to be done as a separate step of the release
# 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
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