Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master' into async-cocoa
Browse files Browse the repository at this point in the history
  • Loading branch information
jjchoy committed Mar 4, 2015
2 parents cec428e + 63187bd commit e3715e7
Show file tree
Hide file tree
Showing 19 changed files with 839 additions and 25 deletions.
1 change: 1 addition & 0 deletions CONTRIBUTORS
Expand Up @@ -10,6 +10,7 @@ Scott Purdy <scott@fer.io>: kj/std iostream interface
Bryan Borham <bjboreham@gmail.com>: Initial MSVC support
Philip Quinn <p@partylemon.com>: cmake build and other assorted bits
Brian Taylor <el.wubo@gmail.com>: emacs syntax highlighting
Ben Laurie <ben@links.org>: discovered and responsibly disclosed security bugs

This file does not list people who maintain their own Cap'n Proto
implementations as separate projects. Those people are awesome too! :)
15 changes: 10 additions & 5 deletions c++/Makefile.am
Expand Up @@ -185,8 +185,12 @@ else
lib_LTLIBRARIES = libkj.la libkj-test.la libkj-async.la libcapnp.la libcapnp-rpc.la libcapnpc.la
endif

# Don't include security release in soname -- we want to replace old binaries
# in this case.
SO_VERSION = $(shell echo $(VERSION) | sed -re 's/^([0-9]+[.][0-9]+[.][0-9]+)([.][0-9]+)?(-.*)?$$/\1\3/g')

libkj_la_LIBADD = $(PTHREAD_LIBS)
libkj_la_LDFLAGS = -release $(VERSION) -no-undefined
libkj_la_LDFLAGS = -release $(SO_VERSION) -no-undefined
libkj_la_SOURCES= \
src/kj/common.c++ \
src/kj/units.c++ \
Expand All @@ -210,7 +214,7 @@ libkj_test_la_SOURCES = src/kj/test.c++

if !LITE_MODE
libkj_async_la_LIBADD = libkj.la $(PTHREAD_LIBS)
libkj_async_la_LDFLAGS = -release $(VERSION) -no-undefined
libkj_async_la_LDFLAGS = -release $(SO_VERSION) -no-undefined
libkj_async_la_SOURCES= \
src/kj/async.c++ \
src/kj/async-unix.c++ \
Expand All @@ -227,7 +231,7 @@ heavy_sources = \
endif !LITE_MODE

libcapnp_la_LIBADD = libkj.la $(PTHREAD_LIBS)
libcapnp_la_LDFLAGS = -release $(VERSION) -no-undefined
libcapnp_la_LDFLAGS = -release $(SO_VERSION) -no-undefined
libcapnp_la_SOURCES= \
src/capnp/c++.capnp.c++ \
src/capnp/blob.c++ \
Expand All @@ -245,7 +249,7 @@ libcapnp_la_SOURCES= \
if !LITE_MODE

libcapnp_rpc_la_LIBADD = libcapnp.la libkj-async.la libkj.la $(PTHREAD_LIBS)
libcapnp_rpc_la_LDFLAGS = -release $(VERSION) -no-undefined
libcapnp_rpc_la_LDFLAGS = -release $(SO_VERSION) -no-undefined
libcapnp_rpc_la_SOURCES= \
src/capnp/serialize-async.c++ \
src/capnp/capability.c++ \
Expand All @@ -258,7 +262,7 @@ libcapnp_rpc_la_SOURCES= \
src/capnp/ez-rpc.c++

libcapnpc_la_LIBADD = libcapnp.la libkj.la $(PTHREAD_LIBS)
libcapnpc_la_LDFLAGS = -release $(VERSION) -no-undefined
libcapnpc_la_LDFLAGS = -release $(SO_VERSION) -no-undefined
libcapnpc_la_SOURCES= \
src/capnp/compiler/md5.h \
src/capnp/compiler/md5.c++ \
Expand Down Expand Up @@ -413,6 +417,7 @@ capnp_test_SOURCES = \
src/capnp/orphan-test.c++ \
src/capnp/serialize-test.c++ \
src/capnp/serialize-packed-test.c++ \
src/capnp/fuzz-test.c++ \
src/capnp/test-util.c++ \
src/capnp/test-util.h \
$(heavy_tests)
Expand Down
1 change: 1 addition & 0 deletions c++/src/capnp/CMakeLists.txt
Expand Up @@ -195,6 +195,7 @@ if(BUILD_TESTING)
orphan-test.c++
serialize-test.c++
serialize-packed-test.c++
fuzz-test.c++
test-util.c++
${test_capnp_cpp_files}
${test_capnp_h_files}
Expand Down
14 changes: 14 additions & 0 deletions c++/src/capnp/any-test.c++
Expand Up @@ -162,6 +162,20 @@ TEST(Any, AnyStruct) {
// TODO: is there a higher-level API for this?
memcpy(sb.getDataSection().begin(), r.getDataSection().begin(), r.getDataSection().size());
}

