diff options
Diffstat (limited to 'cpp/src/sfntly/data')
-rw-r--r-- | cpp/src/sfntly/data/byte_array.cc | 2 | ||||
-rw-r--r-- | cpp/src/sfntly/data/font_data.cc | 44 | ||||
-rw-r--r-- | cpp/src/sfntly/data/font_data.h | 15 | ||||
-rw-r--r-- | cpp/src/sfntly/data/readable_font_data.cc | 131 | ||||
-rw-r--r-- | cpp/src/sfntly/data/readable_font_data.h | 25 | ||||
-rw-r--r-- | cpp/src/sfntly/data/writable_font_data.cc | 9 |
6 files changed, 149 insertions, 77 deletions
diff --git a/cpp/src/sfntly/data/byte_array.cc b/cpp/src/sfntly/data/byte_array.cc index 915a40c..57f9eed 100644 --- a/cpp/src/sfntly/data/byte_array.cc +++ b/cpp/src/sfntly/data/byte_array.cc @@ -35,6 +35,8 @@ int32_t ByteArray::SetFilledLength(int32_t filled_length) { } int32_t ByteArray::Get(int32_t index) { + if (index < 0 || index >= Length()) + return -1; return InternalGet(index) & 0xff; } diff --git a/cpp/src/sfntly/data/font_data.cc b/cpp/src/sfntly/data/font_data.cc index d2b95ea..95bee3e 100644 --- a/cpp/src/sfntly/data/font_data.cc +++ b/cpp/src/sfntly/data/font_data.cc @@ -14,11 +14,13 @@ * limitations under the License. */ -#include <limits.h> +#include "sfntly/data/font_data.h" + #include <algorithm> #include <functional> +#include <limits> -#include "sfntly/data/font_data.h" +#include "sfntly/port/logging.h" namespace sfntly { @@ -26,21 +28,29 @@ int32_t FontData::Size() const { return std::min<int32_t>(array_->Size() - bound_offset_, bound_length_); } -bool FontData::Bound(int32_t offset, int32_t length) { - if (offset + length > Size() || offset < 0 || length < 0) - return false; - - bound_offset_ += offset; +void FontData::Bound(int32_t offset, int32_t length) { + // Inputs should not be negative. + CHECK(offset >= 0); + CHECK(length >= 0); + + // Check to make sure |bound_offset_| will not overflow. + CHECK(bound_offset_ <= std::numeric_limits<int32_t>::max() - offset); + const int32_t new_offset = bound_offset_ + offset; + + if (length == GROWABLE_SIZE) { + // When |length| has the special value of GROWABLE_SIZE, it means the size + // should not have any artificial limits, thus it is just the underlying + // |array_|'s size. Just make sure |new_offset| is still within bounds. + CHECK(new_offset <= array_->Size()); + } else { + // When |length| has any other value, |new_offset| + |length| points to the + // end of the array. Make sure that is within bounds, but use subtraction to + // avoid an integer overflow. + CHECK(new_offset <= array_->Size() - length); + } + + bound_offset_ = new_offset; bound_length_ = length; - return true; -} - -bool FontData::Bound(int32_t offset) { -if (offset > Size() || offset < 0) - return false; - - bound_offset_ += offset; - return true; } int32_t FontData::Length() const { @@ -60,7 +70,7 @@ FontData::FontData(FontData* data, int32_t offset) { Init(data->array_); Bound(data->bound_offset_ + offset, (data->bound_length_ == GROWABLE_SIZE) - ? GROWABLE_SIZE : data->bound_length_ - offset); + ? GROWABLE_SIZE : data->bound_length_ - offset); } FontData::~FontData() {} diff --git a/cpp/src/sfntly/data/font_data.h b/cpp/src/sfntly/data/font_data.h index d02e8b7..e0e7e79 100644 --- a/cpp/src/sfntly/data/font_data.h +++ b/cpp/src/sfntly/data/font_data.h @@ -19,11 +19,9 @@ #include <limits.h> -#include <vector> - -#include "sfntly/port/type.h" #include "sfntly/data/byte_array.h" #include "sfntly/port/refcount.h" +#include "sfntly/port/type.h" namespace sfntly { @@ -60,16 +58,7 @@ class FontData : virtual public RefCount { // visible within the bounds set. // @param offset the start of the new bounds // @param length the number of bytes in the bounded array - // @return true if the bounding range was successful; false otherwise - virtual bool Bound(int32_t offset, int32_t length); - - // Sets limits on the size of the FontData. This is a offset bound only so if - // the FontData is writable and growable then there is no limit to that growth - // from the bounding operation. - // @param offset the start of the new bounds which must be within the current - // size of the FontData - // @return true if the bounding range was successful; false otherwise - virtual bool Bound(int32_t offset); + virtual void Bound(int32_t offset, int32_t length); // Makes a slice of this FontData. The returned slice will share the data with // the original <code>FontData</code>. diff --git a/cpp/src/sfntly/data/readable_font_data.cc b/cpp/src/sfntly/data/readable_font_data.cc index 06d783f..07a0db6 100644 --- a/cpp/src/sfntly/data/readable_font_data.cc +++ b/cpp/src/sfntly/data/readable_font_data.cc @@ -18,6 +18,8 @@ #include <stdio.h> +#include <limits> + #include "sfntly/data/memory_byte_array.h" #include "sfntly/data/writable_font_data.h" #include "sfntly/port/exception_type.h" @@ -59,23 +61,25 @@ void ReadableFontData::SetCheckSumRanges(const IntegerList& ranges) { int32_t ReadableFontData::ReadUByte(int32_t index) { int32_t b = array_->Get(BoundOffset(index)); -#if !defined (SFNTLY_NO_EXCEPTION) if (b < 0) { +#if !defined (SFNTLY_NO_EXCEPTION) throw IndexOutOfBoundException( "Index attempted to be read from is out of bounds", index); - } #endif + return kInvalidUnsigned; + } return b; } int32_t ReadableFontData::ReadByte(int32_t index) { int32_t b = array_->Get(BoundOffset(index)); -#if !defined (SFNTLY_NO_EXCEPTION) if (b < 0) { +#if !defined (SFNTLY_NO_EXCEPTION) throw IndexOutOfBoundException( "Index attempted to be read from is out of bounds", index); - } #endif + return kInvalidByte; + } return (b << 24) >> 24; } @@ -91,24 +95,54 @@ int32_t ReadableFontData::ReadChar(int32_t index) { } int32_t ReadableFontData::ReadUShort(int32_t index) { - return 0xffff & (ReadUByte(index) << 8 | ReadUByte(index + 1)); + int32_t b1 = ReadUByte(index); + if (b1 < 0) + return kInvalidUnsigned; + int32_t b2 = ReadUByte(index + 1); + if (b2 < 0) + return kInvalidUnsigned; + return 0xffff & (b1 << 8 | b2); } int32_t ReadableFontData::ReadShort(int32_t index) { - return ((ReadByte(index) << 8 | ReadUByte(index + 1)) << 16) >> 16; + int32_t b1 = ReadByte(index); + if (b1 == kInvalidByte) + return kInvalidShort; + int32_t b2 = ReadUByte(index + 1); + if (b2 < 0) + return kInvalidShort; + + uint32_t result = static_cast<uint32_t>(b1) << 8 | b2; + return static_cast<int32_t>(result << 16) >> 16; } int32_t ReadableFontData::ReadUInt24(int32_t index) { - return 0xffffff & (ReadUByte(index) << 16 | - ReadUByte(index + 1) << 8 | - ReadUByte(index + 2)); + int32_t b1 = ReadUByte(index); + if (b1 < 0) + return kInvalidUnsigned; + int32_t b2 = ReadUByte(index + 1); + if (b2 < 0) + return kInvalidUnsigned; + int32_t b3 = ReadUByte(index + 2); + if (b3 < 0) + return kInvalidUnsigned; + return 0xffffff & (b1 << 16 | b2 << 8 | b3); } int64_t ReadableFontData::ReadULong(int32_t index) { - return 0xffffffffL & (ReadUByte(index) << 24 | - ReadUByte(index + 1) << 16 | - ReadUByte(index + 2) << 8 | - ReadUByte(index + 3)); + int32_t b1 = ReadUByte(index); + if (b1 < 0) + return kInvalidUnsigned; + int32_t b2 = ReadUByte(index + 1); + if (b2 < 0) + return kInvalidUnsigned; + int32_t b3 = ReadUByte(index + 2); + if (b3 < 0) + return kInvalidUnsigned; + int32_t b4 = ReadUByte(index + 3); + if (b4 < 0) + return kInvalidUnsigned; + return 0xffffffffL & (b1 << 24 | b2 << 16 | b3 << 8 | b4); } int32_t ReadableFontData::ReadULongAsInt(int32_t index) { @@ -122,17 +156,35 @@ int32_t ReadableFontData::ReadULongAsInt(int32_t index) { } int64_t ReadableFontData::ReadULongLE(int32_t index) { - return 0xffffffffL & (ReadUByte(index) | - ReadUByte(index + 1) << 8 | - ReadUByte(index + 2) << 16 | - ReadUByte(index + 3) << 24); + int32_t b1 = ReadUByte(index); + if (b1 < 0) + return kInvalidUnsigned; + int32_t b2 = ReadUByte(index + 1); + if (b2 < 0) + return kInvalidUnsigned; + int32_t b3 = ReadUByte(index + 2); + if (b3 < 0) + return kInvalidUnsigned; + int32_t b4 = ReadUByte(index + 3); + if (b4 < 0) + return kInvalidUnsigned; + return 0xffffffffL & (b1 | b2 << 8 | b3 << 16 | b4 << 24); } int32_t ReadableFontData::ReadLong(int32_t index) { - return ReadByte(index) << 24 | - ReadUByte(index + 1) << 16 | - ReadUByte(index + 2) << 8 | - ReadUByte(index + 3); + int32_t b1 = ReadByte(index); + if (b1 == kInvalidByte) + return kInvalidLong; + int32_t b2 = ReadUByte(index + 1); + if (b2 < 0) + return kInvalidLong; + int32_t b3 = ReadUByte(index + 2); + if (b3 < 0) + return kInvalidLong; + int32_t b4 = ReadUByte(index + 3); + if (b4 < 0) + return kInvalidLong; + return static_cast<uint32_t>(b1) << 24 | b2 << 16 | b3 << 8 | b4; } int32_t ReadableFontData::ReadFixed(int32_t index) { @@ -140,7 +192,13 @@ int32_t ReadableFontData::ReadFixed(int32_t index) { } int64_t ReadableFontData::ReadDateTimeAsLong(int32_t index) { - return (int64_t)ReadULong(index) << 32 | ReadULong(index + 4); + int32_t high = ReadULong(index); + if (high == kInvalidUnsigned) + return kInvalidLongDateTime; + int32_t low = ReadULong(index + 4); + if (low == kInvalidUnsigned) + return kInvalidLongDateTime; + return (int64_t)high << 32 | low; } int32_t ReadableFontData::ReadFWord(int32_t index) { @@ -187,12 +245,11 @@ int32_t ReadableFontData::SearchUShort(int32_t start_index, #if defined (SFNTLY_DEBUG_FONTDATA) fprintf(stderr, "**start: %d; end: %d\n", location_start, location_end); #endif - if (key <= location_end) { + if (key <= location_end) return location; - } else { - // location is above the current location - bottom = location + 1; - } + + // location is above the current location + bottom = location + 1; } } return -1; @@ -208,14 +265,15 @@ int32_t ReadableFontData::SearchUShort(int32_t start_index, while (top != bottom) { location = (top + bottom) / 2; int32_t location_start = ReadUShort(start_index + location * start_offset); + if (key == location_start) + return location; + if (key < location_start) { // location is below current location top = location; - } else if (key > location_start) { + } else { // location is above current location bottom = location + 1; - } else { - return location; } } return -1; @@ -243,12 +301,11 @@ int32_t ReadableFontData::SearchULong(int32_t start_index, #if defined (SFNTLY_DEBUG_FONTDATA) fprintf(stderr, "**start: %d; end: %d\n", location_start, location_end); #endif - if (key <= location_end) { + if (key <= location_end) return location; - } else { - // location is above the current location - bottom = location + 1; - } + + // location is above the current location + bottom = location + 1; } } return -1; @@ -256,7 +313,9 @@ int32_t ReadableFontData::SearchULong(int32_t start_index, CALLER_ATTACH FontData* ReadableFontData::Slice(int32_t offset, int32_t length) { - if (offset < 0 || offset + length > Size()) { + if (offset < 0 || length < 0 || + offset > std::numeric_limits<int32_t>::max() - length || + offset + length > Size()) { #if !defined (SFNTLY_NO_EXCEPTION) throw IndexOutOfBoundsException( "Attempt to bind data outside of its limits"); diff --git a/cpp/src/sfntly/data/readable_font_data.h b/cpp/src/sfntly/data/readable_font_data.h index b43c626..37a0918 100644 --- a/cpp/src/sfntly/data/readable_font_data.h +++ b/cpp/src/sfntly/data/readable_font_data.h @@ -22,8 +22,8 @@ namespace sfntly { -class WritableFontData; class OutputStream; +class WritableFontData; // Writable font data wrapper. Supports reading of data primitives in the // TrueType / OpenType spec. @@ -51,6 +51,12 @@ class ReadableFontData : public FontData, explicit ReadableFontData(ByteArray* array); virtual ~ReadableFontData(); + static const int32_t kInvalidByte = 128; + static const int32_t kInvalidShort = 32768; + static const int32_t kInvalidLong = 0xffffffff; + static const int32_t kInvalidUnsigned = -1; + static const int64_t kInvalidLongDateTime = -1; + static CALLER_ATTACH ReadableFontData* CreateReadableFontData(ByteVector* b); // Gets a computed checksum for the data. This checksum uses the OpenType spec @@ -76,7 +82,7 @@ class ReadableFontData : public FontData, // Read the BYTE at the given index. // @param index index into the font data - // @return the BYTE + // @return the BYTE; |kInvalidByte| if outside the bounds of the font data // @throws IndexOutOfBoundsException if index is outside the FontData's range virtual int32_t ReadByte(int32_t index); @@ -94,31 +100,31 @@ class ReadableFontData : public FontData, // Read the CHAR at the given index. // @param index index into the font data - // @return the CHAR + // @return the CHAR; -1 if outside the bounds of the font data // @throws IndexOutOfBoundsException if index is outside the FontData's range virtual int32_t ReadChar(int32_t index); // Read the USHORT at the given index. // @param index index into the font data - // @return the USHORT + // @return the USHORT; -1 if outside the bounds of the font data // @throws IndexOutOfBoundsException if index is outside the FontData's range virtual int32_t ReadUShort(int32_t index); // Read the SHORT at the given index. // @param index index into the font data - // @return the SHORT + // @return the SHORT; |kInvalidShort| if outside the bounds of the font data // @throws IndexOutOfBoundsException if index is outside the FontData's range virtual int32_t ReadShort(int32_t index); // Read the UINT24 at the given index. // @param index index into the font data - // @return the UINT24 + // @return the UINT24; -1 if outside the bounds of the font data // @throws IndexOutOfBoundsException if index is outside the FontData's range virtual int32_t ReadUInt24(int32_t index); // Read the ULONG at the given index. // @param index index into the font data - // @return the ULONG + // @return the ULONG; kInvalidUnsigned if outside the bounds of the font data // @throws IndexOutOfBoundsException if index is outside the FontData's range virtual int64_t ReadULong(int32_t index); @@ -136,7 +142,7 @@ class ReadableFontData : public FontData, // Read the LONG at the given index. // @param index index into the font data - // @return the LONG + // @return the LONG; kInvalidLong if outside the bounds of the font data // @throws IndexOutOfBoundsException if index is outside the FontData's range virtual int32_t ReadLong(int32_t index); @@ -148,7 +154,8 @@ class ReadableFontData : public FontData, // Read the LONGDATETIME at the given index. // @param index index into the font data - // @return the LONGDATETIME + // @return the LONGDATETIME; kInvalidLongDateTime if outside the bounds of the + // font data // @throws IndexOutOfBoundsException if index is outside the FontData's range virtual int64_t ReadDateTimeAsLong(int32_t index); diff --git a/cpp/src/sfntly/data/writable_font_data.cc b/cpp/src/sfntly/data/writable_font_data.cc index 7f6f72f..073e9df 100644 --- a/cpp/src/sfntly/data/writable_font_data.cc +++ b/cpp/src/sfntly/data/writable_font_data.cc @@ -16,6 +16,9 @@ #include "sfntly/data/writable_font_data.h" +#include <algorithm> +#include <limits> + #include "sfntly/data/memory_byte_array.h" #include "sfntly/data/growable_memory_byte_array.h" @@ -165,7 +168,9 @@ void WritableFontData::CopyFrom(InputStream* is) { CALLER_ATTACH FontData* WritableFontData::Slice(int32_t offset, int32_t length) { - if (offset < 0 || offset + length > Size()) { + if (offset < 0 || length < 0 || + offset > std::numeric_limits<int32_t>::max() - length || + offset + length > Size()) { #if !defined (SFNTLY_NO_EXCEPTION) throw IndexOutOfBoundsException( "Attempt to bind data outside of its limits"); @@ -177,7 +182,7 @@ CALLER_ATTACH FontData* WritableFontData::Slice(int32_t offset, } CALLER_ATTACH FontData* WritableFontData::Slice(int32_t offset) { - if (offset > Size()) { + if (offset < 0 || offset > Size()) { #if !defined (SFNTLY_NO_EXCEPTION) throw IndexOutOfBoundsException( "Attempt to bind data outside of its limits"); |