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(
ListSchema::of(elementType, member.getContainingStruct()),
reader.getListField(field.getOffset() * POINTERS,
elementSizeFor(elementType.getBody().which()),
dval.getListValue<internal::TrustedMessage>())));
dval.getListValue<internal::UncheckedMessage>())));
}
case schema::Type::Body::STRUCT_TYPE: {
return DynamicValue::Reader(DynamicStruct::Reader(
member.getContainingStruct().getDependency(type.getStructType()).asStruct(),
reader.getStructField(field.getOffset() * POINTERS,
dval.getStructValue<internal::TrustedMessage>())));
dval.getStructValue<internal::UncheckedMessage>())));
}
case schema::Type::Body::OBJECT_TYPE: {
return DynamicValue::Reader(DynamicObject(
reader.getObjectField(field.getOffset() * POINTERS,
dval.getObjectValue<internal::TrustedMessage>())));
dval.getObjectValue<internal::UncheckedMessage>())));
}
case schema::Type::Body::INTERFACE_TYPE:
......@@ -805,12 +805,12 @@ DynamicValue::Builder DynamicStruct::Builder::getImpl(
return DynamicValue::Builder(DynamicList::Builder(listType,
builder.getStructListField(field.getOffset() * POINTERS,
structSizeFromSchema(listType.getStructElementType()),
dval.getListValue<internal::TrustedMessage>())));
dval.getListValue<internal::UncheckedMessage>())));
} else {
return DynamicValue::Builder(DynamicList::Builder(listType,
builder.getListField(field.getOffset() * POINTERS,
elementSizeFor(listType.whichElementType()),
dval.getListValue<internal::TrustedMessage>())));
dval.getListValue<internal::UncheckedMessage>())));
}
}
......@@ -822,14 +822,14 @@ DynamicValue::Builder DynamicStruct::Builder::getImpl(
builder.getStructField(
field.getOffset() * POINTERS,
structSizeFromSchema(structSchema),
dval.getStructValue<internal::TrustedMessage>())));
dval.getStructValue<internal::UncheckedMessage>())));
}
case schema::Type::Body::OBJECT_TYPE: {
return DynamicValue::Builder(DynamicObject(
builder.asReader().getObjectField(
field.getOffset() * POINTERS,
dval.getObjectValue<internal::TrustedMessage>())));
dval.getObjectValue<internal::UncheckedMessage>())));
}
case schema::Type::Body::INTERFACE_TYPE:
......
......@@ -69,7 +69,7 @@ TEST(Encoding, AllTypes) {
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
reader.getRoot<TestAllTypes>().totalSizeInWords());
......@@ -93,7 +93,7 @@ TEST(Encoding, Defaults) {
SegmentArrayMessageReader reader(arrayPtr(segments, 1));
checkTestMessage(reader.getRoot<TestDefaults>());
checkTestMessage(readMessageTrusted<TestDefaults>(nullRoot.words));
checkTestMessage(readMessageUnchecked<TestDefaults>(nullRoot.words));
}
TEST(Encoding, DefaultInitialization) {
......@@ -133,7 +133,7 @@ TEST(Encoding, DefaultsFromEmptyMessage) {
SegmentArrayMessageReader reader(arrayPtr(segments, 1));
checkTestMessage(reader.getRoot<TestDefaults>());
checkTestMessage(readMessageTrusted<TestDefaults>(emptyMessage.words));
checkTestMessage(readMessageUnchecked<TestDefaults>(emptyMessage.words));
}
TEST(Encoding, GenericObjects) {
......
......@@ -109,18 +109,18 @@ struct PointerHelpers<T, Kind::BLOB> {
#if defined(CAPNPROTO_PRIVATE) || defined(__CDT_PARSER__)
struct TrustedMessage {
struct UncheckedMessage {
typedef const word* Reader;
};
template <>
struct PointerHelpers<TrustedMessage> {
// Reads an Object field as a trusted message pointer. Requires that the containing message is
// itself trusted. This hack is currently private. It is used to locate default values within
struct PointerHelpers<UncheckedMessage> {
// Reads an Object field as an unchecked message pointer. Requires that the containing message is
// itself unchecked. This hack is currently private. It is used to locate default values within
// encoded schemas.
static inline const word* get(StructReader reader, WirePointerCount index) {
return reader.getTrustedPointer(index);
return reader.getUncheckedPointer(index);
}
};
......@@ -132,7 +132,7 @@ struct RawSchema {
// This is an internal structure which could change in the future.
const word* encodedNode;
// Encoded SchemaNode, readable via readMessageTrusted<schema::Node>(encodedNode).
// Encoded SchemaNode, readable via readMessageUnchecked<schema::Node>(encodedNode).
const RawSchema* const* dependencies;
// Pointers to other types on which this one depends, sorted by ID.
......
......@@ -46,7 +46,7 @@ TEST(WireFormat, SimpleRawDataStruct) {
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(0u, reader.getDataField<uint64_t>(1 * ELEMENTS));
......@@ -301,7 +301,7 @@ TEST(WireFormat, StructRoundTrip_OneSegment) {
checkStruct(builder);
checkStruct(builder.asReader());
checkStruct(StructReader::readRootTrusted(segment->getStartPtr()));
checkStruct(StructReader::readRootUnchecked(segment->getStartPtr()));
checkStruct(StructReader::readRoot(segment->getStartPtr(), segment, 4));
}
......
......@@ -211,7 +211,7 @@ struct WireHelpers {
static CAPNPROTO_ALWAYS_INLINE(bool boundsCheck(
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);
}
......@@ -269,7 +269,7 @@ struct WireHelpers {
static CAPNPROTO_ALWAYS_INLINE(
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) {
// Look up the segment containing the landing pad.
segment = segment->getArena()->tryGetSegment(ref->farRef.segmentId.get());
......@@ -1901,7 +1901,7 @@ StructReader StructBuilder::asReader() const {
// =======================================================================================
// StructReader
StructReader StructReader::readRootTrusted(const word* location) {
StructReader StructReader::readRootUnchecked(const word* location) {
return WireHelpers::readStructPointer(nullptr, reinterpret_cast<const WirePointer*>(location),
nullptr, std::numeric_limits<int>::max());
}
......@@ -1950,8 +1950,8 @@ ObjectReader StructReader::getObjectField(
segment, pointers + ptrIndex, defaultValue, nestingLimit);
}
const word* StructReader::getTrustedPointer(WirePointerCount ptrIndex) const {
PRECOND(segment == nullptr, "getTrustedPointer() only allowed on trusted messages.");
const word* StructReader::getUncheckedPointer(WirePointerCount ptrIndex) const {
PRECOND(segment == nullptr, "getUncheckedPointer() only allowed on unchecked messages.");
return reinterpret_cast<const word*>(pointers + ptrIndex);
}
......
......@@ -333,7 +333,7 @@ public:
StructBuilder getStructField(WirePointerCount ptrIndex, StructSize size,
const word* defaultValue) const;
// 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.
ListBuilder initListField(WirePointerCount ptrIndex, FieldSize elementSize,
......@@ -350,14 +350,14 @@ public:
const word* defaultValue) const;
// 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
// 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.
ListBuilder getStructListField(WirePointerCount ptrIndex, StructSize elementSize,
const word* defaultValue) const;
// 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
// 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.
template <typename T>
......@@ -418,7 +418,7 @@ public:
: segment(nullptr), data(nullptr), pointers(nullptr), dataSize(0),
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);
inline BitCount getDataSectionSize() const { return dataSize; }
......@@ -439,7 +439,7 @@ public:
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
// 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
// be null, in which case an empty struct is used.
......@@ -456,10 +456,10 @@ public:
ObjectReader getObjectField(WirePointerCount ptrIndex, const word* defaultValue) const;
// Read a pointer of arbitrary type.
const word* getTrustedPointer(WirePointerCount ptrIndex) const;
// If this is a trusted 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
// this isn't a trusted message, throws an exception.
const word* getUncheckedPointer(WirePointerCount ptrIndex) const;
// If this is an unchecked message, get a word* pointing at the location of the pointer. This
// word* can actually be passed to readUnchecked() to read the designated sub-object later. If
// this isn't an unchecked message, throws an exception.
bool isPointerFieldNull(WirePointerCount ptrIndex) const;
......
......@@ -175,27 +175,32 @@ private:
};
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,
// MURDER YOUR FIRST-BORN CHILD, AND/OR BRING ABOUT ETERNAL DAMNATION ON ALL OF HUMANITY. DO NOT
// USE UNLESS YOU UNDERSTAND THE CONSEQUENCES.
//
// 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
// message. Use this only if you are absolutely sure that the input data is a valid message
// created by your own system. Never use this to read messages received from others.
// returns a reader for that message. No bounds-checking will be done while traversing this
// message. Use this only if you have already verified that all pointers are valid and in-bounds,
// and there are no far pointers in the message.
//
// To create a trusted message, build a message using a MallocAllocator whose preferred segment
// size is larger than the message size. This guarantees that the message will be allocated as a
// single segment, meaning getSegmentsForOutput() returns a single word array. That word array
// is your message; you may pass a pointer to its first word into readMessageTrusted() to read the
// message.
// To create a message that can be passed to this function, build a message using a MallocAllocator
// whose preferred segment size is larger than the message size. This guarantees that the message
// will be allocated as a single segment, meaning getSegmentsForOutput() returns a single word
// array. That word array is your message; you may pass a pointer to its first word into
// readMessageUnchecked() to read the message.
//
// 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
// 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:
// 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>
static typename Type::Reader defaultValue();
......@@ -324,8 +329,8 @@ inline typename RootType::Builder MessageBuilder::getRoot() {
}
template <typename RootType>
typename RootType::Reader readMessageTrusted(const word* data) {
return typename RootType::Reader(internal::StructReader::readRootTrusted(data));
typename RootType::Reader readMessageUnchecked(const word* data) {
return typename RootType::Reader(internal::StructReader::readRootUnchecked(data));
}
template <typename Type>
......
......@@ -29,7 +29,7 @@
namespace capnproto {
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 {
......
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