Commit 6be6e0f2 authored by Kristian Høgsberg's avatar Kristian Høgsberg
Browse files

2005-12-12 Kristian Høgsberg <krh@redhat.com>

	* poppler/TextOutputDev.cc:
	* qt/poppler-qt.h: GCC-4.1 fixes (#5031).

	* qt/Makefile.am (noinst_PROGRAMS): Only build qt test program if
	splash is enabled.

	* poppler/CairoOutputDev.cc: Remove unused grid snapping code,
	sidestepping #4507.

	* glib/poppler-document.h: Fix glib-mkenums warning (#4600).

	* poppler/Makefile.am (libpoppler_la_LIBADD): Add $(FREETYPE_LIBS)
	(#4514).

	* poppler/TextOutputDev.cc (TextWord::visitSelection,
	TextWord::visitSelection): Fix selection crash (#4402).

	* poppler/CairoOutputDev.h: Fix wrong cairo-ft.h include (#4413).

	* poppler/JPXStream.cc:
	* poppler/Stream.cc:
	* poppler/Stream.h: CVE-2005-3191 security fix.

	* fofi/FoFiTrueType.cc:
	* poppler/SplashOutputDev.cc: CAN-2005-2097 security fix.
parent 04ca240c
2005-12-12 Kristian Høgsberg <krh@redhat.com>
* poppler/TextOutputDev.cc:
* qt/poppler-qt.h: GCC-4.1 fixes (#5031).
* qt/Makefile.am (noinst_PROGRAMS): Only build qt test program if
splash is enabled.
* poppler/CairoOutputDev.cc: Remove unused grid snapping code,
sidestepping #4507.
* glib/poppler-document.h: Fix glib-mkenums warning (#4600).
* poppler/Makefile.am (libpoppler_la_LIBADD): Add $(FREETYPE_LIBS)
(#4514).
* poppler/TextOutputDev.cc (TextWord::visitSelection,
TextWord::visitSelection): Fix selection crash (#4402).
* poppler/CairoOutputDev.h: Fix wrong cairo-ft.h include (#4413).
* poppler/JPXStream.cc:
* poppler/Stream.cc:
* poppler/Stream.h: CVE-2005-3191 security fix.
* fofi/FoFiTrueType.cc:
* poppler/SplashOutputDev.cc: CAN-2005-2097 security fix.
2005-10-16 Kristian Høgsberg <krh@redhat.com>
* poppler/poppler-config.h.in (GCC_PRINTF_FORMAT): Remove evil
......
Release 0.4.3
- Fix selection crasher (Nickolay V. Shmyrev, #4402).
- Fix printing problem for single page output (#4555).
- Fix miscelanous compile problems/warnings.
- CVE-2005-3191 and CAN-2005-2097 security fixes.
Release 0.4.2
- Fix a rotation bug.
......
......@@ -1343,6 +1343,27 @@ void FoFiTrueType::parse() {
return;
}
// make sure the loca table is sane (correct length and entries are
// in bounds)
i = seekTable("loca");
if (tables[i].len < (nGlyphs + 1) * (locaFmt ? 4 : 2)) {
parsedOk = gFalse;
return;
}
for (j = 0; j <= nGlyphs; ++j) {
if (locaFmt) {
pos = (int)getU32BE(tables[i].offset + j*4, &parsedOk);
} else {
pos = getU16BE(tables[i].offset + j*2, &parsedOk);
}
if (pos < 0 || pos > len) {
parsedOk = gFalse;
}
}
if (!parsedOk) {
return;
}
// read the post table
readPostTable();
if (!parsedOk) {
......
......@@ -82,10 +82,7 @@ typedef enum /*< flags >*/
POPPLER_PERMISSIONS_OK_TO_MODIFY = 1 << 1,
POPPLER_PERMISSIONS_OK_TO_COPY = 1 << 2,
POPPLER_PERMISSIONS_OK_TO_ADD_NOTES = 1 << 3,
POPPLER_PERMISSIONS_FULL = (POPPLER_PERMISSIONS_OK_TO_PRINT
| POPPLER_PERMISSIONS_OK_TO_MODIFY
| POPPLER_PERMISSIONS_OK_TO_COPY
| POPPLER_PERMISSIONS_OK_TO_ADD_NOTES),
POPPLER_PERMISSIONS_FULL = (POPPLER_PERMISSIONS_OK_TO_PRINT | POPPLER_PERMISSIONS_OK_TO_MODIFY | POPPLER_PERMISSIONS_OK_TO_COPY | POPPLER_PERMISSIONS_OK_TO_ADD_NOTES)
} PopplerPermissions;
......
......@@ -246,8 +246,7 @@ void CairoOutputDev::updateFont(GfxState *state) {
cairo_set_font_matrix (cairo, &matrix);
}
void CairoOutputDev::doPath(GfxState *state, GfxPath *path,
GBool snapToGrid) {
void CairoOutputDev::doPath(GfxState *state, GfxPath *path) {
GfxSubpath *subpath;
double x1, y1, x2, y2, x3, y3;
int i, j;
......@@ -256,9 +255,6 @@ void CairoOutputDev::doPath(GfxState *state, GfxPath *path,
subpath = path->getSubpath(i);
if (subpath->getNumPoints() > 0) {
state->transform(subpath->getX(0), subpath->getY(0), &x1, &y1);
if (snapToGrid) {
x1 = round (x1); y1 = round (y1);
}
cairo_move_to (cairo, x1, y1);
LOG (printf ("move_to %f, %f\n", x1, y1));
j = 1;
......@@ -267,11 +263,6 @@ void CairoOutputDev::doPath(GfxState *state, GfxPath *path,
state->transform(subpath->getX(j), subpath->getY(j), &x1, &y1);
state->transform(subpath->getX(j+1), subpath->getY(j+1), &x2, &y2);
state->transform(subpath->getX(j+2), subpath->getY(j+2), &x3, &y3);
if (snapToGrid) {
x1 = round (x1); y1 = round (y1);
x2 = round (x2); y2 = round (y2);
x3 = round (x3); y3 = round (y3);
}
cairo_curve_to (cairo,
x1, y1,
x2, y2,
......@@ -280,9 +271,6 @@ void CairoOutputDev::doPath(GfxState *state, GfxPath *path,
j += 3;
} else {
state->transform(subpath->getX(j), subpath->getY(j), &x1, &y1);
if (snapToGrid) {
x1 = round (x1); y1 = round (y1);
}
cairo_line_to (cairo, x1, y1);
LOG(printf ("line_to %f, %f\n", x1, y1));
++j;
......@@ -297,7 +285,7 @@ void CairoOutputDev::doPath(GfxState *state, GfxPath *path,
}
void CairoOutputDev::stroke(GfxState *state) {
doPath (state, state->getPath(), gFalse);
doPath (state, state->getPath());
cairo_set_source_rgba (cairo,
stroke_color.r, stroke_color.g, stroke_color.b,
stroke_opacity);
......@@ -306,7 +294,7 @@ void CairoOutputDev::stroke(GfxState *state) {
}
void CairoOutputDev::fill(GfxState *state) {
doPath (state, state->getPath(), gFalse);
doPath (state, state->getPath());
cairo_set_fill_rule (cairo, CAIRO_FILL_RULE_WINDING);
cairo_set_source_rgba (cairo,
fill_color.r, fill_color.g, fill_color.b,
......@@ -316,7 +304,7 @@ void CairoOutputDev::fill(GfxState *state) {
}
void CairoOutputDev::eoFill(GfxState *state) {
doPath (state, state->getPath(), gFalse);
doPath (state, state->getPath());
cairo_set_fill_rule (cairo, CAIRO_FILL_RULE_EVEN_ODD);
cairo_set_source_rgb (cairo,
fill_color.r, fill_color.g, fill_color.b);
......@@ -325,14 +313,14 @@ void CairoOutputDev::eoFill(GfxState *state) {
}
void CairoOutputDev::clip(GfxState *state) {
doPath (state, state->getPath(), gFalse);
doPath (state, state->getPath());
cairo_set_fill_rule (cairo, CAIRO_FILL_RULE_WINDING);
cairo_clip (cairo);
LOG (printf ("clip\n"));
}
void CairoOutputDev::eoClip(GfxState *state) {
doPath (state, state->getPath(), gFalse);
doPath (state, state->getPath());
cairo_set_fill_rule (cairo, CAIRO_FILL_RULE_EVEN_ODD);
cairo_clip (cairo);
LOG (printf ("clip-eo\n"));
......
......@@ -15,7 +15,7 @@
#endif
#include "goo/gtypes.h"
#include <cairo/cairo-ft.h>
#include <cairo-ft.h>
#include "OutputDev.h"
#include "GfxState.h"
......@@ -133,7 +133,7 @@ public:
void setSurface (cairo_surface_t *surface);
protected:
void doPath(GfxState *state, GfxPath *path, GBool snapToGrid);
void doPath(GfxState *state, GfxPath *path);
GfxRGB fill_color;
GfxRGB stroke_color;
......
......@@ -7,6 +7,7 @@
//========================================================================
#include <config.h>
#include <limits.h>
#ifdef USE_GCC_PRAGMAS
#pragma implementation
......@@ -666,7 +667,7 @@ GBool JPXStream::readCodestream(Guint len) {
int segType;
GBool haveSIZ, haveCOD, haveQCD, haveSOT;
Guint precinctSize, style;
Guint segLen, capabilities, comp, i, j, r;
Guint segLen, capabilities, nTiles, comp, i, j, r;
//----- main header
haveSIZ = haveCOD = haveQCD = haveSOT = gFalse;
......@@ -701,8 +702,18 @@ GBool JPXStream::readCodestream(Guint len) {
/ img.xTileSize;
img.nYTiles = (img.ySize - img.yTileOffset + img.yTileSize - 1)
/ img.yTileSize;
img.tiles = (JPXTile *)gmalloc(img.nXTiles * img.nYTiles *
sizeof(JPXTile));
// check for overflow before allocating memory
if (img.nXTiles <= 0 || img.nYTiles <= 0 ||
img.nXTiles >= INT_MAX/img.nYTiles) {
error(getPos(), "Bad tile count in JPX SIZ marker segment");
return gFalse;
}
nTiles = img.nXTiles * img.nYTiles;
if (nTiles >= INT_MAX/sizeof(JPXTile)) {
error(getPos(), "Bad tile count in JPX SIZ marker segment");
return gFalse;
}
img.tiles = (JPXTile *)gmalloc(nTiles * sizeof(JPXTile));
for (i = 0; i < img.nXTiles * img.nYTiles; ++i) {
img.tiles[i].tileComps = (JPXTileComp *)gmalloc(img.nComps *
sizeof(JPXTileComp));
......
......@@ -89,7 +89,8 @@ libpoppler_la_LIBADD = \
$(cairo_libs) \
$(arthur_libs) \
$(libjpeg_libs) \
$(zlib_libs)
$(zlib_libs) \
$(FREETYPE_LIBS)
poppler_includedir = $(includedir)/poppler
poppler_include_HEADERS = \
......
......@@ -38,6 +38,35 @@
#include "splash/Splash.h"
#include "SplashOutputDev.h"
//------------------------------------------------------------------------
// Font substitutions
//------------------------------------------------------------------------
struct SplashOutFontSubst {
char *name;
double mWidth;
};
// index: {symbolic:12, fixed:8, serif:4, sans-serif:0} + bold*2 + italic
static SplashOutFontSubst splashOutSubstFonts[16] = {
{"Helvetica", 0.833},
{"Helvetica-Oblique", 0.833},
{"Helvetica-Bold", 0.889},
{"Helvetica-BoldOblique", 0.889},
{"Times-Roman", 0.788},
{"Times-Italic", 0.722},
{"Times-Bold", 0.833},
{"Times-BoldItalic", 0.778},
{"Courier", 0.600},
{"Courier-Oblique", 0.600},
{"Courier-Bold", 0.600},
{"Courier-BoldOblique", 0.600},
{"Symbol", 0.576},
{"Symbol", 0.576},
{"Symbol", 0.576},
{"Symbol", 0.576}
};
//------------------------------------------------------------------------
#define soutRound(x) ((int)(x + 0.5))
......@@ -49,7 +78,7 @@
class SplashOutFontFileID: public SplashFontFileID {
public:
SplashOutFontFileID(Ref *rA) { r = *rA; }
SplashOutFontFileID(Ref *rA) { r = *rA; substIdx = -1; }
~SplashOutFontFileID() {}
......@@ -58,9 +87,13 @@ public:
((SplashOutFontFileID *)id)->r.gen == r.gen;
}
void setSubstIdx(int substIdxA) { substIdx = substIdxA; }
int getSubstIdx() { return substIdx; }
private:
Ref r;
int substIdx;
};
//------------------------------------------------------------------------
......@@ -514,8 +547,36 @@ void SplashOutputDev::updateFont(GfxState *state) {
// look for a display font mapping or a substitute font
dfp = NULL;
if (gfxFont->getName()) {
dfp = globalParams->getDisplayFont(gfxFont);
if (gfxFont->isCIDFont()) {
if (((GfxCIDFont *)gfxFont)->getCollection()) {
dfp = globalParams->
getDisplayCIDFont(gfxFont->getName(),
((GfxCIDFont *)gfxFont)->getCollection());
}
} else {
if (gfxFont->getName()) {
dfp = globalParams->getDisplayFont(gfxFont->getName());
}
if (!dfp) {
// 8-bit font substitution
if (gfxFont->isFixedWidth()) {
substIdx = 8;
} else if (gfxFont->isSerif()) {
substIdx = 4;
} else {
substIdx = 0;
}
if (gfxFont->isBold()) {
substIdx += 2;
}
if (gfxFont->isItalic()) {
substIdx += 1;
}
substName = new GooString(splashOutSubstFonts[substIdx].name);
dfp = globalParams->getDisplayFont(substName);
delete substName;
id->setSubstIdx(substIdx);
}
}
if (!dfp) {
error(-1, "Couldn't find a font for '%s'",
......@@ -562,16 +623,19 @@ void SplashOutputDev::updateFont(GfxState *state) {
}
break;
case fontTrueType:
if (!(ff = FoFiTrueType::load(fileName->getCString()))) {
goto err2;
if ((ff = FoFiTrueType::load(fileName->getCString()))) {
codeToGID = ((Gfx8BitFont *)gfxFont)->getCodeToGIDMap(ff);
n = 256;
delete ff;
} else {
codeToGID = NULL;
n = 0;
}
codeToGID = ((Gfx8BitFont *)gfxFont)->getCodeToGIDMap(ff);
delete ff;
if (!(fontFile = fontEngine->loadTrueTypeFont(
id,
fileName->getCString(),
fileName == tmpFileName,
codeToGID, 256))) {
codeToGID, n))) {
error(-1, "Couldn't create a font for '%s'",
gfxFont->getName() ? gfxFont->getName()->getCString()
: "(unnamed)");
......@@ -617,6 +681,31 @@ void SplashOutputDev::updateFont(GfxState *state) {
m11 *= state->getHorizScaling();
m12 *= state->getHorizScaling();
// for substituted fonts: adjust the font matrix -- compare the
// width of 'm' in the original font and the substituted font
substIdx = ((SplashOutFontFileID *)fontFile->getID())->getSubstIdx();
if (substIdx >= 0) {
for (code = 0; code < 256; ++code) {
if ((name = ((Gfx8BitFont *)gfxFont)->getCharName(code)) &&
name[0] == 'm' && name[1] == '\0') {
break;
}
}
if (code < 256) {
w1 = ((Gfx8BitFont *)gfxFont)->getWidth(code);
w2 = splashOutSubstFonts[substIdx].mWidth;
if (!gfxFont->isSymbolic()) {
// if real font is substantially narrower than substituted
// font, reduce the font size accordingly
if (w1 > 0.01 && w1 < 0.9 * w2) {
w1 /= w2;
m11 *= w1;
m21 *= w1;
}
}
}
}
// create the scaled font
mat[0] = m11; mat[1] = -m12;
mat[2] = m21; mat[3] = -m22;
......@@ -1220,3 +1309,43 @@ void SplashOutputDev::setFillColor(int r, int g, int b) {
gray = 0.299 * rgb.r + 0.587 * rgb.g + 0.114 * rgb.g;
splash->setFillPattern(getColor(gray, &rgb));
}
SplashFont *SplashOutputDev::getFont(GooString *name, double *mat) {
DisplayFontParam *dfp;
Ref ref;
SplashOutFontFileID *id;
SplashFontFile *fontFile;
SplashFont *fontObj;
int i;
for (i = 0; i < 16; ++i) {
if (!name->cmp(splashOutSubstFonts[i].name)) {
break;
}
}
if (i == 16) {
return NULL;
}
ref.num = i;
ref.gen = -1;
id = new SplashOutFontFileID(&ref);
// check the font file cache
if ((fontFile = fontEngine->getFontFile(id))) {
delete id;
// load the font file
} else {
dfp = globalParams->getDisplayFont(name);
if (dfp->kind != displayFontT1) {
return NULL;
}
fontFile = fontEngine->loadType1Font(id, dfp->t1.fileName->getCString(),
gFalse, winAnsiEncoding);
}
// create the scaled font
fontObj = fontEngine->getFont(fontFile, (SplashCoord *)mat);
return fontObj;
}
......@@ -15,6 +15,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <limits.h>
#ifndef WIN32
#include <unistd.h>
#endif
......@@ -420,13 +421,28 @@ StreamPredictor::StreamPredictor(Stream *strA, int predictorA,
width = widthA;
nComps = nCompsA;
nBits = nBitsA;
predLine = NULL;
ok = gFalse;
if (width <= 0 || nComps <= 0 || nBits <= 0 ||
nComps >= INT_MAX/nBits ||
width >= INT_MAX/nComps/nBits) {
return;
}
nVals = width * nComps;
if (nVals + 7 <= 0) {
return;
}
pixBytes = (nComps * nBits + 7) >> 3;
rowBytes = ((nVals * nBits + 7) >> 3) + pixBytes;
if (rowBytes < 0) {
return;
}
predLine = (Guchar *)gmalloc(rowBytes);
memset(predLine, 0, rowBytes);
predIdx = rowBytes;
ok = gTrue;
}
StreamPredictor::~StreamPredictor() {
......@@ -1020,6 +1036,10 @@ LZWStream::LZWStream(Stream *strA, int predictor, int columns, int colors,
FilterStream(strA) {
if (predictor != 1) {
pred = new StreamPredictor(this, predictor, columns, colors, bits);
if (!pred->isOk()) {
delete pred;
pred = NULL;
}
} else {
pred = NULL;
}
......@@ -2907,6 +2927,10 @@ GBool DCTStream::readBaselineSOF() {
height = read16();
width = read16();
numComps = str->getChar();
if (numComps <= 0 || numComps > 4) {
error(getPos(), "Bad number of components in DCT stream", prec);
return gFalse;
}
if (prec != 8) {
error(getPos(), "Bad DCT precision %d", prec);
return gFalse;
......@@ -2933,6 +2957,10 @@ GBool DCTStream::readProgressiveSOF() {
height = read16();
width = read16();
numComps = str->getChar();
if (numComps <= 0 || numComps > 4) {
error(getPos(), "Bad number of components in DCT stream", prec);
return gFalse;
}
if (prec != 8) {
error(getPos(), "Bad DCT precision %d", prec);
return gFalse;
......@@ -2955,6 +2983,10 @@ GBool DCTStream::readScanInfo() {
length = read16() - 2;
scanInfo.numComps = str->getChar();
if (scanInfo.numComps <= 0 || scanInfo.numComps > 4) {
error(getPos(), "Bad number of components in DCT stream");
return gFalse;
}
--length;
if (length != 2 * scanInfo.numComps + 3) {
error(getPos(), "Bad DCT scan info block");
......@@ -3268,6 +3300,10 @@ FlateStream::FlateStream(Stream *strA, int predictor, int columns,
FilterStream(strA) {
if (predictor != 1) {
pred = new StreamPredictor(this, predictor, columns, colors, bits);
if (!pred->isOk()) {
delete pred;
pred = NULL;
}
} else {
pred = NULL;
}
......
......@@ -231,6 +231,8 @@ public:
~StreamPredictor();
GBool isOk() { return ok; }
int lookChar();
int getChar();
......@@ -248,6 +250,7 @@ private:
int rowBytes; // bytes per line
Guchar *predLine; // line buffer
int predIdx; // current index in predLine
GBool ok;
};
//------------------------------------------------------------------------
......
......@@ -3025,7 +3025,7 @@ public:
virtual void visitWord (TextWord *word, int begin, int end,
PDFRectangle *selection) { };
GooString *TextSelectionDumper::getText(void);
GooString *getText(void);
private:
TextLineFrag *frags;
......@@ -3351,8 +3351,8 @@ void TextLine::visitSelection(TextSelectionVisitor *visitor,
(selection->x2 < p->xMax && selection->y2 < p->yMax))
if (begin == NULL)
begin = p;
if ((selection->x1 > p->xMin && selection->y1 > p->yMin) ||
(selection->x2 > p->xMin && selection->y2 > p->yMin))
if ((selection->x1 > p->xMin && selection->y1 > p->yMin ||
selection->x2 > p->xMin && selection->y2 > p->yMin) && (begin != NULL))
end = p->next;
}
......@@ -3419,8 +3419,8 @@ void TextBlock::visitSelection(TextSelectionVisitor *visitor,
stop_y = selection->y1;
}
if (selection->x1 > p->xMin && selection->y1 > p->yMin ||
selection->x2 > p->xMin && selection->y2 > p->yMin)
if ((selection->x1 > p->xMin && selection->y1 > p->yMin ||
selection->x2 > p->xMin && selection->y2 > p->yMin) && (begin != NULL))
end = p->next;
}
......
......@@ -22,8 +22,12 @@ libpoppler_qt_la_LIBADD= \
$(POPPLER_QT_LIBS) \
$(FREETYPE_LIBS)
if BUILD_SPLASH_OUTPUT
noinst_PROGRAMS = test-poppler-qt
endif
test_poppler_qt_SOURCES = \
test-poppler-qt.cpp
......
......@@ -150,7 +150,7 @@ public:
UseOC
};
static Document *Document::load(const QString & filePath);
static Document *load(const QString & filePath);
Page *getPage(int index) const{ return new Page(this, index); }
......@@ -172,11 +172,11 @@ public:
bool okToAddNotes() const;
double getPDFVersion() const;
Document::~Document();
~Document();
private:
DocumentData *data;
Document::Document(DocumentData *dataA);
Document(DocumentData *dataA);
};
}
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment