summaryrefslogtreecommitdiff
path: root/image
diff options
context:
space:
mode:
authorwolfbeast <mcwerewolf@gmail.com>2018-12-13 14:25:47 +0100
committerwolfbeast <mcwerewolf@gmail.com>2018-12-13 19:48:31 +0100
commite80c7360235d5c3d6d5e2a615ad3909c3487dc7d (patch)
tree8e7219120f7f699ee726bdaf57888123c8d9124f /image
parentb62191e06e90cc0847e17d07e9db97747f581ab7 (diff)
downloaduxp-e80c7360235d5c3d6d5e2a615ad3909c3487dc7d.tar.gz
Avoid overflow in nsPNGEncoder::WriteCallback.
Diffstat (limited to 'image')
-rw-r--r--image/encoders/png/nsPNGEncoder.cpp52
-rw-r--r--image/encoders/png/nsPNGEncoder.h1
2 files changed, 40 insertions, 13 deletions
diff --git a/image/encoders/png/nsPNGEncoder.cpp b/image/encoders/png/nsPNGEncoder.cpp
index 66294146df..abe6f35b42 100644
--- a/image/encoders/png/nsPNGEncoder.cpp
+++ b/image/encoders/png/nsPNGEncoder.cpp
@@ -9,6 +9,7 @@
#include "nsStreamUtils.h"
#include "nsString.h"
#include "prprf.h"
+#include "mozilla/CheckedInt.h"
using namespace mozilla;
@@ -703,30 +704,55 @@ nsPNGEncoder::WriteCallback(png_structp png, png_bytep data,
return;
}
- if (that->mImageBufferUsed + size > that->mImageBufferSize) {
+ CheckedUint32 sizeNeeded = CheckedUint32(that->mImageBufferUsed) + size;
+ if (!sizeNeeded.isValid()) {
+ // Take the lock to ensure that nobody is trying to read from the buffer
+ // we are destroying
+ ReentrantMonitorAutoEnter autoEnter(that->mReentrantMonitor);
+
+ that->NullOutImageBuffer();
+ return;
+ }
+
+ if (sizeNeeded.value() > that->mImageBufferSize) {
// When we're reallocing the buffer we need to take the lock to ensure
// that nobody is trying to read from the buffer we are destroying
ReentrantMonitorAutoEnter autoEnter(that->mReentrantMonitor);
- // expand buffer, just double each time
- that->mImageBufferSize *= 2;
- uint8_t* newBuf = (uint8_t*)realloc(that->mImageBuffer,
- that->mImageBufferSize);
- if (!newBuf) {
- // can't resize, just zero (this will keep us from writing more)
- free(that->mImageBuffer);
- that->mImageBuffer = nullptr;
- that->mImageBufferSize = 0;
- that->mImageBufferUsed = 0;
- return;
+ while (sizeNeeded.value() > that->mImageBufferSize) {
+ // expand buffer, just double each time
+ CheckedUint32 bufferSize = CheckedUint32(that->mImageBufferSize) * 2;
+ if (!bufferSize.isValid()) {
+ that->NullOutImageBuffer();
+ return;
+ }
+ that->mImageBufferSize *= 2;
+ uint8_t* newBuf = (uint8_t*)realloc(that->mImageBuffer,
+ that->mImageBufferSize);
+ if (!newBuf) {
+ // can't resize, just zero (this will keep us from writing more)
+ that->NullOutImageBuffer();
+ return;
+ }
+ that->mImageBuffer = newBuf;
}
- that->mImageBuffer = newBuf;
}
+
memcpy(&that->mImageBuffer[that->mImageBufferUsed], data, size);
that->mImageBufferUsed += size;
that->NotifyListener();
}
+void nsPNGEncoder::NullOutImageBuffer()
+{
+ mReentrantMonitor.AssertCurrentThreadIn();
+
+ free(mImageBuffer);
+ mImageBuffer = nullptr;
+ mImageBufferSize = 0;
+ mImageBufferUsed = 0;
+}
+
void
nsPNGEncoder::NotifyListener()
{
diff --git a/image/encoders/png/nsPNGEncoder.h b/image/encoders/png/nsPNGEncoder.h
index 95e7d5c195..8c2239c119 100644
--- a/image/encoders/png/nsPNGEncoder.h
+++ b/image/encoders/png/nsPNGEncoder.h
@@ -54,6 +54,7 @@ protected:
static void WarningCallback(png_structp png_ptr, png_const_charp warning_msg);
static void ErrorCallback(png_structp png_ptr, png_const_charp error_msg);
static void WriteCallback(png_structp png, png_bytep data, png_size_t size);
+ void NullOutImageBuffer();
void NotifyListener();
png_struct* mPNG;