Commit a1e067fb authored by Kenton Varda's avatar Kenton Varda

Rename 'trusted' messages to 'unchecked', since they don't have to be quite so trusted anymore.

parent de15e658
...@@ -712,20 +712,20 @@ DynamicValue::Reader DynamicStruct::Reader::getImpl( ...@@ -712,20 +712,20 @@ DynamicValue::Reader DynamicStruct::Reader::getImpl(
ListSchema::of(elementType, member.getContainingStruct()), ListSchema::of(elementType, member.getContainingStruct()),
reader.getListField(field.getOffset() * POINTERS, reader.getListField(field.getOffset() * POINTERS,
elementSizeFor(elementType.getBody().which()), elementSizeFor(elementType.getBody().which()),
dval.getListValue<internal::TrustedMessage>()))); dval.getListValue<internal::UncheckedMessage>())));
} }
case schema::Type::Body::STRUCT_TYPE: { case schema::Type::Body::STRUCT_TYPE: {
return DynamicValue::Reader(DynamicStruct::Reader( return DynamicValue::Reader(DynamicStruct::Reader(
member.getContainingStruct().getDependency(type.getStructType()).asStruct(), member.getContainingStruct().getDependency(type.getStructType()).asStruct(),
reader.getStructField(field.getOffset() * POINTERS, reader.getStructField(field.getOffset() * POINTERS,
dval.getStructValue<internal::TrustedMessage>()))); dval.getStructValue<internal::UncheckedMessage>())));
} }
case schema::Type::Body::OBJECT_TYPE: { case schema::Type::Body::OBJECT_TYPE: {
return DynamicValue::Reader(DynamicObject( return DynamicValue::Reader(DynamicObject(
reader.getObjectField(field.getOffset() * POINTERS, reader.getObjectField(field.getOffset() * POINTERS,
dval.getObjectValue<internal::TrustedMessage>()))); dval.getObjectValue<internal::UncheckedMessage>())));
} }
case schema::Type::Body::INTERFACE_TYPE: case schema::Type::Body::INTERFACE_TYPE:
...@@ -805,12 +805,12 @@ DynamicValue::Builder DynamicStruct::Builder::getImpl( ...@@ -805,12 +805,12 @@ DynamicValue::Builder DynamicStruct::Builder::getImpl(
return DynamicValue::Builder(DynamicList::Builder(listType, return DynamicValue::Builder(DynamicList::Builder(listType,
builder.getStructListField(field.getOffset() * POINTERS, builder.getStructListField(field.getOffset() * POINTERS,
structSizeFromSchema(listType.getStructElementType()), structSizeFromSchema(listType.getStructElementType()),
dval.getListValue<internal::TrustedMessage>()))); dval.getListValue<internal::UncheckedMessage>())));
} else { } else {
return DynamicValue::Builder(DynamicList::Builder(listType, return DynamicValue::Builder(DynamicList::Builder(listType,
builder.getListField(field.getOffset() * POINTERS, builder.getListField(field.getOffset() * POINTERS,
elementSizeFor(listType.whichElementType()), elementSizeFor(listType.whichElementType()),
dval.getListValue<internal::TrustedMessage>()))); dval.getListValue<internal::UncheckedMessage>())));
} }
} }
...@@ -822,14 +822,14 @@ DynamicValue::Builder DynamicStruct::Builder::getImpl( ...@@ -822,14 +822,14 @@ DynamicValue::Builder DynamicStruct::Builder::getImpl(
builder.getStructField( builder.getStructField(
field.getOffset() * POINTERS, field.getOffset() * POINTERS,
structSizeFromSchema(structSchema), structSizeFromSchema(structSchema),
dval.getStructValue<internal::TrustedMessage>()))); dval.getStructValue<internal::UncheckedMessage>())));
} }
case schema::Type::Body::OBJECT_TYPE: { case schema::Type::Body::OBJECT_TYPE: {
return DynamicValue::Builder(DynamicObject( return DynamicValue::Builder(DynamicObject(
builder.asReader().getObjectField( builder.asReader().getObjectField(
field.getOffset() * POINTERS, field.getOffset() * POINTERS,
dval.getObjectValue<internal::TrustedMessage>()))); dval.getObjectValue<internal::UncheckedMessage>())));
} }
case schema::Type::Body::INTERFACE_TYPE: case schema::Type::Body::INTERFACE_TYPE:
......
...@@ -69,7 +69,7 @@ TEST(Encoding, AllTypes) { ...@@ -69,7 +69,7 @@ TEST(Encoding, AllTypes) {
ASSERT_EQ(1u, builder.getSegmentsForOutput().size()); ASSERT_EQ(1u, builder.getSegmentsForOutput().size());
checkTestMessage(readMessageTrusted<TestAllTypes>(builder.getSegmentsForOutput()[0].begin())); checkTestMessage(readMessageUnchecked<TestAllTypes>(builder.getSegmentsForOutput()[0].begin()));
EXPECT_EQ(builder.getSegmentsForOutput()[0].size() - 1, // -1 for root pointer EXPECT_EQ(builder.getSegmentsForOutput()[0].size() - 1, // -1 for root pointer
reader.getRoot<TestAllTypes>().totalSizeInWords()); reader.getRoot<TestAllTypes>().totalSizeInWords());
...@@ -93,7 +93,7 @@ TEST(Encoding, Defaults) { ...@@ -93,7 +93,7 @@ TEST(Encoding, Defaults) {
SegmentArrayMessageReader reader(arrayPtr(segments, 1)); SegmentArrayMessageReader reader(arrayPtr(segments, 1));
checkTestMessage(reader.getRoot<TestDefaults>()); checkTestMessage(reader.getRoot<TestDefaults>());
checkTestMessage(readMessageTrusted<TestDefaults>(nullRoot.words)); checkTestMessage(readMessageUnchecked<TestDefaults>(nullRoot.words));
} }
TEST(Encoding, DefaultInitialization) { TEST(Encoding, DefaultInitialization) {
...@@ -133,7 +133,7 @@ TEST(Encoding, DefaultsFromEmptyMessage) { ...@@ -133,7 +133,7 @@ TEST(Encoding, DefaultsFromEmptyMessage) {
SegmentArrayMessageReader reader(arrayPtr(segments, 1)); SegmentArrayMessageReader reader(arrayPtr(segments, 1));
checkTestMessage(reader.getRoot<TestDefaults>()); checkTestMessage(reader.getRoot<TestDefaults>());
checkTestMessage(readMessageTrusted<TestDefaults>(emptyMessage.words)); checkTestMessage(readMessageUnchecked<TestDefaults>(emptyMessage.words));
} }
TEST(Encoding, GenericObjects) { TEST(Encoding, GenericObjects) {
......
...@@ -109,18 +109,18 @@ struct PointerHelpers<T, Kind::BLOB> { ...@@ -109,18 +109,18 @@ struct PointerHelpers<T, Kind::BLOB> {
#if defined(CAPNPROTO_PRIVATE) || defined(__CDT_PARSER__) #if defined(CAPNPROTO_PRIVATE) || defined(__CDT_PARSER__)
struct TrustedMessage { struct UncheckedMessage {
typedef const word* Reader; typedef const word* Reader;
}; };
template <> template <>
struct PointerHelpers<TrustedMessage> { struct PointerHelpers<UncheckedMessage> {
// Reads an Object field as a trusted message pointer. Requires that the containing message is // Reads an Object field as an unchecked message pointer. Requires that the containing message is
// itself trusted. This hack is currently private. It is used to locate default values within // itself unchecked. This hack is currently private. It is used to locate default values within
// encoded schemas. // encoded schemas.
static inline const word* get(StructReader reader, WirePointerCount index) { static inline const word* get(StructReader reader, WirePointerCount index) {
return reader.getTrustedPointer(index); return reader.getUncheckedPointer(index);
} }
}; };
...@@ -132,7 +132,7 @@ struct RawSchema { ...@@ -132,7 +132,7 @@ struct RawSchema {
// This is an internal structure which could change in the future. // This is an internal structure which could change in the future.
const word* encodedNode; const word* encodedNode;
// Encoded SchemaNode, readable via readMessageTrusted<schema::Node>(encodedNode). // Encoded SchemaNode, readable via readMessageUnchecked<schema::Node>(encodedNode).
const RawSchema* const* dependencies; const RawSchema* const* dependencies;
// Pointers to other types on which this one depends, sorted by ID. // Pointers to other types on which this one depends, sorted by ID.
......
...@@ -46,7 +46,7 @@ TEST(WireFormat, SimpleRawDataStruct) { ...@@ -46,7 +46,7 @@ TEST(WireFormat, SimpleRawDataStruct) {
0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef
}}; }};
StructReader reader = StructReader::readRootTrusted(data.words); StructReader reader = StructReader::readRootUnchecked(data.words);
EXPECT_EQ(0xefcdab8967452301ull, reader.getDataField<uint64_t>(0 * ELEMENTS)); EXPECT_EQ(0xefcdab8967452301ull, reader.getDataField<uint64_t>(0 * ELEMENTS));
EXPECT_EQ(0u, reader.getDataField<uint64_t>(1 * ELEMENTS)); EXPECT_EQ(0u, reader.getDataField<uint64_t>(1 * ELEMENTS));
...@@ -301,7 +301,7 @@ TEST(WireFormat, StructRoundTrip_OneSegment) { ...@@ -301,7 +301,7 @@ TEST(WireFormat, StructRoundTrip_OneSegment) {
checkStruct(builder); checkStruct(builder);
checkStruct(builder.asReader()); checkStruct(builder.asReader());
checkStruct(StructReader::readRootTrusted(segment->getStartPtr())); checkStruct(StructReader::readRootUnchecked(segment->getStartPtr()));
checkStruct(StructReader::readRoot(segment->getStartPtr(), segment, 4)); checkStruct(StructReader::readRoot(segment->getStartPtr(), segment, 4));
} }
......
...@@ -211,7 +211,7 @@ struct WireHelpers { ...@@ -211,7 +211,7 @@ struct WireHelpers {
static CAPNPROTO_ALWAYS_INLINE(bool boundsCheck( static CAPNPROTO_ALWAYS_INLINE(bool boundsCheck(
SegmentReader* segment, const word* start, const word* end)) { SegmentReader* segment, const word* start, const word* end)) {
// If segment is null, this is a trusted message, so all pointers have been checked already. // If segment is null, this is an unchecked message, so we don't do bounds checks.
return segment == nullptr || segment->containsInterval(start, end); return segment == nullptr || segment->containsInterval(start, end);
} }
...@@ -269,7 +269,7 @@ struct WireHelpers { ...@@ -269,7 +269,7 @@ struct WireHelpers {
static CAPNPROTO_ALWAYS_INLINE( static CAPNPROTO_ALWAYS_INLINE(
const word* followFars(const WirePointer*& ref, SegmentReader*& segment)) { const word* followFars(const WirePointer*& ref, SegmentReader*& segment)) {
// If the segment is null, this is a trusted message, so there are no FAR pointers. // If the segment is null, this is an unchecked message, so there are no FAR pointers.
if (segment != nullptr && ref->kind() == WirePointer::FAR) { if (segment != nullptr && ref->kind() == WirePointer::FAR) {
// Look up the segment containing the landing pad. // Look up the segment containing the landing pad.
segment = segment->getArena()->tryGetSegment(ref->farRef.segmentId.get()); segment = segment->getArena()->tryGetSegment(ref->farRef.segmentId.get());
...@@ -1901,7 +1901,7 @@ StructReader StructBuilder::asReader() const { ...@@ -1901,7 +1901,7 @@ StructReader StructBuilder::asReader() const {
// ======================================================================================= // =======================================================================================
// StructReader // StructReader
StructReader StructReader::readRootTrusted(const word* location) { StructReader StructReader::readRootUnchecked(const word* location) {
return WireHelpers::readStructPointer(nullptr, reinterpret_cast<const WirePointer*>(location), return WireHelpers::readStructPointer(nullptr, reinterpret_cast<const WirePointer*>(location),
nullptr, std::numeric_limits<int>::max()); nullptr, std::numeric_limits<int>::max());
} }
...@@ -1950,8 +1950,8 @@ ObjectReader StructReader::getObjectField( ...@@ -1950,8 +1950,8 @@ ObjectReader StructReader::getObjectField(
segment, pointers + ptrIndex, defaultValue, nestingLimit); segment, pointers + ptrIndex, defaultValue, nestingLimit);
} }
const word* StructReader::getTrustedPointer(WirePointerCount ptrIndex) const { const word* StructReader::getUncheckedPointer(WirePointerCount ptrIndex) const {
PRECOND(segment == nullptr, "getTrustedPointer() only allowed on trusted messages."); PRECOND(segment == nullptr, "getUncheckedPointer() only allowed on unchecked messages.");
return reinterpret_cast<const word*>(pointers + ptrIndex); return reinterpret_cast<const word*>(pointers + ptrIndex);
} }
......
...@@ -333,7 +333,7 @@ public: ...@@ -333,7 +333,7 @@ public:
StructBuilder getStructField(WirePointerCount ptrIndex, StructSize size, StructBuilder getStructField(WirePointerCount ptrIndex, StructSize size,
const word* defaultValue) const; const word* defaultValue) const;
// Gets the struct field at the given index in the pointer segment. If the field is not already // Gets the struct field at the given index in the pointer segment. If the field is not already
// initialized, it is initialized as a deep copy of the given default value (a trusted message), // initialized, it is initialized as a deep copy of the given default value (a flat message),
// or to the empty state if defaultValue is nullptr. // or to the empty state if defaultValue is nullptr.
ListBuilder initListField(WirePointerCount ptrIndex, FieldSize elementSize, ListBuilder initListField(WirePointerCount ptrIndex, FieldSize elementSize,
...@@ -350,14 +350,14 @@ public: ...@@ -350,14 +350,14 @@ public:
const word* defaultValue) const; const word* defaultValue) const;
// Gets the already-allocated list field for the given pointer index, ensuring that the list is // Gets the already-allocated list field for the given pointer index, ensuring that the list is
// suitable for storing non-struct elements of the given size. If the list is not already // suitable for storing non-struct elements of the given size. If the list is not already
// allocated, it is allocated as a deep copy of the given default value (a trusted message). If // allocated, it is allocated as a deep copy of the given default value (a flat message). If
// the default value is null, an empty list is used. // the default value is null, an empty list is used.
ListBuilder getStructListField(WirePointerCount ptrIndex, StructSize elementSize, ListBuilder getStructListField(WirePointerCount ptrIndex, StructSize elementSize,
const word* defaultValue) const; const word* defaultValue) const;
// Gets the already-allocated list field for the given pointer index, ensuring that the list // Gets the already-allocated list field for the given pointer index, ensuring that the list
// is suitable for storing struct elements of the given size. If the list is not // is suitable for storing struct elements of the given size. If the list is not
// already allocated, it is allocated as a deep copy of the given default value (a trusted // already allocated, it is allocated as a deep copy of the given default value (a flat
// message). If the default value is null, an empty list is used. // message). If the default value is null, an empty list is used.
template <typename T> template <typename T>
...@@ -418,7 +418,7 @@ public: ...@@ -418,7 +418,7 @@ public:
: segment(nullptr), data(nullptr), pointers(nullptr), dataSize(0), : segment(nullptr), data(nullptr), pointers(nullptr), dataSize(0),
pointerCount(0), bit0Offset(0), nestingLimit(0x7fffffff) {} pointerCount(0), bit0Offset(0), nestingLimit(0x7fffffff) {}
static StructReader readRootTrusted(const word* location); static StructReader readRootUnchecked(const word* location);
static StructReader readRoot(const word* location, SegmentReader* segment, int nestingLimit); static StructReader readRoot(const word* location, SegmentReader* segment, int nestingLimit);
inline BitCount getDataSectionSize() const { return dataSize; } inline BitCount getDataSectionSize() const { return dataSize; }
...@@ -439,7 +439,7 @@ public: ...@@ -439,7 +439,7 @@ public:
StructReader getStructField(WirePointerCount ptrIndex, const word* defaultValue) const; StructReader getStructField(WirePointerCount ptrIndex, const word* defaultValue) const;
// Get the struct field at the given index in the pointer segment, or the default value if not // Get the struct field at the given index in the pointer segment, or the default value if not
// initialized. defaultValue will be interpreted as a trusted message -- it must point at a // initialized. defaultValue will be interpreted as a flat message -- it must point at a
// struct pointer, which in turn points at the struct value. The default value is allowed to // struct pointer, which in turn points at the struct value. The default value is allowed to
// be null, in which case an empty struct is used. // be null, in which case an empty struct is used.
...@@ -456,10 +456,10 @@ public: ...@@ -456,10 +456,10 @@ public:
ObjectReader getObjectField(WirePointerCount ptrIndex, const word* defaultValue) const; ObjectReader getObjectField(WirePointerCount ptrIndex, const word* defaultValue) const;
// Read a pointer of arbitrary type. // Read a pointer of arbitrary type.
const word* getTrustedPointer(WirePointerCount ptrIndex) const; const word* getUncheckedPointer(WirePointerCount ptrIndex) const;
// If this is a trusted message, get a word* pointing at the location of the pointer. This // If this is an unchecked message, get a word* pointing at the location of the pointer. This
// word* can actually be passed to readTrusted() to read the designated sub-object later. If // word* can actually be passed to readUnchecked() to read the designated sub-object later. If
// this isn't a trusted message, throws an exception. // this isn't an unchecked message, throws an exception.
bool isPointerFieldNull(WirePointerCount ptrIndex) const; bool isPointerFieldNull(WirePointerCount ptrIndex) const;
......
...@@ -175,27 +175,32 @@ private: ...@@ -175,27 +175,32 @@ private:
}; };
template <typename RootType> template <typename RootType>
static typename RootType::Reader readMessageTrusted(const word* data); static typename RootType::Reader readMessageUnchecked(const word* data);
// IF THE INPUT IS INVALID, THIS MAY CRASH, CORRUPT MEMORY, CREATE A SECURITY HOLE IN YOUR APP, // IF THE INPUT IS INVALID, THIS MAY CRASH, CORRUPT MEMORY, CREATE A SECURITY HOLE IN YOUR APP,
// MURDER YOUR FIRST-BORN CHILD, AND/OR BRING ABOUT ETERNAL DAMNATION ON ALL OF HUMANITY. DO NOT // MURDER YOUR FIRST-BORN CHILD, AND/OR BRING ABOUT ETERNAL DAMNATION ON ALL OF HUMANITY. DO NOT
// USE UNLESS YOU UNDERSTAND THE CONSEQUENCES. // USE UNLESS YOU UNDERSTAND THE CONSEQUENCES.
// //
// Given a pointer to a known-valid message located in a single contiguous memory segment, // Given a pointer to a known-valid message located in a single contiguous memory segment,
// returns a reader for that message. No bounds-checking will be done while tranversing this // returns a reader for that message. No bounds-checking will be done while traversing this
// message. Use this only if you are absolutely sure that the input data is a valid message // message. Use this only if you have already verified that all pointers are valid and in-bounds,
// created by your own system. Never use this to read messages received from others. // and there are no far pointers in the message.
// //
// To create a trusted message, build a message using a MallocAllocator whose preferred segment // To create a message that can be passed to this function, build a message using a MallocAllocator
// size is larger than the message size. This guarantees that the message will be allocated as a // whose preferred segment size is larger than the message size. This guarantees that the message
// single segment, meaning getSegmentsForOutput() returns a single word array. That word array // will be allocated as a single segment, meaning getSegmentsForOutput() returns a single word
// is your message; you may pass a pointer to its first word into readMessageTrusted() to read the // array. That word array is your message; you may pass a pointer to its first word into
// message. // readMessageUnchecked() to read the message.
// //
// This can be particularly handy for embedding messages in generated code: you can // This can be particularly handy for embedding messages in generated code: you can
// embed the raw bytes (using AlignedData) then make a Reader for it using this. This is the way // embed the raw bytes (using AlignedData) then make a Reader for it using this. This is the way
// default values are embedded in code generated by the Cap'n Proto compiler. E.g., if you have // default values are embedded in code generated by the Cap'n Proto compiler. E.g., if you have
// a message MyMessage, you can read its default value like so: // a message MyMessage, you can read its default value like so:
// MyMessage::Reader reader = Message<MyMessage>::readMessageTrusted(MyMessage::DEFAULT.words); // MyMessage::Reader reader = Message<MyMessage>::readMessageUnchecked(MyMessage::DEFAULT.words);
//
// To sanitize a message from an untrusted source such that it can be safely passed to
// readMessageUnchecked(), construct a MessageBuilder whose first segment is large enough to store
// the message, and then use MessageBuilder::setRoot() to copy the message in. The process of
// copying the message implicitly validates all pointers.
template <typename Type> template <typename Type>
static typename Type::Reader defaultValue(); static typename Type::Reader defaultValue();
...@@ -324,8 +329,8 @@ inline typename RootType::Builder MessageBuilder::getRoot() { ...@@ -324,8 +329,8 @@ inline typename RootType::Builder MessageBuilder::getRoot() {
} }
template <typename RootType> template <typename RootType>
typename RootType::Reader readMessageTrusted(const word* data) { typename RootType::Reader readMessageUnchecked(const word* data) {
return typename RootType::Reader(internal::StructReader::readRootTrusted(data)); return typename RootType::Reader(internal::StructReader::readRootUnchecked(data));
} }
template <typename Type> template <typename Type>
......
...@@ -29,7 +29,7 @@ ...@@ -29,7 +29,7 @@
namespace capnproto { namespace capnproto {
schema::Node::Reader Schema::getProto() const { schema::Node::Reader Schema::getProto() const {
return readMessageTrusted<schema::Node>(raw->encodedNode); return readMessageUnchecked<schema::Node>(raw->encodedNode);
} }
Schema Schema::getDependency(uint64_t id) const { Schema Schema::getDependency(uint64_t id) const {
......
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