Upstream libmspub fixes committed after the 0.1.5 release (OSS-Fuzz hardening), git diff 08f4e6d8ae..2b094242f9 of https://git.libreoffice.org/libmspub: ofz#42501439 subtract the parent coordinate height in 64 bits ofz#42501619 map the paragraph alignment byte like the underline one ofz#42491111 leave the dash style unsigned until getDash maps it stop turning raw file values into invalid enums ofz#510328337 only use a master page that is a page as well ofz#42522990 return an empty clip path for a shape we do not have ofz#42501940 remember the fallback encoding as well ofz#553153864 leave the shape type unsigned until a switch maps it ofz#565077751 leave the fill type unsigned until the switch maps it diff --git a/src/lib/Dash.cpp b/src/lib/Dash.cpp index 00c7ba7..bb061a1 100644 --- a/src/lib/Dash.cpp +++ b/src/lib/Dash.cpp @@ -42,7 +42,7 @@ bool operator==(const Dash &lhs, const Dash &rhs) return true; } -Dash getDash(MSPUBDashStyle style, unsigned shapeLineWidthEmu, +Dash getDash(unsigned style, unsigned shapeLineWidthEmu, DotStyle dotStyle) { double shapeLineWidth = static_cast(shapeLineWidthEmu) / diff --git a/src/lib/Dash.h b/src/lib/Dash.h index 6079c59..32ffdaa 100644 --- a/src/lib/Dash.h +++ b/src/lib/Dash.h @@ -59,7 +59,7 @@ struct Dash bool operator!=(const Dot &lhs, const Dot &rhs); bool operator==(const Dot &lhs, const Dot &rhs); bool operator==(const Dash &lhs, const Dash &rhs); -Dash getDash(MSPUBDashStyle style, unsigned shapeLineWidthInEmu, +Dash getDash(unsigned style, unsigned shapeLineWidthInEmu, DotStyle dotStyle); } // namespace libmspub diff --git a/src/lib/MSPUBCollector.cpp b/src/lib/MSPUBCollector.cpp index 73c7264..e5c2fd1 100644 --- a/src/lib/MSPUBCollector.cpp +++ b/src/lib/MSPUBCollector.cpp @@ -749,7 +749,7 @@ std::function MSPUBCollector::paintShape(const ShapeInfo &info, cons const Coordinate coord = info.m_coordinates.get_value_or(Coordinate()); BorderPosition borderPosition = hasBorderArt ? INSIDE_SHAPE : info.m_borderPosition.get_value_or(HALF_INSIDE_SHAPE); - ShapeType type; + unsigned type; if (bool(info.m_cropType)) { type = info.m_cropType.get(); @@ -1307,7 +1307,9 @@ const char *MSPUBCollector::getCalculatedEncoding() const } csd_fail: ucsdet_close(ucd); - return "windows-1252"; // Pretty likely to give garbage text, but it's the best we can do. + // Pretty likely to give garbage text, but it's the best we can do. + m_calculatedEncoding = "windows-1252"; + return m_calculatedEncoding.get(); } void MSPUBCollector::setShapeLineBackColor(unsigned shapeSeqNum, @@ -1473,7 +1475,7 @@ void MSPUBCollector::setShapeFlip(unsigned seqNum, bool flipVertical, bool flipH m_shapeInfosBySeqNum[seqNum].m_flips = std::pair(flipVertical, flipHorizontal); } -void MSPUBCollector::setShapeType(unsigned seqNum, ShapeType type) +void MSPUBCollector::setShapeType(unsigned seqNum, unsigned type) { m_shapeInfosBySeqNum[seqNum].m_type = type; } @@ -1758,7 +1760,8 @@ boost::optional MSPUBCollector::getMasterPageSeqNum(unsigned pageSeqNu { boost::optional toReturn; const unsigned *ptr_masterSeqNum = getIfExists_const(m_masterPagesByPageSeqNum, pageSeqNum); - if (ptr_masterSeqNum && m_masterPages.find(*ptr_masterSeqNum) != m_masterPages.end()) + if (ptr_masterSeqNum && hasPage(*ptr_masterSeqNum) && + m_masterPages.find(*ptr_masterSeqNum) != m_masterPages.end()) { return *ptr_masterSeqNum; } @@ -1990,7 +1993,7 @@ void MSPUBCollector::setMasterPage(unsigned seqNum, unsigned masterPageSeqNum) m_masterPagesByPageSeqNum[seqNum] = masterPageSeqNum; } -void MSPUBCollector::setShapeCropType(unsigned seqNum, ShapeType cropType) +void MSPUBCollector::setShapeCropType(unsigned seqNum, unsigned cropType) { m_shapeInfosBySeqNum[seqNum].m_cropType = cropType; } diff --git a/src/lib/MSPUBCollector.h b/src/lib/MSPUBCollector.h index a1f0db3..eb7f05a 100644 --- a/src/lib/MSPUBCollector.h +++ b/src/lib/MSPUBCollector.h @@ -67,8 +67,8 @@ class MSPUBCollector void setNextPage(unsigned seqNum); - void setShapeType(unsigned seqNum, ShapeType type); - void setShapeCropType(unsigned seqNum, ShapeType cropType); + void setShapeType(unsigned seqNum, unsigned type); + void setShapeCropType(unsigned seqNum, unsigned cropType); void setShapePictureRecolor(unsigned seqNum, const ColorReference &recolor); void setShapePictureBrightness(unsigned seqNum, int brightness); void setShapePictureContrast(unsigned seqNum, int contrast); @@ -151,7 +151,7 @@ class MSPUBCollector std::vector > m_fonts; std::vector m_defaultCharStyles; std::vector m_defaultParaStyles; - std::map m_shapeTypesBySeqNum; + std::map m_shapeTypesBySeqNum; std::vector m_paletteColors; std::vector m_shapeSeqNumsOrdered; std::map m_pageSeqNumsByShapeSeqNum; diff --git a/src/lib/MSPUBParser.cpp b/src/lib/MSPUBParser.cpp index 5c2d173..c735509 100644 --- a/src/lib/MSPUBParser.cpp +++ b/src/lib/MSPUBParser.cpp @@ -57,6 +57,74 @@ namespace // below any stack-overflow risk. constexpr unsigned MAX_SHAPE_GROUP_DEPTH = 100; +ArrowStyle readArrowStyle(const unsigned value) +{ + if (value > LINE_ARROW) + { + MSPUB_DEBUG_MSG(("unknown arrow style %u\n", value)); + return NO_ARROW; + } + return ArrowStyle(value); +} + +ArrowSize readArrowSize(const unsigned value) +{ + if (value > LARGE) + { + MSPUB_DEBUG_MSG(("unknown arrow size %u\n", value)); + return MEDIUM; + } + return ArrowSize(value); +} + +VerticalAlign readVerticalAlign(const unsigned value) +{ + if (value > BOTTOM) + { + MSPUB_DEBUG_MSG(("unknown vertical alignment %u\n", value)); + return TOP; + } + return VerticalAlign(value); +} + +SuperSubType readSuperSubType(const unsigned value) +{ + if (value > SUBSCRIPT) + { + MSPUB_DEBUG_MSG(("unknown super or subscript type %u\n", value)); + return NO_SUPER_SUB; + } + return SuperSubType(value); +} + +NumberingType readNumberingType(const unsigned value) +{ + if ((value > SPELLED_ORDINALS) && (value != STANDARD_WESTERN_AT_LEAST_TWO_DIGITS)) + { + MSPUB_DEBUG_MSG(("unknown numbering type %u\n", value)); + return STANDARD_WESTERN; + } + return NumberingType(value); +} + +Alignment readAlignment(const unsigned value) +{ + switch (value & 0xff) + { + case CENTER: + return CENTER; + case RIGHT: + return RIGHT; + case JUSTIFY: + return JUSTIFY; + default: + MSPUB_DEBUG_MSG(("unknown alignment %u\n", value & 0xff)); + MSPUB_FALLTHROUGH; + case LEFT: + return LEFT; + } +} + Underline readUnderline(const unsigned value) { switch (value & 0xff) @@ -905,12 +973,11 @@ bool MSPUBParser::parseShape(librevenge::RVNGInputStream *input, else if (info.id == SHAPE_VALIGN) { m_collector->setShapeVerticalTextAlign(chunk.seqNum, - static_cast(info.data)); + readVerticalAlign(info.data)); } else if (info.id == SHAPE_CROP && info.data != 0) { - m_collector->setShapeCropType(chunk.seqNum, - static_cast(info.data)); + m_collector->setShapeCropType(chunk.seqNum, info.data); } } if (shouldStretchBorderArt) @@ -1294,7 +1361,7 @@ ParagraphStyle MSPUBParser::getParagraphStyle(librevenge::RVNGInputStream *input switch (info.id) { case PARAGRAPH_ALIGNMENT: - ret.m_align = (Alignment)(info.data & 0xFF); // Is this correct? + ret.m_align = readAlignment(info.data); // Is this correct? break; case PARAGRAPH_DEFAULT_CHAR_STYLE: ret.m_defaultCharStyleIndex = info.data; @@ -1366,7 +1433,7 @@ ParagraphStyle MSPUBParser::getParagraphStyle(librevenge::RVNGInputStream *input switch (listSubInfo.id) { case PARAGRAPH_LIST_NUMBERING_TYPE: - numberingType = static_cast(info.data); + numberingType = readNumberingType(info.data); break; case PARAGRAPH_LIST_BULLET_CHAR: bulletChar = info.data; @@ -1451,7 +1518,7 @@ CharacterStyle MSPUBParser::getCharacterStyle(librevenge::RVNGInputStream *input fontIndex = getFontIndex(input, info); break; case SUPER_SUB_TYPE_ID: - style.superSubType = static_cast(info.data); + style.superSubType = readSuperSubType(info.data); break; case OUTLINE_ID: style.outline = true; @@ -1622,7 +1689,7 @@ void MSPUBParser::parseEscherShape(librevenge::RVNGInputStream *input, const Esc EscherContainerInfo cFspgr; unsigned shapeFlags = 0; bool isGroupLeader = false; - ShapeType st = RECTANGLE; + unsigned st = RECTANGLE; if (findEscherContainer(input, sp, cFspgr, OFFICE_ART_FSPGR)) { input->seek(cFspgr.contentsOffset, librevenge::RVNG_SEEK_SET); @@ -1636,7 +1703,7 @@ void MSPUBParser::parseEscherShape(librevenge::RVNGInputStream *input, const Esc input->seek(sp.contentsOffset, librevenge::RVNG_SEEK_SET); if (findEscherContainer(input, sp, cFsp, OFFICE_ART_FSP)) { - st = (ShapeType)(cFsp.initial >> 4); + st = cFsp.initial >> 4; std::map fspData = extractEscherValues(input, cFsp); input->seek(cFsp.contentsOffset + 4, librevenge::RVNG_SEEK_SET); shapeFlags = readU32(input); @@ -1853,7 +1920,7 @@ void MSPUBParser::parseEscherShape(librevenge::RVNGInputStream *input, const Esc if (ptr_lineDashing) { m_collector->setShapeDash(*shapeSeqNum, getDash( - static_cast(*ptr_lineDashing), lineWidth, + *ptr_lineDashing, lineWidth, dotStyle)); } @@ -1878,11 +1945,11 @@ void MSPUBParser::parseEscherShape(librevenge::RVNGInputStream *input, const Esc unsigned *ptr_beginArrowHeight = getIfExists(foptValues.m_scalarValues, FIELDID_BEGIN_ARROW_HEIGHT); m_collector->setShapeBeginArrow(*shapeSeqNum, Arrow( - ptr_beginArrowStyle ? (ArrowStyle)(*ptr_beginArrowStyle) : + ptr_beginArrowStyle ? readArrowStyle(*ptr_beginArrowStyle) : NO_ARROW, - ptr_beginArrowWidth ? (ArrowSize)(*ptr_beginArrowWidth) : + ptr_beginArrowWidth ? readArrowSize(*ptr_beginArrowWidth) : MEDIUM, - ptr_beginArrowHeight ? (ArrowSize)(*ptr_beginArrowHeight) : + ptr_beginArrowHeight ? readArrowSize(*ptr_beginArrowHeight) : MEDIUM)); unsigned *ptr_endArrowStyle = getIfExists(foptValues.m_scalarValues, FIELDID_END_ARROW_STYLE); @@ -1891,11 +1958,11 @@ void MSPUBParser::parseEscherShape(librevenge::RVNGInputStream *input, const Esc unsigned *ptr_endArrowHeight = getIfExists(foptValues.m_scalarValues, FIELDID_END_ARROW_HEIGHT); m_collector->setShapeEndArrow(*shapeSeqNum, Arrow( - ptr_endArrowStyle ? (ArrowStyle)(*ptr_endArrowStyle) : + ptr_endArrowStyle ? readArrowStyle(*ptr_endArrowStyle) : NO_ARROW, - ptr_endArrowWidth ? (ArrowSize)(*ptr_endArrowWidth) : + ptr_endArrowWidth ? readArrowSize(*ptr_endArrowWidth) : MEDIUM, - ptr_endArrowHeight ? (ArrowSize)(*ptr_endArrowHeight) : + ptr_endArrowHeight ? readArrowSize(*ptr_endArrowHeight) : MEDIUM)); unsigned *shadowBoolProps = getIfExists(foptValues.m_scalarValues, FIELDID_SHADOW_BOOL_PROPS); @@ -1905,7 +1972,7 @@ void MSPUBParser::parseEscherShape(librevenge::RVNGInputStream *input, const Esc if ((shadowProps & FLAG_USE_FSHADOW) && (shadowProps & FLAG_USE_SHADOW)) { unsigned *ptr_shadowType = getIfExists(foptValues.m_scalarValues, FIELDID_SHADOW_TYPE); - auto shadowType = static_cast(ptr_shadowType ? *ptr_shadowType : 0); + const unsigned shadowType = ptr_shadowType ? *ptr_shadowType : 0; unsigned *shadowColor = getIfExists(foptValues.m_scalarValues, FIELDID_SHADOW_COLOR); unsigned *shadowHColor = getIfExists(foptValues.m_scalarValues, FIELDID_SHADOW_HIGHLIGHT); unsigned *shadowOpacity = getIfExists(foptValues.m_scalarValues, FIELDID_SHADOW_OPACITY); @@ -1966,7 +2033,7 @@ void MSPUBParser::parseEscherShape(librevenge::RVNGInputStream *input, const Esc int coordSystemWidth = int64_t(thisParentCoordinateSystem.m_xe) - thisParentCoordinateSystem.m_xs; if (coordSystemWidth == 0) coordSystemWidth = 1; - int coordSystemHeight = thisParentCoordinateSystem.m_ye - thisParentCoordinateSystem.m_ys; + int coordSystemHeight = int64_t(thisParentCoordinateSystem.m_ye) - thisParentCoordinateSystem.m_ys; if (coordSystemHeight == 0) coordSystemHeight = 1; int groupWidth = int64_t(parentGroupAbsoluteCoord.m_xe) - parentGroupAbsoluteCoord.m_xs; @@ -2010,8 +2077,8 @@ void MSPUBParser::parseEscherShape(librevenge::RVNGInputStream *input, const Esc std::shared_ptr MSPUBParser::getNewFill(const std::map &foptProperties, bool &skipIfNotBg, std::map > &foptValues) { - const FillType *ptr_fillType = (FillType *)getIfExists_const(foptProperties, FIELDID_FILL_TYPE); - FillType fillType = ptr_fillType ? *ptr_fillType : SOLID; + const unsigned *ptr_fillType = getIfExists_const(foptProperties, FIELDID_FILL_TYPE); + unsigned fillType = ptr_fillType ? *ptr_fillType : unsigned(SOLID); switch (fillType) { case SOLID: diff --git a/src/lib/PolygonUtils.cpp b/src/lib/PolygonUtils.cpp index 3497b49..85c75a5 100644 --- a/src/lib/PolygonUtils.cpp +++ b/src/lib/PolygonUtils.cpp @@ -5242,7 +5242,7 @@ const CustomShape CS_ACTION_BUTTON_MOVIE( 21600, 21600, nullptr, 0); -const CustomShape *getCustomShape(ShapeType type) +const CustomShape *getCustomShape(unsigned type) { switch (type) { @@ -5708,7 +5708,7 @@ struct LineInfo } -void drawEmulatedLine(std::shared_ptr shape, ShapeType shapeType, const std::vector &lines, +void drawEmulatedLine(std::shared_ptr shape, unsigned shapeType, const std::vector &lines, Vector2D center, VectorTransformation2D transform, double x, double y, double scaleX, double scaleY, bool drawStroke, librevenge::RVNGPropertyList &graphicsProps, librevenge::RVNGDrawingInterface *painter, @@ -5870,6 +5870,10 @@ void getRayEllipseIntersection(double initX, double initY, double rx, double ry, librevenge::RVNGPropertyList calcClipPath(const std::vector &verts, double x, double y, double height, double width, VectorTransformation2D transform, std::shared_ptr shape) { librevenge::RVNGPropertyList vertices; + if (!shape) + { + return vertices; + } Vector2D center(x + width / 2, y + height / 2); double scaleX = width / shape->m_coordWidth; double scaleY = height / shape->m_coordHeight; @@ -5892,7 +5896,7 @@ librevenge::RVNGPropertyList calcClipPath(const std::vector &verts, doub return vertices; } -void writeCustomShape(ShapeType shapeType, librevenge::RVNGPropertyList &graphicsProps, librevenge::RVNGDrawingInterface *painter, double x, double y, double height, double width, bool closeEverything, VectorTransformation2D transform, std::vector lines, std::function calculator, const std::vector &palette, std::shared_ptr shape) +void writeCustomShape(unsigned shapeType, librevenge::RVNGPropertyList &graphicsProps, librevenge::RVNGDrawingInterface *painter, double x, double y, double height, double width, bool closeEverything, VectorTransformation2D transform, std::vector lines, std::function calculator, const std::vector &palette, std::shared_ptr shape) { MSPUB_DEBUG_MSG(("***STARTING CUSTOM SHAPE***\n")); if (!shape) @@ -6359,7 +6363,7 @@ void writeCustomShape(ShapeType shapeType, librevenge::RVNGPropertyList &graphic } } -bool isShapeTypeRectangle(ShapeType type) +bool isShapeTypeRectangle(unsigned type) { return type == RECTANGLE || type == TEXT_BOX; } diff --git a/src/lib/PolygonUtils.h b/src/lib/PolygonUtils.h index df0e05e..27ef695 100644 --- a/src/lib/PolygonUtils.h +++ b/src/lib/PolygonUtils.h @@ -111,10 +111,10 @@ struct DynamicCustomShape std::shared_ptr getFromDynamicCustomShape(const DynamicCustomShape &dcs); -const CustomShape *getCustomShape(ShapeType type); -bool isShapeTypeRectangle(ShapeType type); +const CustomShape *getCustomShape(unsigned type); +bool isShapeTypeRectangle(unsigned type); librevenge::RVNGPropertyList calcClipPath(const std::vector &verts, double x, double y, double height, double width, VectorTransformation2D transform, std::shared_ptr shape); -void writeCustomShape(ShapeType shapeType, librevenge::RVNGPropertyList &graphicsProps, librevenge::RVNGDrawingInterface *painter, double x, double y, double height, double width, bool closeEverything, VectorTransformation2D transform, std::vector lines, std::function calculator, const std::vector &palette, std::shared_ptr shape); +void writeCustomShape(unsigned shapeType, librevenge::RVNGPropertyList &graphicsProps, librevenge::RVNGDrawingInterface *painter, double x, double y, double height, double width, bool closeEverything, VectorTransformation2D transform, std::vector lines, std::function calculator, const std::vector &palette, std::shared_ptr shape); } // libmspub #endif /* INCLUDED_POLYGONUTILS_H */ diff --git a/src/lib/Shadow.h b/src/lib/Shadow.h index 8cd9764..d7f7eb2 100644 --- a/src/lib/Shadow.h +++ b/src/lib/Shadow.h @@ -25,7 +25,7 @@ enum ShadowType }; struct Shadow { - ShadowType m_type; + unsigned m_type; int m_offsetXInEmu; int m_offsetYInEmu; int m_SecondOffsetXInEmu; @@ -35,7 +35,7 @@ struct Shadow double m_opacity; ColorReference m_color; ColorReference m_highColor; - Shadow(ShadowType type, int offsetXInEmu, int offsetYInEmu, int secondOffsetXInEmu, int secondOffsetYInEmu, + Shadow(unsigned type, int offsetXInEmu, int offsetYInEmu, int secondOffsetXInEmu, int secondOffsetYInEmu, double originXInEmu, double originYInEmu, double opacity, ColorReference color, ColorReference colorH) : m_type(type), m_offsetXInEmu(offsetXInEmu), m_offsetYInEmu(offsetYInEmu), diff --git a/src/lib/ShapeInfo.h b/src/lib/ShapeInfo.h index ff50787..d69628d 100644 --- a/src/lib/ShapeInfo.h +++ b/src/lib/ShapeInfo.h @@ -36,8 +36,8 @@ namespace libmspub void noop(const CustomShape *); struct ShapeInfo { - boost::optional m_type; - boost::optional m_cropType; + boost::optional m_type; + boost::optional m_cropType; boost::optional m_imgIndex; boost::optional m_borderImgIndex; boost::optional m_coordinates;