gdk-pixubuf bug + patch
- From: Mathieu Lacage <mathieu gnu org>
- To: gtk-devel-list gnome org
- Subject: gdk-pixubuf bug + patch
- Date: 06 Aug 2001 21:08:50 +0000
hi all,
while playing with gdk-pixbuf, I noticed that a call to gdk_pixbuf_scale
with very small values makes the scaler segfault.
So, I fixed it in the NEAREST case (patch attached). The other modes
still segfault: I have tried unsuccessfully to fix them.
Mathieu
--
Mathieu Lacage <mathieu gnu org>
Portable: <lacage orange fr>
? patch
Index: gdk-pixbuf/gdk-pixbuf-scale.c
===================================================================
RCS file: /cvs/gnome/gdk-pixbuf/gdk-pixbuf/gdk-pixbuf-scale.c,v
retrieving revision 1.5
diff -u -r1.5 gdk-pixbuf-scale.c
--- gdk-pixbuf/gdk-pixbuf-scale.c 2000/04/24 05:28:01 1.5
+++ gdk-pixbuf/gdk-pixbuf-scale.c 2001/08/06 16:39:01
@@ -27,6 +27,13 @@
+#define MAXVAL ((1<<15)-1)
+#define MINVAL (((double)1)/(1<<14))
+
+
+#define abs_double(x) ((x)<0)?-(x):(x)
+#define pad(x) ((x)<MINVAL)?MINVAL:((x>MAXVAL)?(MAXVAL):(x))
+
/**
* gdk_pixbuf_scale:
* @src: a #GdkPixbuf
@@ -45,6 +52,11 @@
* translating by @offset_x and @offset_y, then renders the rectangle
* (@dest,@dest_y,@dest_width,@dest_height) of the resulting image onto the
* destination drawable replacing the previous contents.
+ * If @scale_x or @scale_y are negative, their absolute value is used as scaling
+ * factor.
+ * If @scale_x or @scale_y are smaller than (1/1<<14), the (1/1<<14) scaling
+ * factor is used. If they are bigger than (1<<15-1), the (1<<15-1) scaling factor
+ * is used.
**/
void
gdk_pixbuf_scale (const GdkPixbuf *src,
@@ -66,6 +78,8 @@
offset_x = floor (offset_x + 0.5);
offset_y = floor (offset_y + 0.5);
+ scale_x = pad (abs_double (scale_x));
+ scale_y = pad (abs_double (scale_y));
pixops_scale (dest->pixels + dest_y * dest->rowstride + dest_x * dest->n_channels,
dest_x - offset_x, dest_y - offset_y,
@@ -95,6 +109,11 @@
* translating by @offset_x and @offset_y, then composites the rectangle
* (@dest,@dest_y,@dest_width,@dest_height) of the resulting image onto the
* destination drawable.
+ * If @scale_x or @scale_y are negative, their absolute value is used as scaling
+ * factor.
+ * If @scale_x or @scale_y are smaller than (1/1<<14), the (1/1<<14) scaling
+ * factor is used. If they are bigger than (1<<15-1), the (1<<15-1) scaling factor
+ * is used.
**/
void
gdk_pixbuf_composite (const GdkPixbuf *src,
@@ -118,6 +137,9 @@
offset_x = floor (offset_x + 0.5);
offset_y = floor (offset_y + 0.5);
+ scale_x = pad (abs_double (scale_x));
+ scale_y = pad (abs_double (scale_y));
+
pixops_composite (dest->pixels + dest_y * dest->rowstride + dest_x * dest->n_channels,
dest_x - offset_x, dest_y - offset_y,
dest_x + dest_width - offset_x, dest_y + dest_height - offset_y,
@@ -152,6 +174,11 @@
* (@dest,@dest_y,@dest_width,@dest_height) of the resulting image with
* a checkboard of the colors @color1 and @color2 and renders it onto the
* destination drawable.
+ * If @scale_x or @scale_y are negative, their absolute value is used as scaling
+ * factor.
+ * If @scale_x or @scale_y are smaller than (1/1<<14), the (1/1<<14) scaling
+ * factor is used. If they are bigger than (1<<15-1), the (1<<15-1) scaling factor
+ * is used.
**/
void
gdk_pixbuf_composite_color (const GdkPixbuf *src,
@@ -180,6 +207,8 @@
offset_x = floor (offset_x + 0.5);
offset_y = floor (offset_y + 0.5);
+ scale_x = pad (abs_double (scale_x));
+ scale_y = pad (abs_double (scale_y));
pixops_composite_color (dest->pixels + dest_y * dest->rowstride + dest_x * dest->n_channels,
dest_x - offset_x, dest_y - offset_y,
Index: gdk-pixbuf/pixops/pixops.c
===================================================================
RCS file: /cvs/gnome/gdk-pixbuf/gdk-pixbuf/pixops/pixops.c,v
retrieving revision 1.16
diff -u -r1.16 pixops.c
--- gdk-pixbuf/pixops/pixops.c 2001/03/01 23:23:09 1.16
+++ gdk-pixbuf/pixops/pixops.c 2001/08/06 16:39:04
@@ -47,6 +47,9 @@
return check_shift;
}
+#define MAXVAL 2147483647 /* 2^31 - 1 */
+#define pad(x) (x > MAXVAL)?(gint32)MAXVAL:((x < -MAXVAL)?(gint32)-MAXVAL:(x))
+
static void
pixops_scale_nearest (guchar *dest_buf,
int render_x0,
@@ -66,14 +69,21 @@
double scale_y)
{
int i, j;
- int x;
- int x_step = (1 << SCALE_SHIFT) / scale_x;
- int y_step = (1 << SCALE_SHIFT) / scale_y;
+ gint32 x;
+ /* at worst, scale_x = 1/1<<14 which means that x_step = 1<<(14+SCALE_SHIFT) which means NO overflow
+ if SCALE_SHIFT is smaller than 16. */
+ gint32 x_step = (1 << SCALE_SHIFT) / scale_x;
+ gint32 y_step = (1 << SCALE_SHIFT) / scale_y;
+ const guchar *end_src_buf;
#define INNER_LOOP(SRC_CHANNELS,DEST_CHANNELS) \
for (j=0; j < (render_x1 - render_x0); j++) \
{ \
- const guchar *p = src + (x >> SCALE_SHIFT) * SRC_CHANNELS; \
+ const guchar *p = src + ((x + (1<<(SCALE_SHIFT-1))) >> SCALE_SHIFT) * SRC_CHANNELS; \
+ if (p > (src+src_rowstride) || p < src) \
+ { \
+ break; \
+ } \
\
dest[0] = p[0]; \
dest[1] = p[1]; \
@@ -88,15 +98,22 @@
} \
\
dest += DEST_CHANNELS; \
- x += x_step; \
+ x += x_step; \
}
+ end_src_buf = src_buf + src_height * src_rowstride;
+
for (i = 0; i < (render_y1 - render_y0); i++)
{
- const guchar *src = src_buf + (((i + render_y0) * y_step + y_step / 2) >> SCALE_SHIFT) * src_rowstride;
+ const guchar *src = src_buf + (((i + render_y0) * y_step + (1<<(SCALE_SHIFT-1))/*+ y_step / 2*/) >> SCALE_SHIFT) * src_rowstride;
guchar *dest = dest_buf + i * dest_rowstride;
+
+ if (src > end_src_buf || src < src_buf)
+ {
+ break;
+ }
- x = render_x0 * x_step + x_step / 2;
+ x = render_x0 * x_step /*+ x_step / 2*/;
if (src_channels == 3)
{
@@ -154,22 +171,35 @@
int overall_alpha)
{
int i, j;
- int x;
- int x_step = (1 << SCALE_SHIFT) / scale_x;
- int y_step = (1 << SCALE_SHIFT) / scale_y;
+ gint32 x;
+ gint32 x_step = (1 << SCALE_SHIFT) / scale_x;
+ gint32 y_step = (1 << SCALE_SHIFT) / scale_y;
+ const guchar *end_src_buf;
+ end_src_buf = src_buf + src_height*src_rowstride;
+
for (i = 0; i < (render_y1 - render_y0); i++)
{
- const guchar *src = src_buf + (((i + render_y0) * y_step + y_step / 2) >> SCALE_SHIFT) * src_rowstride;
+ const guchar *src = src_buf + (((i + render_y0) * y_step + (1<<(SCALE_SHIFT-1))/*y_step / 2*/) >> SCALE_SHIFT) * src_rowstride;
guchar *dest = dest_buf + i * dest_rowstride;
+
+ if (src < src_buf || src > end_src_buf)
+ {
+ break;
+ }
- x = render_x0 * x_step + x_step / 2;
+ x = render_x0 * x_step /*+ x_step / 2*/;
for (j=0; j < (render_x1 - render_x0); j++)
{
- const guchar *p = src + (x >> SCALE_SHIFT) * src_channels;
+ const guchar *p = src + ((x + (1<<(SCALE_SHIFT-1))) >> SCALE_SHIFT) * src_channels;
unsigned int a0;
+ if (p < src || p > (src+src_rowstride))
+ {
+ break;
+ }
+
if (src_has_alpha)
a0 = (p[3] * overall_alpha) / 0xff;
else
@@ -237,18 +267,26 @@
guint32 color2)
{
int i, j;
- int x;
- int x_step = (1 << SCALE_SHIFT) / scale_x;
- int y_step = (1 << SCALE_SHIFT) / scale_y;
+ gint32 x;
+ gint32 x_step = (1 << SCALE_SHIFT) / scale_x;
+ gint32 y_step = (1 << SCALE_SHIFT) / scale_y;
int r1, g1, b1, r2, g2, b2;
int check_shift = get_check_shift (check_size);
+ const guchar *end_src_buf;
+
+ end_src_buf = src_buf + src_height*src_rowstride;
for (i = 0; i < (render_y1 - render_y0); i++)
{
- const guchar *src = src_buf + (((i + render_y0) * y_step + y_step/2) >> SCALE_SHIFT) * src_rowstride;
+ const guchar *src = src_buf + (((i + render_y0) * y_step + (1<<(SCALE_SHIFT-1)) /*y_step/2*/) >> SCALE_SHIFT) * src_rowstride;
guchar *dest = dest_buf + i * dest_rowstride;
- x = render_x0 * x_step + x_step / 2;
+ if (src < src_buf || src > end_src_buf)
+ {
+ break;
+ }
+
+ x = render_x0 * x_step /*+ x_step / 2 */;
if (((i + check_y) >> check_shift) & 1)
{
@@ -273,9 +311,14 @@
for (j=0 ; j < (render_x1 - render_x0); j++)
{
- const guchar *p = src + (x >> SCALE_SHIFT) * src_channels;
+ const guchar *p = src + ((x + (1<<(SCALE_SHIFT-1))) >> SCALE_SHIFT) * src_channels;
int a0;
int tmp;
+
+ if (p < src || p > (src+src_rowstride))
+ {
+ break;
+ }
if (src_has_alpha)
a0 = (p[3] * overall_alpha + 0xff) >> 8;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]