{
auto ptrs = r.getPointerSection();
EXPECT_EQ("foo", ptrs[0].getAs<Text>());
EXPECT_EQ("bar", kj::heapString(ptrs[1].getAs<Data>().asChars()));
EXPECT_EQ("xyzzy", ptrs[15].getAs<List<Text>>()[1]);
}

{
auto ptrs = b.getPointerSection();
EXPECT_EQ("foo", ptrs[0].getAs<Text>());
EXPECT_EQ("bar", kj::heapString(ptrs[1].getAs<Data>().asChars()));
EXPECT_EQ("xyzzy", ptrs[15].getAs<List<Text>>()[1]);
}
}

TEST(Any, AnyList) {
Expand Down
4 changes: 2 additions & 2 deletions c++/src/capnp/any.h
Expand Up @@ -574,7 +574,7 @@ class AnyList::Reader {
inline uint size() { return _reader.size() / ELEMENTS; }

template <typename T> ReaderFor<T> as() {
// T must be List<U>.
// T must be List<U>.
return ReaderFor<T>(_reader);
}
private:
Expand All @@ -599,7 +599,7 @@ class AnyList::Builder {
inline uint size() { return _builder.size() / ELEMENTS; }

template <typename T> BuilderFor<T> as() {
// T must be List<U>.
// T must be List<U>.
return BuilderFor<T>(_builder);
}

Expand Down
11 changes: 11 additions & 0 deletions c++/src/capnp/arena.h
Expand Up @@ -117,6 +117,13 @@ class SegmentReader {

KJ_ALWAYS_INLINE(bool containsInterval(const void* from, const void* to));

KJ_ALWAYS_INLINE(bool amplifiedRead(WordCount virtualAmount));
// Indicates that the reader should pretend that `virtualAmount` additional data was read even
// though no actual pointer was traversed. This is used e.g. when reading a struct list pointer
// where the element sizes are zero -- the sender could set the list size arbitrarily high and
// cause the receiver to iterate over this list even though the message itself is small, so we
// need to defend agaisnt DoS attacks based on this.

inline Arena* getArena();
inline SegmentId getSegmentId();

Expand Down Expand Up @@ -367,6 +374,10 @@ inline bool SegmentReader::containsInterval(const void* from, const void* to) {
arena);
}

inline bool SegmentReader::amplifiedRead(WordCount virtualAmount) {
return readLimiter->canRead(virtualAmount, arena);
}

inline Arena* SegmentReader::getArena() { return arena; }
inline SegmentId SegmentReader::getSegmentId() { return id; }
inline const word* SegmentReader::getStartPtr() { return ptr.begin(); }
Expand Down
1 change: 1 addition & 0 deletions c++/src/capnp/common-test.c++
Expand Up @@ -40,6 +40,7 @@ TEST(Common, Version) {
kj::StringPtr actualVersion = VERSION;
KJ_ASSERT(actualVersion == expectedVersion ||
actualVersion.startsWith(kj::str(expectedVersion, '-')) ||
actualVersion.startsWith(kj::str(expectedVersion, '.')) ||
(actualVersion == devVersion && CAPNP_VERSION_MICRO == 0),
expectedVersion, actualVersion);
#endif
Expand Down
30 changes: 30 additions & 0 deletions c++/src/capnp/encoding-test.c++
Expand Up @@ -1410,6 +1410,36 @@ TEST(Encoding, Has) {
EXPECT_TRUE(root.asReader().hasInt32List());
}

TEST(Encoding, VoidListAmplification) {
MallocMessageBuilder builder;
builder.initRoot<test::TestAnyPointer>().getAnyPointerField().initAs<List<Void>>(1u << 28);

auto segments = builder.getSegmentsForOutput();
EXPECT_EQ(1, segments.size());
EXPECT_LT(segments[0].size(), 16); // quite small for such a big list!

SegmentArrayMessageReader reader(builder.getSegmentsForOutput());
auto root = reader.getRoot<test::TestAnyPointer>().getAnyPointerField();
EXPECT_NONFATAL_FAILURE(root.getAs<List<TestAllTypes>>());

MallocMessageBuilder copy;
EXPECT_NONFATAL_FAILURE(copy.setRoot(reader.getRoot<AnyPointer>()));
}

TEST(Encoding, EmptyStructListAmplification) {
MallocMessageBuilder builder;
builder.initRoot<test::TestAnyPointer>().getAnyPointerField()
.initAs<List<test::TestEmptyStruct>>(1u << 28);

auto segments = builder.getSegmentsForOutput();
EXPECT_EQ(1, segments.size());
EXPECT_LT(segments[0].size(), 16); // quite small for such a big list!

SegmentArrayMessageReader reader(builder.getSegmentsForOutput());
auto root = reader.getRoot<test::TestAnyPointer>().getAnyPointerField();
EXPECT_NONFATAL_FAILURE(root.getAs<List<TestAllTypes>>());
}

TEST(Encoding, Constants) {
EXPECT_EQ(VOID, test::TestConstants::VOID_CONST);
EXPECT_EQ(true, test::TestConstants::BOOL_CONST);
Expand Down

0 comments on commit e3715e7

Please sign in to comment.