summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlbert Astals Cid <aacid@kde.org>2019-07-03 16:18:43 +0200
committerAlbert Astals Cid <aacid@kde.org>2019-07-04 09:17:38 +0200
commite69dc7a5a44c1c3fb97023d44e9e99a2bca75a46 (patch)
tree2c99dbe6fc7dca8d55b2fa50e6ff168333908a20
parentee7f64083109b18e09b50c0a35136060f7495dbe (diff)
TextOuputDev: Fix crash when grealloc would overflow
Introduces a new greallocn variant that doesn't free the pointer passed in case of error, since the pointer holds pointers inside, that would lead to leak of all those pointers
-rw-r--r--goo/gmem.h12
-rw-r--r--poppler/TextOutputDev.cc13
2 files changed, 17 insertions, 8 deletions
diff --git a/goo/gmem.h b/goo/gmem.h
index 9b187c1d..2eb88be7 100644
--- a/goo/gmem.h
+++ b/goo/gmem.h
@@ -14,7 +14,7 @@
// under GPL version 2 or later
//
// Copyright (C) 2005 Takashi Iwai <tiwai@suse.de>
-// Copyright (C) 2007-2010, 2017 Albert Astals Cid <aacid@kde.org>
+// Copyright (C) 2007-2010, 2017, 2019 Albert Astals Cid <aacid@kde.org>
// Copyright (C) 2008 Jonathan Kew <jonathan_kew@sil.org>
// Copyright (C) 2018 Adam Reichold <adam.reichold@t-online.de>
//
@@ -139,9 +139,11 @@ inline void *gmallocn3(int width, int height, int size, bool checkoverflow = fal
return gmalloc(bytes, checkoverflow);
}
-inline void *greallocn(void *p, int count, int size, bool checkoverflow = false) {
+inline void *greallocn(void *p, int count, int size, bool checkoverflow = false, bool free_p = true) {
if (count == 0) {
- gfree(p);
+ if (free_p) {
+ gfree(p);
+ }
return nullptr;
}
@@ -150,7 +152,9 @@ inline void *greallocn(void *p, int count, int size, bool checkoverflow = false)
std::fputs("Bogus memory allocation size\n", stderr);
if (checkoverflow) {
- gfree(p);
+ if (free_p) {
+ gfree(p);
+ }
return nullptr;
}
diff --git a/poppler/TextOutputDev.cc b/poppler/TextOutputDev.cc
index 6cb1d9aa..e62e088c 100644
--- a/poppler/TextOutputDev.cc
+++ b/poppler/TextOutputDev.cc
@@ -887,7 +887,6 @@ int TextPool::getBaseIdx(double base) {
}
void TextPool::addWord(TextWord *word) {
- TextWord **newPool;
int wordBaseIdx, newMinBaseIdx, newMaxBaseIdx, baseIdx;
TextWord *w0, *w1;
@@ -908,7 +907,7 @@ void TextPool::addWord(TextWord *word) {
}
} else if (wordBaseIdx < minBaseIdx) {
newMinBaseIdx = wordBaseIdx - 128;
- newPool = (TextWord **)gmallocn_checkoverflow(maxBaseIdx - newMinBaseIdx + 1,
+ TextWord **newPool = (TextWord **)gmallocn_checkoverflow(maxBaseIdx - newMinBaseIdx + 1,
sizeof(TextWord *));
if (unlikely(!newPool)) {
error(errSyntaxWarning, -1, "newPool would overflow");
@@ -925,8 +924,14 @@ void TextPool::addWord(TextWord *word) {
minBaseIdx = newMinBaseIdx;
} else if (wordBaseIdx > maxBaseIdx) {
newMaxBaseIdx = wordBaseIdx + 128;
- pool = (TextWord **)greallocn(pool, newMaxBaseIdx - minBaseIdx + 1,
- sizeof(TextWord *));
+ TextWord **reallocatedPool = (TextWord **)greallocn(pool, newMaxBaseIdx - minBaseIdx + 1,
+ sizeof(TextWord *), true /*checkoverflow*/, false /*free_pool*/);
+ if (!reallocatedPool) {
+ error(errSyntaxWarning, -1, "new pool size would overflow");
+ delete word;
+ return;
+ }
+ pool = reallocatedPool;
for (baseIdx = maxBaseIdx + 1; baseIdx <= newMaxBaseIdx; ++baseIdx) {
pool[baseIdx - minBaseIdx] = nullptr;
}