diff options
author | Albert Astals Cid <aacid@kde.org> | 2019-07-03 16:18:43 +0200 |
---|---|---|
committer | Albert Astals Cid <aacid@kde.org> | 2019-07-04 09:17:38 +0200 |
commit | e69dc7a5a44c1c3fb97023d44e9e99a2bca75a46 (patch) | |
tree | 2c99dbe6fc7dca8d55b2fa50e6ff168333908a20 | |
parent | ee7f64083109b18e09b50c0a35136060f7495dbe (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.h | 12 | ||||
-rw-r--r-- | poppler/TextOutputDev.cc | 13 |
2 files changed, 17 insertions, 8 deletions
@@ -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; } |