Skip to content

Commit

Permalink
- Protect against buffer overwrite
Browse files Browse the repository at this point in the history
- Assert array element size meets expectations
- Use std::unique_ptr to avoid memory leak
  • Loading branch information
jasonmreding committed Jan 31, 2025
1 parent 44cf697 commit 2381e43
Show file tree
Hide file tree
Showing 4 changed files with 15 additions and 10 deletions.
1 change: 1 addition & 0 deletions src/lv_interop.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ namespace grpc_labview
T* bytes()
{
static_assert(!std::is_class<T>::value, "T must not be a struct/class type.");
static_assert(sizeof(T) <= 8, "Need to revisit logic if we ever have element size larger than 8 bytes.");
return (T*)(rawBytes);
}
};
Expand Down
8 changes: 4 additions & 4 deletions src/message_metadata.cc
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace grpc_labview
//---------------------------------------------------------------------
// Functions for calculating whether an element is considered a well known type.
//---------------------------------------------------------------------
static wellknown::Types IsWellKnownDouble2DArray(const MessageElementMetadata& metadata)
static wellknown::Types CalculateDouble2DArrayWellKnownTypeEnum(const MessageElementMetadata& metadata)
{
if (!metadata.isRepeated)
{
Expand All @@ -22,7 +22,7 @@ namespace grpc_labview
//---------------------------------------------------------------------
std::map<const std::string, wellknown::Types(*)(const MessageElementMetadata&)> MessageElementMetadata::_wellKnownTypeFunctionMap =
{
{ wellknown::Double2DArray::GetMessageName(), IsWellKnownDouble2DArray}
{ wellknown::Double2DArray::GetMessageName(), CalculateDouble2DArrayWellKnownTypeEnum}
};

//---------------------------------------------------------------------
Expand Down Expand Up @@ -85,7 +85,7 @@ namespace grpc_labview
if (lvMetadata->elements != nullptr)
{
// byteAlignment for LVMessageElementMetadata would be the size of its largest element which is a LStrHandle
auto lvElement = (LVMessageElementMetadata*)(*lvMetadata->elements)->bytes(0, sizeof(LStrHandle));
auto lvElement = (LVMessageElementMetadata*)(*lvMetadata->elements)->bytes(0, alignof(LVMessageElementMetadata));
auto metadataVersion = 1;
InitializeElements(metadataOwner, lvElement, (*lvMetadata->elements)->cnt, metadataVersion);
}
Expand All @@ -104,7 +104,7 @@ namespace grpc_labview
if (lvMetadata->elements != nullptr)
{
// byteAlignment for LVMessageElementMetadata would be the size of its largest element which is a LStrHandle
auto lvElement = (LVMessageElementMetadata*)(*lvMetadata->elements)->bytes(0, sizeof(LStrHandle));
auto lvElement = (LVMessageElementMetadata*)(*lvMetadata->elements)->bytes(0, alignof(LVMessageElementMetadata));
auto metadataVersion = 2;
InitializeElements(metadataOwner, lvElement, (*lvMetadata->elements)->cnt, metadataVersion);
}
Expand Down
14 changes: 9 additions & 5 deletions src/well_known_types.cc
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ namespace grpc_labview
if (_instance == nullptr)
{
_instance = new MetadataOwner();
auto owner = _instance->_owner;
owner->RegisterMetadata(Double2DArray::GetMetadata(owner));
auto& owner = _instance->_owner;
owner->RegisterMetadata(Double2DArray::GetMetadata(owner.get()));
owner->FinalizeMetadata();
}
return *_instance;
Expand All @@ -31,7 +31,7 @@ namespace grpc_labview
//---------------------------------------------------------------------
MetadataOwner::MetadataOwner()
{
_owner = new MessageElementMetadataOwner();
_owner = std::make_unique<MessageElementMetadataOwner>();
}

//---------------------------------------------------------------------
Expand Down Expand Up @@ -141,8 +141,12 @@ namespace grpc_labview
auto array = *(LV2DArrayHandle*)start;
(*array)->dimensionSizes[0] = rows;
(*array)->dimensionSizes[1] = columns;
auto byteCount = elementCount * sizeof(double);
memcpy((*array)->bytes<double>(), dataValue->_value.data(), byteCount);
// Protect against a malformed message where the amount of data sent doesn't match the dimension sizes.
// LV will automatically pad/handle writing less data than was allocated to the array so we just need
// to make sure we don't write more data than was allocated to the array.
auto lvByteCount = elementCount * sizeof(double);
auto protobufByteCount = dataValue->_value.size() * sizeof(double);
memcpy((*array)->bytes<double>(), dataValue->_value.data(), std::min(lvByteCount, protobufByteCount));
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/well_known_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ namespace grpc_labview
private:
static MetadataOwner* _instance;
static std::mutex _mutex;
MessageElementMetadataOwner* _owner;
std::unique_ptr<MessageElementMetadataOwner> _owner;

MetadataOwner();
};
Expand Down

0 comments on commit 2381e43

Please sign in to comment.