aboutsummaryrefslogtreecommitdiff
path: root/cpp/src/sfntly/data
diff options
context:
space:
mode:
Diffstat (limited to 'cpp/src/sfntly/data')
-rw-r--r--cpp/src/sfntly/data/byte_array.cc2
-rw-r--r--cpp/src/sfntly/data/font_data.cc44
-rw-r--r--cpp/src/sfntly/data/font_data.h15
-rw-r--r--cpp/src/sfntly/data/readable_font_data.cc131
-rw-r--r--cpp/src/sfntly/data/readable_font_data.h25
-rw-r--r--cpp/src/sfntly/data/writable_font_data.cc9
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");