Skip to content

Commit 0950d03

Browse files
Fix buffer overrun if header specifies more vertices than the file really has (#53)
1 parent ef1f8d5 commit 0950d03

File tree

1 file changed

+26
-14
lines changed

1 file changed

+26
-14
lines changed

source/tinyply.h

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -279,8 +279,8 @@ struct PlyFile::PlyFileImpl
279279
const std::vector<std::string> propertyKeys,
280280
const Type type, const size_t count, const uint8_t * data, const Type listType, const size_t listCount);
281281

282-
size_t read_property_binary(const size_t & stride, void * dest, size_t & destOffset, std::istream & is) noexcept;
283-
size_t read_property_ascii(const Type & t, const size_t & stride, void * dest, size_t & destOffset, std::istream & is);
282+
size_t read_property_binary(const size_t & stride, void * dest, size_t & destOffset, size_t destSize, std::istream & is);
283+
size_t read_property_ascii(const Type & t, const size_t & stride, void * dest, size_t & destOffset, size_t destSize, std::istream & is);
284284

285285
std::vector<std::vector<PropertyLookup>> make_property_lookup_table();
286286

@@ -429,15 +429,25 @@ void PlyFile::PlyFileImpl::read_header_property(std::istream & is)
429429
elements.back().properties.emplace_back(is);
430430
}
431431

432-
size_t PlyFile::PlyFileImpl::read_property_binary(const size_t & stride, void * dest, size_t & destOffset, std::istream & is) noexcept
432+
size_t PlyFile::PlyFileImpl::read_property_binary(const size_t & stride, void * dest, size_t & destOffset, size_t destSize, std::istream & is)
433433
{
434+
if (destOffset + stride > destSize)
435+
{
436+
throw std::runtime_error("unexpected EOF. malformed file?");
437+
}
438+
434439
destOffset += stride;
435440
is.read((char*)dest, stride);
436441
return stride;
437442
}
438443

439-
size_t PlyFile::PlyFileImpl::read_property_ascii(const Type & t, const size_t & stride, void * dest, size_t & destOffset, std::istream & is)
444+
size_t PlyFile::PlyFileImpl::read_property_ascii(const Type & t, const size_t & stride, void * dest, size_t & destOffset, size_t destSize, std::istream & is)
440445
{
446+
if (destOffset + stride > destSize)
447+
{
448+
throw std::runtime_error("unexpected EOF. malformed file?");
449+
}
450+
441451
destOffset += stride;
442452
switch (t)
443453
{
@@ -810,7 +820,7 @@ void PlyFile::PlyFileImpl::add_properties_to_element(const std::string & element
810820

811821
void PlyFile::PlyFileImpl::parse_data(std::istream & is, bool firstPass)
812822
{
813-
std::function<void(PropertyLookup & f, const PlyProperty & p, uint8_t * dest, size_t & destOffset, std::istream & is)> read;
823+
std::function<void(PropertyLookup & f, const PlyProperty & p, uint8_t * dest, size_t & destOffset, size_t destSize, std::istream & is)> read;
814824
std::function<size_t(PropertyLookup & f, const PlyProperty & p, std::istream & is)> skip;
815825

816826
const auto start = is.tellg();
@@ -846,14 +856,14 @@ void PlyFile::PlyFileImpl::parse_data(std::istream & is, bool firstPass)
846856

847857
if (isBinary)
848858
{
849-
read = [this, &listSize, &dummyCount, &read_list_binary](PropertyLookup & f, const PlyProperty & p, uint8_t * dest, size_t & destOffset, std::istream & _is) noexcept
859+
read = [this, &listSize, &dummyCount, &read_list_binary](PropertyLookup & f, const PlyProperty & p, uint8_t * dest, size_t & destOffset, size_t destSize, std::istream & _is)
850860
{
851861
if (!p.isList)
852862
{
853-
return read_property_binary(f.prop_stride, dest + destOffset, destOffset, _is);
863+
return read_property_binary(f.prop_stride, dest + destOffset, destOffset, destSize, _is);
854864
}
855865
read_list_binary(p.listType, &listSize, dummyCount, f.list_stride, _is); // the list size
856-
return read_property_binary(f.prop_stride * listSize, dest + destOffset, destOffset, _is); // properties in list
866+
return read_property_binary(f.prop_stride * listSize, dest + destOffset, destOffset, destSize, _is); // properties in list
857867
};
858868
skip = [this, &listSize, &dummyCount, &read_list_binary](PropertyLookup & f, const PlyProperty & p, std::istream & _is) noexcept
859869
{
@@ -870,18 +880,18 @@ void PlyFile::PlyFileImpl::parse_data(std::istream & is, bool firstPass)
870880
}
871881
else
872882
{
873-
read = [this, &listSize, &dummyCount](PropertyLookup & f, const PlyProperty & p, uint8_t * dest, size_t & destOffset, std::istream & _is) noexcept
883+
read = [this, &listSize, &dummyCount](PropertyLookup & f, const PlyProperty & p, uint8_t * dest, size_t & destOffset, size_t destSize, std::istream & _is)
874884
{
875885
if (!p.isList)
876886
{
877-
read_property_ascii(p.propertyType, f.prop_stride, dest + destOffset, destOffset, _is);
887+
read_property_ascii(p.propertyType, f.prop_stride, dest + destOffset, destOffset, destSize, _is);
878888
}
879889
else
880890
{
881-
read_property_ascii(p.listType, f.list_stride, &listSize, dummyCount, _is); // the list size
891+
read_property_ascii(p.listType, f.list_stride, &listSize, dummyCount, sizeof(listSize), _is); // the list size
882892
for (size_t i = 0; i < listSize; ++i)
883893
{
884-
read_property_ascii(p.propertyType, f.prop_stride, dest + destOffset, destOffset, _is);
894+
read_property_ascii(p.propertyType, f.prop_stride, dest + destOffset, destOffset, destOffset, _is);
885895
}
886896
}
887897
};
@@ -890,7 +900,8 @@ void PlyFile::PlyFileImpl::parse_data(std::istream & is, bool firstPass)
890900
skip_ascii_buffer.clear();
891901
if (p.isList)
892902
{
893-
read_property_ascii(p.listType, f.list_stride, &listSize, dummyCount, _is); // the list size (does not count for memory alloc)
903+
dummyCount = 0;
904+
read_property_ascii(p.listType, f.list_stride, &listSize, dummyCount, sizeof(listSize), _is); // the list size (does not count for memory alloc)
894905
for (size_t i = 0; i < listSize; ++i) _is >> skip_ascii_buffer; // properties in list
895906
return listSize * f.prop_stride;
896907
}
@@ -929,7 +940,8 @@ void PlyFile::PlyFileImpl::parse_data(std::istream & is, bool firstPass)
929940
}
930941
else
931942
{
932-
read(lookup, property, helper->data->buffer.get(), helper->cursor->byteOffset, is);
943+
const size_t destSize = helper->data->buffer.size_bytes();
944+
read(lookup, property, helper->data->buffer.get(), helper->cursor->byteOffset, destSize, is);
933945
}
934946
}
935947
else

0 commit comments

Comments
 (0)