Bug 1443095 - Update graphite2 library to release 1.3.11 (plus upstream commit 6e24eb7e to fix leak). r=jrmuizel

This commit is contained in:
Jonathan Kew 2018-03-10 10:43:38 +00:00
parent 8dfb05971f
commit 243822d04c
31 changed files with 264 additions and 133 deletions

View File

@ -1,5 +1,12 @@
# Graphite engine
## Project CI status
Linux -- Intel 64bit:[![Build Status](http://build.palaso.org/app/rest/builds/buildType:bt124/statusIcon)](http://build.palaso.org/viewType.html?buildTypeId=bt124&guest=1)
Intel 32bit:[![Build Status](http://build.palaso.org/app/rest/builds/buildType:bt123/statusIcon)](http://build.palaso.org/viewType.html?buildTypeId=bt123&guest=1)
ARM 32bit:[![Build Status](http://build.palaso.org/app/rest/builds/buildType:Graphite_Linux32bitArm/statusIcon)](http://build.palaso.org/viewType.html?buildTypeId=Graphite_Linux32bitArm&guest=1)
Windows -- Intel 64bit:[![Build Status](http://build.palaso.org/app/rest/builds/buildType:Graphite_Windows64bitProduction/statusIcon)](http://build.palaso.org/viewType.html?buildTypeId=Graphite_Windows64bitProduction&guest=1)
## What is Graphite?
Graphite is a system that can be used to create “smart fonts” capable of displaying writing systems with various complex behaviors. A smart font contains not only letter shapes but also additional instructions indicating how to combine and position the letters in complex ways.

View File

@ -1,3 +1,7 @@
This directory contains the Graphite2 library release 1.3.10 from
https://github.com/silnrsi/graphite/releases/download/1.3.10/graphite2-minimal-1.3.10.tgz
This directory contains the Graphite2 library release 1.3.11 from
https://github.com/silnrsi/graphite/releases/download/1.3.11/graphite2-minimal-1.3.11.tgz
See ./gfx/graphite2/moz-gr-update.sh for update procedure.
Note (2018-03-10):
Cherry-picked 6e24eb7edbd0872b46441d7397e8b87cccfede73 from upstream to fix memory leak
as noted in bug https://bugzilla.mozilla.org/show_bug.cgi?id=1443095.

View File

@ -30,7 +30,7 @@
#define GR2_VERSION_MAJOR 1
#define GR2_VERSION_MINOR 3
#define GR2_VERSION_BUGFIX 10
#define GR2_VERSION_BUGFIX 11
#ifdef __cplusplus
extern "C"

View File

@ -56,6 +56,10 @@ if (GRAPHITE2_TELEMETRY)
add_definitions(-DGRAPHITE2_TELEMETRY)
endif (GRAPHITE2_TELEMETRY)
if (NOT BUILD_SHARED_LIBS)
add_definitions(-DGRAPHITE2_STATIC)
endif (NOT BUILD_SHARED_LIBS)
set(GRAPHITE_HEADERS
../include/graphite2/Font.h
../include/graphite2/Segment.h
@ -65,7 +69,7 @@ set(GRAPHITE_HEADERS
file(GLOB PRIVATE_HEADERS inc/*.h)
add_library(graphite2 SHARED
add_library(graphite2
${GRAPHITE2_VM_TYPE}_machine.cpp
gr_char_info.cpp
gr_features.cpp
@ -107,9 +111,9 @@ set_target_properties(graphite2 PROPERTIES PUBLIC_HEADER "${GRAPHITE_HEADERS}"
LT_VERSION_AGE ${GRAPHITE_API_AGE})
if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
set_target_properties(graphite2 PROPERTIES
COMPILE_FLAGS "-Wall -Wextra -Wno-unknown-pragmas -Wendif-labels -Wshadow -Wctor-dtor-privacy -Wnon-virtual-dtor -fno-rtti -fno-exceptions -fvisibility=hidden -fvisibility-inlines-hidden -fno-stack-protector"
LINK_FLAGS "-nodefaultlibs ${GRAPHITE_LINK_FLAGS}"
set_target_properties(graphite2 PROPERTIES
COMPILE_FLAGS "-Wall -Wextra -Wno-unknown-pragmas -Wendif-labels -Wshadow -Wctor-dtor-privacy -Wnon-virtual-dtor -fno-rtti -fno-exceptions -fvisibility=hidden -fvisibility-inlines-hidden"
LINK_FLAGS "-nodefaultlibs ${GRAPHITE_LINK_FLAGS}"
LINKER_LANGUAGE C)
if (${CMAKE_SYSTEM_PROCESSOR} MATCHES "x86|i.86")
add_definitions(-mfpmath=sse -msse2)
@ -130,16 +134,18 @@ if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
target_link_libraries(graphite2 c gcc)
endif (GRAPHITE2_ASAN)
include(Graphite)
nolib_test(stdc++ $<TARGET_SONAME_FILE:graphite2>)
if (BUILD_SHARED_LIBS)
nolib_test(stdc++ $<TARGET_SONAME_FILE:graphite2>)
endif (BUILD_SHARED_LIBS)
endif (${CMAKE_CXX_COMPILER} MATCHES ".*mingw.*")
set(CMAKE_CXX_IMPLICIT_LINK_LIBRARIES "")
CREATE_LIBTOOL_FILE(graphite2 "/lib${LIB_SUFFIX}")
endif (${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
if (${CMAKE_SYSTEM_NAME} STREQUAL "Darwin")
set_target_properties(graphite2 PROPERTIES
COMPILE_FLAGS "-Wall -Wextra -Wno-unknown-pragmas -Wimplicit-fallthrough -Wendif-labels -Wshadow -Wno-ctor-dtor-privacy -Wno-non-virtual-dtor -fno-rtti -fno-exceptions -fvisibility=hidden -fvisibility-inlines-hidden -fno-stack-protector -mfpmath=sse -msse2"
LINK_FLAGS "-nodefaultlibs"
set_target_properties(graphite2 PROPERTIES
COMPILE_FLAGS "-Wall -Wextra -Wno-unknown-pragmas -Wimplicit-fallthrough -Wendif-labels -Wshadow -Wno-ctor-dtor-privacy -Wno-non-virtual-dtor -fno-rtti -fno-exceptions -fvisibility=hidden -fvisibility-inlines-hidden -mfpmath=sse -msse2"
LINK_FLAGS "-nodefaultlibs"
LINKER_LANGUAGE C)
target_link_libraries(graphite2 c)
include(Graphite)

View File

@ -219,7 +219,11 @@ Machine::Code::Code(bool is_constraint, const byte * bytecode_begin, const byte
if (_out)
*_out += total_sz;
else
_code = static_cast<instr *>(realloc(_code, total_sz));
{
instr * const old_code = _code;
_code = static_cast<instr *>(realloc(_code, total_sz));
if (!_code) free(old_code);
}
_data = reinterpret_cast<byte *>(_code + (_instr_count+1));
if (!_code)
@ -316,8 +320,9 @@ opcode Machine::Code::decoder::fetch_opcode(const byte * bc)
if (_stack_depth <= 0)
failure(underfull_stack);
break;
case NEXT :
case NEXT_N : // runtime checked
break;
case NEXT :
case COPY_NEXT :
++_out_index;
if (_out_index < -1 || _out_index > _out_length || _slotref > _max.rule_length)

View File

@ -306,7 +306,7 @@ bool ShiftCollider::mergeSlot(Segment *seg, Slot *slot, const SlotCollision *csl
float seq_above_wt = cslot->seqAboveWt();
float seq_below_wt = cslot->seqBelowWt();
float seq_valign_wt = cslot->seqValignWt();
float lmargin = _margin;
float lmargin;
// if isAfter, invert orderFlags for diagonal orders.
if (isAfter)
{
@ -558,6 +558,8 @@ bool ShiftCollider::mergeSlot(Segment *seg, Slot *slot, const SlotCollision *csl
{
// Set up the bogus slot representing the exclusion glyph.
Slot *exclSlot = seg->newSlot();
if (!exclSlot)
return res;
exclSlot->setGlyph(seg, cslot->exclGlyph());
Position exclOrigin(slot->origin() + cslot->exclOffset());
exclSlot->origin(exclOrigin);
@ -805,6 +807,8 @@ static float get_edge(Segment *seg, const Slot *s, const Position &shift, float
{
const BBox &bb = gc.getBoundingBBox(gid);
const SlantBox &sb = gc.getBoundingSlantBox(gid);
if (sy + bb.yi - margin > y + width / 2 || sy + bb.ya + margin < y - width / 2)
return res;
float td = sx - sy + y;
float ts = sx + sy - y;
if (isRight)
@ -924,7 +928,7 @@ bool KernCollider::initSlot(Segment *seg, Slot *aSlot, const Rect &limit, float
}
}
done:
_mingap = (float)1e38;
_mingap = (float)1e37; // less than 1e38 s.t. 1e38-_mingap is really big
_target = aSlot;
_margin = margin;
_currShift = currShift;
@ -945,7 +949,7 @@ bool KernCollider::mergeSlot(Segment *seg, Slot *slot, const Position &currShift
const float sx = slot->origin().x + currShift.x;
float x = (sx + (rtl > 0 ? bb.tr.x : bb.bl.x)) * rtl;
// this isn't going to reduce _mingap so skip
if (x < rtl * (_xbound - _mingap - currSpace))
if (_hit && x < rtl * (_xbound - _mingap - currSpace))
return false;
const float sy = slot->origin().y + currShift.y;
@ -954,19 +958,24 @@ bool KernCollider::mergeSlot(Segment *seg, Slot *slot, const Position &currShift
if (smin > smax)
return false;
bool collides = false;
bool nooverlap = true;
for (int i = smin; i <= smax; ++i)
{
float t;
float here = _edges[i] * rtl;
float y = (float)(_miny - 1 + (i + .5f) * _sliceWidth); // vertical center of slice
if ( (x > here - _mingap - currSpace) )
if (here > (float)9e37)
continue;
if (!_hit || x > here - _mingap - currSpace)
{
float y = (float)(_miny - 1 + (i + .5f) * _sliceWidth); // vertical center of slice
// 2 * currSpace to account for the space that is already separating them and the space we want to add
float m = get_edge(seg, slot, currShift, y, _sliceWidth, 0., rtl > 0) * rtl + 2 * currSpace;
t = here - m;
if (m < (float)-8e37) // only true if the glyph has a gap in it
continue;
nooverlap = false;
float t = here - m;
// _mingap is positive to shrink
if (t < _mingap)
if (t < _mingap || (!_hit && !collides))
{
_mingap = t;
collides = true;
@ -980,8 +989,14 @@ bool KernCollider::mergeSlot(Segment *seg, Slot *slot, const Position &currShift
}
#endif
}
else
nooverlap = false;
}
return collides; // note that true is not a necessarily reliable value
if (nooverlap)
_mingap = max(_mingap, _xbound + currSpace + _margin - x);
if (collides && !nooverlap)
_hit = true;
return collides | nooverlap; // note that true is not a necessarily reliable value
} // end of KernCollider::mergeSlot

View File

@ -43,29 +43,32 @@ u32 read_literal(u8 const * &s, u8 const * const e, u32 l) {
return l;
}
bool read_sequence(u8 const * &src, u8 const * const end, u8 const * &literal, u32 & literal_len, u32 & match_len, u32 & match_dist)
bool read_sequence(u8 const * &src, u8 const * const end, u8 const * &literal,
u32 & literal_len, u32 & match_len, u32 & match_dist)
{
u8 const token = *src++;
literal_len = read_literal(src, end, token >> 4);
literal = src;
src += literal_len;
if (src > end - 2 || src < literal)
// Normal exit for end of stream, wrap arround check and parital match check.
if (src > end - sizeof(u16) || src < literal)
return false;
match_dist = *src++;
match_dist |= *src++ << 8;
match_len = read_literal(src, end, token & 0xf);
return src <= end-5;
match_len = read_literal(src, end, token & 0xf) + MINMATCH;
// Malformed stream check.
return src <= end-MINCODA;
}
}
int lz4::decompress(void const *in, size_t in_size, void *out, size_t out_size)
{
if (out_size <= in_size || in_size < sizeof(unsigned long)+1)
if (out_size <= in_size || in_size < MINSRCSIZE)
return -1;
u8 const * src = static_cast<u8 const *>(in),
@ -74,39 +77,47 @@ int lz4::decompress(void const *in, size_t in_size, void *out, size_t out_size)
u8 * dst = static_cast<u8*>(out),
* const dst_end = dst + out_size;
// Check the in and out size hasn't wrapped around.
if (src >= src_end || dst >= dst_end)
return -1;
u32 literal_len = 0,
match_len = 0,
match_dist = 0;
while (read_sequence(src, src_end, literal, literal_len, match_len, match_dist))
while (read_sequence(src, src_end, literal, literal_len, match_len,
match_dist))
{
if (literal_len != 0)
{
// Copy in literal. At this point the last full sequence must be at
// least MINMATCH + 5 from the end of the output buffer.
if (align(literal_len) > unsigned(dst_end - dst - (MINMATCH+5)) || dst_end - dst < MINMATCH + 5)
// Copy in literal. At this point the a minimal literal + minminal
// match plus the coda (1 + 2 + 5) must be 8 bytes or more allowing
// us to remain within the src buffer for an overrun_copy on
// machines upto 64 bits.
if (align(literal_len) > out_size)
return -1;
dst = overrun_copy(dst, literal, literal_len);
out_size -= literal_len;
}
// Copy, possibly repeating, match from earlier in the
// decoded output.
u8 const * const pcpy = dst - match_dist;
if (pcpy < static_cast<u8*>(out)
|| pcpy >= dst
|| match_len > unsigned(dst_end - dst - (MINMATCH+5))
|| dst_end - dst < MINMATCH + 5)
|| match_len > unsigned(out_size - LASTLITERALS)
// Wrap around checks:
|| out_size < LASTLITERALS || pcpy >= dst)
return -1;
if (dst > pcpy+sizeof(unsigned long)
&& dst + align(match_len + MINMATCH) <= dst_end)
dst = overrun_copy(dst, pcpy, match_len + MINMATCH);
else
dst = safe_copy(dst, pcpy, match_len + MINMATCH);
if (dst > pcpy+sizeof(unsigned long)
&& align(match_len) <= out_size)
dst = overrun_copy(dst, pcpy, match_len);
else
dst = safe_copy(dst, pcpy, match_len);
out_size -= match_len;
}
if (literal_len > src_end - literal
|| literal_len > dst_end - dst)
if (literal > src_end - literal_len || literal_len > out_size)
return -1;
dst = fast_copy(dst, literal, literal_len);

View File

@ -73,7 +73,7 @@ FeatureRef::FeatureRef(const Face & face,
unsigned short & bits_offset, uint32 max_val,
uint32 name, uint16 uiName, uint16 flags,
FeatureSetting *settings, uint16 num_set) throw()
: m_pFace(&face),
: m_face(&face),
m_nameValues(settings),
m_mask(mask_over_val(max_val)),
m_max(max_val),
@ -135,7 +135,7 @@ bool FeatureMap::readFeats(const Face & face)
const uint16 flags = be::read<uint16>(p),
uiName = be::read<uint16>(p);
if (settings_offset > size_t(feat_end - feat_start)
if (settings_offset > size_t(feat_end - feat_start)
|| settings_offset + num_settings * FEATURE_SETTING_SIZE > size_t(feat_end - feat_start))
{
free(defVals);
@ -176,9 +176,9 @@ bool FeatureMap::readFeats(const Face & face)
for (int i = 0; i < m_numFeats; ++i)
{
m_feats[i].applyValToFeature(defVals[i], m_defaultFeatures);
m_pNamedFeats[i] = m_feats+i;
m_pNamedFeats[i] = m_feats[i];
}
free(defVals);
qsort(m_pNamedFeats, m_numFeats, sizeof(NameAndFeatureRef), &cmpNameAndFeatures);
@ -259,7 +259,7 @@ Features* SillMap::cloneFeatures(uint32 langname/*0 means default*/) const
const FeatureRef *FeatureMap::findFeatureRef(uint32 name) const
{
NameAndFeatureRef *it;
for (it = m_pNamedFeats; it < m_pNamedFeats + m_numFeats; ++it)
if (it->m_name == name)
return it->m_pFRef;
@ -267,13 +267,13 @@ const FeatureRef *FeatureMap::findFeatureRef(uint32 name) const
}
bool FeatureRef::applyValToFeature(uint32 val, Features & pDest) const
{
if (val>maxVal() || !m_pFace)
{
if (val>maxVal() || !m_face)
return false;
if (pDest.m_pMap==NULL)
pDest.m_pMap = &m_pFace->theSill().theFeatureMap();
pDest.m_pMap = &m_face->theSill().theFeatureMap();
else
if (pDest.m_pMap!=&m_pFace->theSill().theFeatureMap())
if (pDest.m_pMap!=&m_face->theSill().theFeatureMap())
return false; //incompatible
if (m_index >= pDest.size())
pDest.resize(m_index+1);
@ -283,11 +283,10 @@ bool FeatureRef::applyValToFeature(uint32 val, Features & pDest) const
}
uint32 FeatureRef::getFeatureVal(const Features& feats) const
{
if (m_index < feats.size() && &m_pFace->theSill().theFeatureMap()==feats.m_pMap)
return (feats[m_index] & m_mask) >> m_bits;
{
if (m_index < feats.size() && m_face
&& &m_face->theSill().theFeatureMap()==feats.m_pMap)
return (feats[m_index] & m_mask) >> m_bits;
else
return 0;
}

View File

@ -92,7 +92,7 @@ const void *FileFace::get_table_fn(const void* appFaceHandle, unsigned int name,
return 0;
tbl = malloc(tbl_len);
if (fread(tbl, 1, tbl_len, file_face._file) != tbl_len)
if (!tbl || fread(tbl, 1, tbl_len, file_face._file) != tbl_len)
{
free(tbl);
return 0;

View File

@ -171,7 +171,9 @@ bool Pass::readPass(const byte * const pass_start, size_t pass_length, size_t su
const uint16 * const o_actions = reinterpret_cast<const uint16 *>(p);
be::skip<uint16>(p, m_numRules + 1);
const byte * const states = p;
if (e.test(2u*m_numTransition*m_numColumns >= (unsigned)(pass_end - p), E_BADPASSLENGTH)) return face.error(e);
if (e.test(2u*m_numTransition*m_numColumns >= (unsigned)(pass_end - p), E_BADPASSLENGTH)
|| e.test(p >= pass_end, E_BADPASSLENGTH))
return face.error(e);
be::skip<int16>(p, m_numTransition*m_numColumns);
be::skip<uint8>(p);
if (e.test(p != pcCode, E_BADPASSCCODEPTR)) return face.error(e);
@ -270,10 +272,11 @@ bool Pass::readRules(const byte * rule_map, const size_t num_entries,
return face.error(e);
}
byte * moved_progs = static_cast<byte *>(realloc(m_progs, prog_pool_free - m_progs));
byte * const moved_progs = prog_pool_free > m_progs ? static_cast<byte *>(realloc(m_progs, prog_pool_free - m_progs)) : 0;
if (e.test(!moved_progs, E_OUTOFMEM))
{
if (prog_pool_free - m_progs == 0) m_progs = 0;
free(m_progs);
m_progs = 0;
return face.error(e);
}
@ -714,18 +717,18 @@ void Pass::adjustSlot(int delta, Slot * & slot_out, SlotMap & smap) const
{
while (++delta <= 0 && slot_out)
{
slot_out = slot_out->prev();
if (smap.highpassed() && smap.highwater() == slot_out)
smap.highpassed(false);
slot_out = slot_out->prev();
}
}
else if (delta > 0)
{
while (--delta >= 0 && slot_out)
{
slot_out = slot_out->next();
if (slot_out == smap.highwater() && slot_out)
smap.highpassed(true);
slot_out = slot_out->next();
}
}
}
@ -968,8 +971,8 @@ bool Pass::resolveCollisions(Segment *seg, Slot *slotFix, Slot *start,
if (nbor != slotFix // don't process if this is the slot of interest
&& !(cNbor->ignore()) // don't process if ignoring
&& (nbor == base || sameCluster // process if in the same cluster as slotFix
|| !inKernCluster(seg, nbor) // or this cluster is not to be kerned
|| (rtl ^ ignoreForKern)) // or it comes before(ltr) or after(rtl)
|| !inKernCluster(seg, nbor)) // or this cluster is not to be kerned
// || (rtl ^ ignoreForKern)) // or it comes before(ltr) or after(rtl)
&& (!isRev // if processing forwards then good to merge otherwise only:
|| !(cNbor->flags() & SlotCollision::COLL_FIX) // merge in immovable stuff
|| ((cNbor->flags() & SlotCollision::COLL_KERN) && !sameCluster) // ignore other kernable clusters
@ -1037,6 +1040,8 @@ float Pass::resolveKern(Segment *seg, Slot *slotFix, GR_MAYBE_UNUSED Slot *start
base = base->attachedTo();
SlotCollision *cFix = seg->collisionInfo(base);
const GlyphCache &gc = seg->getFace()->glyphs();
const Rect &bbb = seg->theGlyphBBoxTemporary(slotFix->gid());
const float by = slotFix->origin().y + cFix->shift().y;
if (base != slotFix)
{
@ -1047,6 +1052,8 @@ float Pass::resolveKern(Segment *seg, Slot *slotFix, GR_MAYBE_UNUSED Slot *start
bool isInit = false;
KernCollider coll(dbgout);
ymax = max(by + bbb.tr.y, ymax);
ymin = min(by + bbb.bl.y, ymin);
for (nbor = slotFix->next(); nbor; nbor = nbor->next())
{
if (nbor->isChildOf(base))
@ -1066,9 +1073,6 @@ float Pass::resolveKern(Segment *seg, Slot *slotFix, GR_MAYBE_UNUSED Slot *start
else
{
space_count = 0;
float y = nbor->origin().y + cNbor->shift().y;
ymax = max(y + bb.tr.y, ymax);
ymin = min(y + bb.bl.y, ymin);
if (nbor != slotFix && !cNbor->ignore())
{
seenEnd = true;

View File

@ -42,7 +42,7 @@ SegCacheEntry::SegCacheEntry(const uint16* cmapGlyphs, size_t length, Segment *
m_accessCount(0), m_lastAccess(cacheTime)
{
if (m_unicode)
for (uint16 i = 0; i < length; i++)
for (size_t i = 0; i < length; i++)
m_unicode[i] = cmapGlyphs[i];
const size_t glyphCount = seg->slotCount(),

View File

@ -59,7 +59,9 @@ Segment::Segment(unsigned int numchars, const Face* face, uint32 script, int tex
m_dir(textDir),
m_flags(((m_silf->flags() & 0x20) != 0) << 1)
{
freeSlot(newSlot());
Slot *s = newSlot();
if (s)
freeSlot(s);
m_bufSize = log_binary(numchars)+1;
}

View File

@ -276,6 +276,7 @@ size_t Silf::readClassMap(const byte *p, size_t data_len, uint32 version, Error
return ERROROFFSET;
// Check the linear offsets are sane, these must be monotonically increasing.
assert(m_nClass >= m_nLinear);
for (const uint32 *o = m_classOffsets, * const o_end = o + m_nLinear; o != o_end; ++o)
if (e.test(o[0] > o[1], E_BADCLASSOFFSET))
return ERROROFFSET;

View File

@ -341,6 +341,11 @@ bool CheckTable(const Tag TableId, const void * pTable, size_t lTableSize)
return be::swap(pName->format) == 0;
}
case Tag::glyf:
{
return (lTableSize >= sizeof(Sfnt::Glyph));
}
default:
break;
}
@ -464,7 +469,7 @@ void HeadTableModifyTime(const void * pHead,
{
const Sfnt::FontHeader * pTable =
reinterpret_cast<const Sfnt::FontHeader *>(pHead);
;
*pnDateBC = be::swap(pTable->modified[0]);
*pnDateAD = be::swap(pTable->modified[1]);
}
@ -1247,7 +1252,7 @@ size_t LocaLookup(gid16 nGlyphId,
void * GlyfLookup(const void * pGlyf, size_t nGlyfOffset, size_t nTableLen)
{
const uint8 * pByte = reinterpret_cast<const uint8 *>(pGlyf);
if (nGlyfOffset + pByte < pByte || nGlyfOffset + sizeof(Sfnt::Glyph) >= nTableLen)
if (nGlyfOffset + pByte < pByte || nGlyfOffset >= nTableLen - sizeof(Sfnt::Glyph))
return NULL;
return const_cast<uint8 *>(pByte + nGlyfOffset);
}

View File

@ -195,7 +195,7 @@ gr_uint32 gr_face_lang_by_index(const gr_face* pFace, gr_uint16 i)
void gr_face_destroy(gr_face *face)
{
delete face;
delete static_cast<Face*>(face);
}

View File

@ -80,14 +80,14 @@ gr_int16 gr_fref_value(const gr_feature_ref* pfeatureref, gr_uint16 settingno)
void* gr_fref_label(const gr_feature_ref* pfeatureref, gr_uint16 *langId, gr_encform utf, gr_uint32 *length)
{
if(!pfeatureref || !pfeatureref->getFace())
if(!pfeatureref)
{
langId = 0;
length = 0;
return NULL;
}
uint16 label = pfeatureref->getNameId();
NameTable * names = pfeatureref->getFace()->nameTable();
NameTable * names = pfeatureref->getFace().nameTable();
if (!names)
{
langId = 0;
@ -101,14 +101,14 @@ void* gr_fref_label(const gr_feature_ref* pfeatureref, gr_uint16 *langId, gr_enc
void* gr_fref_value_label(const gr_feature_ref*pfeatureref, gr_uint16 setting,
gr_uint16 *langId, gr_encform utf, gr_uint32 *length)
{
if(!pfeatureref || (setting >= pfeatureref->getNumSettings()) || !pfeatureref->getFace())
if(!pfeatureref || (setting >= pfeatureref->getNumSettings()))
{
langId = 0;
length = 0;
return NULL;
}
uint16 label = pfeatureref->getSettingName(setting);
NameTable * names = pfeatureref->getFace()->nameTable();
NameTable * names = pfeatureref->getFace().nameTable();
if (!names)
{
langId = 0;
@ -131,7 +131,7 @@ gr_feature_val* gr_featureval_clone(const gr_feature_val* pfeatures/*may be NULL
void gr_featureval_destroy(gr_feature_val *p)
{
delete p;
delete static_cast<Features*>(p);
}

View File

@ -47,10 +47,16 @@ gr_font* gr_make_font(float ppm/*pixels per em*/, const gr_face *face)
gr_font* gr_make_font_with_ops(float ppm/*pixels per em*/, const void* appFontHandle/*non-NULL*/, const gr_font_ops * font_ops, const gr_face * face/*needed for scaling*/)
{ //the appFontHandle must stay alive all the time when the gr_font is alive. When finished with the gr_font, call destroy_gr_font
if (face == 0) return 0;
if (face == 0 || ppm <= 0) return 0;
Font * const res = new Font(ppm, *face, appFontHandle, font_ops);
return static_cast<gr_font*>(res);
if (*res)
return static_cast<gr_font*>(res);
else
{
delete res;
return 0;
}
}
gr_font* gr_make_font_with_advance_fn(float ppm/*pixels per em*/, const void* appFontHandle/*non-NULL*/, gr_advance_fn getAdvance, const gr_face * face/*needed for scaling*/)
@ -61,7 +67,7 @@ gr_font* gr_make_font_with_advance_fn(float ppm/*pixels per em*/, const void* ap
void gr_font_destroy(gr_font *font)
{
delete font;
delete static_cast<Font*>(font);
}

View File

@ -41,7 +41,7 @@ of the License or (at your option) any later version.
using namespace graphite2;
#if !defined GRAPHITE2_NTRACING
json *global_log = NULL;
json *global_log = 0;
#endif
extern "C" {
@ -120,6 +120,7 @@ void gr_stop_logging(GR_MAYBE_UNUSED gr_face * face)
{
FILE * log = global_log->stream();
delete global_log;
global_log = 0;
fclose(log);
}
#endif
@ -214,7 +215,7 @@ json & graphite2::operator << (json & j, const dslot & ds) throw()
j << "user" << json::flat << json::array;
for (int n = 0; n!= seg.numAttrs(); ++n)
j << s.userAttrs()[n];
j << json::close;
j << json::close;
if (s.firstChild())
{
j << "children" << json::flat << json::array;

View File

@ -103,7 +103,7 @@ gr_segment* gr_make_seg(const gr_font *font, const gr_face *face, gr_uint32 scri
if (pFeats == 0)
pFeats = tmp_feats = static_cast<const gr_feature_val*>(face->theSill().cloneFeatures(0));
gr_segment * seg = makeAndInitialize(font, face, script, pFeats, enc, pStart, nChars, dir);
delete tmp_feats;
delete static_cast<const FeatureVal*>(tmp_feats);
return seg;
}
@ -111,7 +111,7 @@ gr_segment* gr_make_seg(const gr_font *font, const gr_face *face, gr_uint32 scri
void gr_seg_destroy(gr_segment* p)
{
delete p;
delete static_cast<Segment*>(p);
}

View File

@ -162,7 +162,7 @@ inline void Machine::Code::externalProgramMoved(ptrdiff_t dist) throw()
{
if (_code && !_own)
{
_code += dist / sizeof(instr);
_code += dist / signed(sizeof(instr));
_data += dist;
}
}

View File

@ -210,6 +210,7 @@ private:
float _sliceWidth; // width of each slice
float _mingap;
float _xbound; // max or min edge
bool _hit;
#if !defined GRAPHITE2_NTRACING
// Debugging
@ -233,7 +234,8 @@ KernCollider::KernCollider(GR_MAYBE_UNUSED json *dbg)
_maxy(1e38f),
_sliceWidth(0.0f),
_mingap(0.0f),
_xbound(0.0)
_xbound(0.0),
_hit(false)
{
#if !defined GRAPHITE2_NTRACING
_seg = 0;

View File

@ -47,7 +47,10 @@ typedef uint32_t u32;
typedef uint64_t u64;
#endif
ptrdiff_t const MINMATCH = 4;
ptrdiff_t const MINMATCH = 4,
LASTLITERALS = 5,
MINCODA = LASTLITERALS+1,
MINSRCSIZE = 13;
template<int S>
inline

View File

@ -56,7 +56,7 @@ class FeatureRef
static const uint8 SIZEOF_CHUNK = sizeof(chunk_t)*8;
public:
FeatureRef();
FeatureRef() throw();
FeatureRef(const Face & face, unsigned short & bits_offset, uint32 max_val,
uint32 name, uint16 uiName, uint16 flags,
FeatureSetting *settings, uint16 num_set) throw();
@ -65,7 +65,7 @@ public:
bool applyValToFeature(uint32 val, Features& pDest) const; //defined in GrFaceImp.h
void maskFeature(Features & pDest) const {
if (m_index < pDest.size()) //defensive
pDest[m_index] |= m_mask;
pDest[m_index] |= m_mask;
}
uint32 getFeatureVal(const Features& feats) const; //defined in GrFaceImp.h
@ -76,14 +76,14 @@ public:
uint16 getSettingName(uint16 index) const { return m_nameValues[index].label(); }
int16 getSettingValue(uint16 index) const { return m_nameValues[index].value(); }
uint32 maxVal() const { return m_max; }
const Face* getFace() const { return m_pFace;}
const Face & getFace() const { assert(m_face); return *m_face;}
const FeatureMap* getFeatureMap() const;// { return m_pFace;}
CLASS_NEW_DELETE;
private:
FeatureRef(const FeatureRef & rhs);
const Face * m_pFace; //not NULL
const Face * m_face;
FeatureSetting * m_nameValues; // array of name table ids for feature values
chunk_t m_mask, // bit mask to get the value from the vector
m_max; // max value the value can take
@ -98,11 +98,12 @@ private: //unimplemented
FeatureRef& operator=(const FeatureRef&);
};
inline
FeatureRef::FeatureRef()
: m_pFace(0), m_nameValues(0),
m_mask(0), m_max(0), m_id(0),
FeatureRef::FeatureRef() throw()
: m_face(0),
m_nameValues(0),
m_mask(0), m_max(0),
m_id(0),
m_nameid(0), m_flags(0), m_numSet(0),
m_bits(0), m_index(0)
{
@ -113,13 +114,13 @@ class NameAndFeatureRef
{
public:
NameAndFeatureRef(uint32 name = 0) : m_name(name) , m_pFRef(NULL){}
NameAndFeatureRef(const FeatureRef* p/*not NULL*/) : m_name(p->getId()), m_pFRef(p) {}
NameAndFeatureRef(FeatureRef const & p) : m_name(p.getId()), m_pFRef(&p) {}
bool operator<(const NameAndFeatureRef& rhs) const //orders by m_name
{ return m_name<rhs.m_name; }
CLASS_NEW_DELETE
uint32 m_name;
const FeatureRef* m_pFRef;
};
@ -128,7 +129,7 @@ class FeatureMap
{
public:
FeatureMap() : m_numFeats(0), m_feats(NULL), m_pNamedFeats(NULL) {}
~FeatureMap() { delete [] m_feats; delete[] m_pNamedFeats; }
~FeatureMap() { delete[] m_feats; delete[] m_pNamedFeats; }
bool readFeats(const Face & face);
const FeatureRef *findFeatureRef(uint32 name) const;

View File

@ -44,6 +44,7 @@ public:
float scale() const;
bool isHinted() const;
const Face & face() const;
operator bool () const throw() { return m_advances; }
CLASS_NEW_DELETE;
private:

View File

@ -34,6 +34,7 @@ of the License or (at your option) any later version.
#include <cstdlib>
#include <new>
#include "Main.h"
namespace graphite2 {
@ -104,7 +105,9 @@ void Vector<T>::reserve(size_t n)
if (n > capacity())
{
const ptrdiff_t sz = size();
m_first = static_cast<T*>(realloc(m_first, n*sizeof(T)));
size_t requested;
if (checked_mul(n,sizeof(T), requested)) std::abort();
m_first = static_cast<T*>(realloc(m_first, requested));
if (!m_first) std::abort();
m_last = m_first + sz;
m_end = m_first + n;

View File

@ -15,8 +15,8 @@
You should also have received a copy of the GNU Lesser General Public
License along with this library in the file named "LICENSE".
If not, write to the Free Software Foundation, 51 Franklin Street,
Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
If not, write to the Free Software Foundation, 51 Franklin Street,
Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
internet at http://www.fsf.org/licenses/lgpl.html.
Alternatively, the contents of this file may be used under the terms of the
@ -27,11 +27,12 @@ of the License or (at your option) any later version.
// This general interpreter interface.
// Author: Tim Eves
// Build one of direct_machine.cpp or call_machine.cpp to implement this
// Build one of direct_machine.cpp or call_machine.cpp to implement this
// interface.
#pragma once
#include <cstring>
#include <limits>
#include <graphite2/Types.h>
#include "inc/Main.h"
@ -56,6 +57,13 @@ of the License or (at your option) any later version.
#define REGPARM(n)
#endif
#if defined(__MINGW32__)
// MinGW's <limits> at some point includes winnt.h which #define's a
// DELETE macro, which conflicts with enum opcode below, so we undefine
// it here.
#undef DELETE
#endif
namespace graphite2 {
// Forward declarations
@ -64,7 +72,7 @@ class Slot;
class SlotMap;
namespace vm
namespace vm
{
@ -112,12 +120,12 @@ enum opcode {
PUT_GLYPH, PUSH_GLYPH_ATTR, PUSH_ATT_TO_GLYPH_ATTR,
BITOR, BITAND, BITNOT,
BITSET, SET_FEAT,
MAX_OPCODE,
MAX_OPCODE,
// private opcodes for internal use only, comes after all other on disk opcodes
TEMP_COPY = MAX_OPCODE
};
struct opcode_t
struct opcode_t
{
instr impl[2];
uint8 param_sz;
@ -186,6 +194,8 @@ inline Machine::status_t Machine::status() const throw()
inline void Machine::check_final_stack(const stack_t * const sp)
{
if (_status != finished) return;
stack_t const * const base = _stack + STACK_GUARD,
* const limit = base + STACK_MAX;
if (sp < base) _status = stack_underflow; // This should be impossible now.
@ -195,6 +205,3 @@ inline void Machine::check_final_stack(const stack_t * const sp)
} // namespace vm
} // namespace graphite2

View File

@ -15,8 +15,8 @@
You should also have received a copy of the GNU Lesser General Public
License along with this library in the file named "LICENSE".
If not, write to the Free Software Foundation, 51 Franklin Street,
Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
If not, write to the Free Software Foundation, 51 Franklin Street,
Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
internet at http://www.fsf.org/licenses/lgpl.html.
Alternatively, the contents of this file may be used under the terms of the
@ -77,15 +77,61 @@ public:
struct telemetry {};
#endif
// Checked multiplaction to catch overflow or underflow when allocating memory
#if defined(__has_builtin)
#if __has_builtin(__builtin_mul_overflow)
#define HAVE_BUILTIN_OVERFLOW
#endif
#elif defined(__GNUC__) && (__GNUC__ >= 5) && !defined(__INTEL_COMPILER)
#define HAVE_BUILTIN_OVERFLOW
#endif
#if defined(__has_include)
#if __has_include(<intsafe.h>)
#define HAVE_INTSAFE_H
#endif
#elif defined(_WIN32)
#define HAVE_INTSAFE_H
#endif
// Need to import intsafe into the top level namespace
#if defined(HAVE_INTSAFE_H)
} // namespace graphite2
#include <intsafe.h>
namespace graphite2 {
#endif
#if defined(HAVE_BUILTIN_OVERFLOW)
inline
bool checked_mul(const size_t a, const size_t b, size_t & t) {
return __builtin_mul_overflow(a, b, &t);
}
#elif defined(HAVE_INTSAFE_H)
inline
bool checked_mul(const size_t a, const size_t b, size_t & t) {
return SizeTMult(a, b, &t) == INTSAFE_E_ARITHMETIC_OVERFLOW;
}
#else
inline
bool checked_mul(const size_t a, const size_t b, size_t & t) {
t = a*b;
return (((a | b) & (~size_t(0) << (sizeof(size_t) << 2))) && (t / a != b));
}
#endif
// typesafe wrapper around malloc for simple types
// use free(pointer) to deallocate
template <typename T> T * gralloc(size_t n)
{
size_t total;
if (checked_mul(n, sizeof(T), total))
return 0;
#ifdef GRAPHITE2_TELEMETRY
telemetry::count_bytes(sizeof(T) * n);
telemetry::count_bytes(total);
#endif
return static_cast<T*>(malloc(sizeof(T) * n));
return static_cast<T*>(malloc(total));
}
template <typename T> T * grzeroalloc(size_t n)
@ -128,7 +174,7 @@ inline T max(const T a, const T b)
#if defined(__clang__) && __cplusplus >= 201103L
/* clang's fallthrough annotations are only available starting in C++11. */
#define GR_FALLTHROUGH [[clang::fallthrough]]
#define GR_FALLTHROUGH [[fallthrough]]
#elif defined(_MSC_VER)
/*
* MSVC's __fallthrough annotations are checked by /analyze (Code Analysis):
@ -136,6 +182,8 @@ inline T max(const T a, const T b)
*/
#include <sal.h>
#define GR_FALLTHROUGH __fallthrough
#elif __GNUC__ >= 7
#define GR_FALLTHROUGH __attribute__ ((fallthrough))
#else
#define GR_FALLTHROUGH /* fallthrough */
#endif

View File

@ -205,7 +205,7 @@ int8 Segment::getSlotBidiClass(Slot *s) const
inline
void Segment::finalise(const Font *font, bool reverse)
{
if (!m_first) return;
if (!m_first || !m_last) return;
m_advance = positionSlots(font, m_first, m_last, m_silf->dir(), true);
//associateChars(0, m_numCharinfo);

View File

@ -15,8 +15,8 @@
You should also have received a copy of the GNU Lesser General Public
License along with this library in the file named "LICENSE".
If not, write to the Free Software Foundation, 51 Franklin Street,
Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
If not, write to the Free Software Foundation, 51 Franklin Street,
Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
internet at http://www.fsf.org/licenses/lgpl.html.
Alternatively, the contents of this file may be used under the terms of the
@ -73,7 +73,7 @@ public:
size_t size() const throw();
size_t _sizeof() const throw();
CLASS_NEW_DELETE;
private:
@ -122,10 +122,7 @@ sparse::sparse(I attr, const I last)
+ n_values);
if (m_array.values == 0)
{
free(m_array.values); m_array.map=0;
return;
}
// coverity[forward_null : FALSE] Since m_array is union and m_array.values is not NULL
chunk * ci = m_array.map;

View File

@ -73,7 +73,7 @@ static const opcode_t opcode_table[] =
{{do2(gtr_eq)}, 0, "GTR_EQ"}, // 0x18
{{do_(next), NILOP}, 0, "NEXT"},
{{do_(next_n), NILOP}, 1, "NEXT_N"}, // number <= smap.end - map
{{NILOP, NILOP}, 1, "NEXT_N"}, // number <= smap.end - map
{{do_(next), NILOP}, 0, "COPY_NEXT"},
{{do_(put_glyph_8bit_obs), NILOP}, 1, "PUT_GLYPH_8BIT_OBS"}, // output_class
{{do_(put_subs_8bit_obs), NILOP}, 3, "PUT_SUBS_8BIT_OBS"}, // slot input_class output_class

View File

@ -26,7 +26,7 @@ of the License or (at your option) any later version.
*/
#pragma once
// This file will be pulled into and integrated into a machine implmentation
// DO NOT build directly and under no circumstances every #include headers in
// DO NOT build directly and under no circumstances ever #include headers in
// here or you will break the direct_machine.
//
// Implementers' notes
@ -65,7 +65,7 @@ of the License or (at your option) any later version.
// #define NOT_IMPLEMENTED assert(false)
#define NOT_IMPLEMENTED
// #define NOT_IMPLEMENTED
#define binop(op) const uint32 a = pop(); *sp = uint32(*sp) op a
#define sbinop(op) const int32 a = pop(); *sp = int32(*sp) op a
@ -130,8 +130,10 @@ STARTOP(mul)
ENDOP
STARTOP(div_)
if (*sp == 0) DIE;
sbinop(/);
const int32 b = pop();
const int32 a = int32(*sp);
if (b == 0 || (a == std::numeric_limits<int32>::min() && b == -1)) DIE;
*sp = int32(*sp) / b;
ENDOP
STARTOP(min_)
@ -208,12 +210,12 @@ STARTOP(next)
++map;
ENDOP
STARTOP(next_n)
use_params(1);
NOT_IMPLEMENTED;
//STARTOP(next_n)
// use_params(1);
// NOT_IMPLEMENTED;
//declare_params(1);
//const size_t num = uint8(*param);
ENDOP
//ENDOP
//STARTOP(copy_next)
// if (is) is = is->next();
@ -337,6 +339,7 @@ STARTOP(delete_)
else
seg.last(is->prev());
if (is == smap.highwater())
smap.highwater(is->next());
if (is->prev())