php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login

Patch 0002-Fix-double-free-in-gdImageWebPtr.patch for GD related Bug #73867

Patch version 2017-01-05 10:30 UTC

Return to Bug #73867 | Download this patch
Patch Revisions:

Developer: ondrej

From 484d3ad832900734e102e269a452ebc88a878312 Mon Sep 17 00:00:00 2001
From: "Christoph M. Becker" <cmbecker69@gmx.de>
Date: Tue, 16 Aug 2016 17:40:23 +0200
Subject: [PATCH 2/4] Fix double-free in gdImageWebPtr()

The issue is that gdImageWebpCtx() (which is called by gdImageWebpPtr() and
the other WebP output functions to do the real work) does not return whether
it succeeded or failed, so this is not checked in gdImageWebpPtr() and the
function wrongly assumes everything is okay, which is not, in this case,
because there is a size limitation for WebP, namely that the width and
height must by less than 16383.

We can't change the signature of gdImageWebpCtx() for API compatibility
reasons, so we introduce the static helper _gdImageWebpCtx() which returns
success respective failure, so gdImageWebpPtr() and gdImageWebpPtrEx() can
check the return value. We leave it solely to libwebp for now to report
warnings regarding the failing write.

This issue had been reported by Ibrahim El-Sayed to security@libgd.org.

CVE-2016-6912
---
 ext/gd/libgd/gd_webp.c | 38 ++++++++++++++++++++++++++------------
 1 file changed, 26 insertions(+), 12 deletions(-)

diff --git a/ext/gd/libgd/gd_webp.c b/ext/gd/libgd/gd_webp.c
index 0ce27e0..a7811e4 100644
--- a/ext/gd/libgd/gd_webp.c
+++ b/ext/gd/libgd/gd_webp.c
@@ -99,21 +99,22 @@ gdImagePtr gdImageCreateFromWebpCtx (gdIOCtx * infile)
 	return im;
 }
 
-void gdImageWebpCtx (gdImagePtr im, gdIOCtx * outfile, int quantization)
+static int _gdImageWebpCtx (gdImagePtr im, gdIOCtx * outfile, int quantization)
 {
 	uint8_t *argb;
 	int x, y;
 	uint8_t *p;
 	uint8_t *out;
 	size_t out_size;
+	int ret = 0;
 
 	if (im == NULL) {
-		return;
+		return 1;
 	}
 
 	if (!gdImageTrueColor(im)) {
 		zend_error(E_ERROR, "Paletter image not supported by webp");
-		return;
+		return 1;
 	}
 
 	if (quantization == -1) {
@@ -121,16 +122,16 @@ void gdImageWebpCtx (gdImagePtr im, gdIOCtx * outfile, int quantization)
 	}
 
 	if (overflow2(gdImageSX(im), 4)) {
-		return;
+		return 1;
 	}
 
 	if (overflow2(gdImageSX(im) * 4, gdImageSY(im))) {
-		return;
+		return 1;
 	}
 
 	argb = (uint8_t *)gdMalloc(gdImageSX(im) * 4 * gdImageSY(im));
 	if (!argb) {
-		return;
+		return 1;
 	}
 	p = argb;
 	for (y = 0; y < gdImageSY(im); y++) {
@@ -153,6 +154,7 @@ void gdImageWebpCtx (gdImagePtr im, gdIOCtx * outfile, int quantization)
 	out_size = WebPEncodeRGBA(argb, gdImageSX(im), gdImageSY(im), gdImageSX(im) * 4, quantization, &out);
 	if (out_size == 0) {
 		zend_error(E_ERROR, "gd-webp encoding failed");
+		ret = -1
 		goto freeargb;
 	}
 	gdPutBuf(out, out_size, outfile);
@@ -160,19 +162,25 @@ void gdImageWebpCtx (gdImagePtr im, gdIOCtx * outfile, int quantization)
 
 freeargb:
 	gdFree(argb);
+	return ret;
+}
+
+static int _gdImageWebpCtx (gdImagePtr im, gdIOCtx * outfile, int quantization)
+{
+	_gdImageWebpCtx(im, outfile, quality);
 }
 
 void gdImageWebpEx (gdImagePtr im, FILE * outFile, int quantization)
 {
 	gdIOCtx *out = gdNewFileCtx(outFile);
-	gdImageWebpCtx(im, out, quantization);
+	_gdImageWebpCtx(im, out, quantization);
 	out->gd_free(out);
 }
 
 void gdImageWebp (gdImagePtr im, FILE * outFile)
 {
 	gdIOCtx *out = gdNewFileCtx(outFile);
-	gdImageWebpCtx(im, out, -1);
+	_gdImageWebpCtx(im, out, -1);
 	out->gd_free(out);
 }
 
@@ -180,8 +188,11 @@ void * gdImageWebpPtr (gdImagePtr im, int *size)
 {
 	void *rv;
 	gdIOCtx *out = gdNewDynamicCtx(2048, NULL);
-	gdImageWebpCtx(im, out, -1);
-	rv = gdDPExtractData(out, size);
+	if (_gdImageWebpCtx(im, out, -1)) {
+		rv = NULL;
+	} else {
+		rv = gdDPExtractData(out, size);
+	}
 	out->gd_free(out);
 
 	return rv;
@@ -191,8 +202,11 @@ void * gdImageWebpPtrEx (gdImagePtr im, int *size, int quantization)
 {
 	void *rv;
 	gdIOCtx *out = gdNewDynamicCtx(2048, NULL);
-	gdImageWebpCtx(im, out, quantization);
-	rv = gdDPExtractData(out, size);
+	if (_gdImageWebpCtx(im, out, quantization)) {
+		rv = NULL;
+	} else {
+		rv = gdDPExtractData(out, size);
+	}
 	out->gd_free(out);
 	return rv;
 }
-- 
2.1.4

 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Sun Apr 28 02:01:30 2024 UTC