git: 9front

Download patch

ref: 1f7c0d20c381bebf89c75efbd58ab6c2ea8bc1e7
parent: fdb072ba76adbe5c6d4f351182cf5e7f222b6762
author: cinap_lenrek <cinap_lenrek@gmx.de>
date: Sun Jun 16 15:01:46 EDT 2013

draw: add badrect() function to reject zero, negative size or orverly huge rectangles

not checking the rectangle dimensions causes integer overflows
and memory corruption. adding a new badrect() function that checks
for these cases.

--- a/sys/include/ape/draw.h
+++ b/sys/include/ape/draw.h
@@ -408,6 +408,7 @@
 extern int		cmap2rgba(int);
 extern void		icossin(int, int*, int*);
 extern void		icossin2(int, int, int*, int*);
+extern int		badrect(Rectangle);
 
 /*
  * Graphics
--- a/sys/include/draw.h
+++ b/sys/include/draw.h
@@ -401,6 +401,7 @@
 extern int		cmap2rgba(int);
 extern void		icossin(int, int*, int*);
 extern void		icossin2(int, int, int*, int*);
+extern int		badrect(Rectangle);
 
 /*
  * Graphics
--- a/sys/src/libdraw/alloc.c
+++ b/sys/src/libdraw/alloc.c
@@ -26,6 +26,10 @@
 	err = 0;
 	i = 0;
 
+	if(badrect(r)){
+		werrstr("bad rectangle");
+		return nil;
+	}
 	if(chan == 0){
 		werrstr("bad channel descriptor");
 		return nil;
--- /dev/null
+++ b/sys/src/libdraw/badrect.c
@@ -1,0 +1,22 @@
+#include <u.h>
+#include <libc.h>
+#include <draw.h>
+
+/*
+ * check for zero, negative size or insanely huge rectangle.
+ */
+int
+badrect(Rectangle r)
+{
+	int x, y;
+	uint z;
+
+	x = Dx(r);
+	y = Dy(r);
+	if(x > 0 && y > 0){
+		z = x*y;
+		if(z/x == y && z < 0x10000000)
+			return 0;
+	}
+	return 1;
+}
--- a/sys/src/libdraw/mkfile
+++ b/sys/src/libdraw/mkfile
@@ -6,6 +6,7 @@
 	alloc.$O\
 	allocimagemix.$O\
 	arith.$O\
+	badrect.$O\
 	bezier.$O\
 	border.$O\
 	buildfont.$O\
--- a/sys/src/libmemdraw/alloc.c
+++ b/sys/src/libmemdraw/alloc.c
@@ -27,14 +27,14 @@
 	ulong l;
 	Memimage *i;
 
-	if(Dx(r) <= 0 || Dy(r) <= 0){
-		werrstr("bad rectangle %R", r);
-		return nil;
-	}
 	if((d = chantodepth(chan)) == 0) {
 		werrstr("bad channel descriptor %.8lux", chan);
 		return nil;
 	}
+	if(badrect(r)){
+		werrstr("bad rectangle %R", r);
+		return nil;
+	}
 
 	l = wordsperline(r, d);
 
@@ -76,8 +76,13 @@
 		werrstr("bad channel descriptor %.8lux", chan);
 		return nil;
 	}
+	if(badrect(r)){
+		werrstr("bad rectangle %R", r);
+		return nil;
+	}
 
 	l = wordsperline(r, d);
+
 	nw = l*Dy(r);
 	md = malloc(sizeof(Memdata));
 	if(md == nil)
--- a/sys/src/libmemdraw/cload.c
+++ b/sys/src/libmemdraw/cload.c
@@ -9,7 +9,7 @@
 	int y, bpl, c, cnt, offs;
 	uchar mem[NMEM], *memp, *omemp, *emem, *linep, *elinep, *u, *eu;
 
-	if(!rectinrect(r, i->r))
+	if(badrect(r) || !rectinrect(r, i->r))
 		return -1;
 	bpl = bytesperline(r, i->depth);
 	u = data;
--- a/sys/src/libmemdraw/draw.c
+++ b/sys/src/libmemdraw/draw.c
@@ -228,7 +228,7 @@
 	int splitcoords;
 	Rectangle omr;
 
-	if(r->min.x>=r->max.x || r->min.y>=r->max.y)
+	if(badrect(*r))
 		return 0;
 	splitcoords = (p0->x!=p1->x) || (p0->y!=p1->y);
 	/* clip to destination */
--- a/sys/src/libmemdraw/load.c
+++ b/sys/src/libmemdraw/load.c
@@ -10,7 +10,7 @@
 	Memdrawparam par;
 	uchar *q;
 
-	if(!rectinrect(r, i->r))
+	if(badrect(r) || !rectinrect(r, i->r))
 		return -1;
 
 	memset(&par, 0, sizeof par);
--- a/sys/src/libmemdraw/unload.c
+++ b/sys/src/libmemdraw/unload.c
@@ -9,7 +9,7 @@
 	int y, l;
 	uchar *q;
 
-	if(!rectinrect(r, i->r))
+	if(badrect(r) || !rectinrect(r, i->r))
 		return -1;
 	l = bytesperline(r, i->depth);
 	if(ndata < l*Dy(r))
--