[Bf-blender-cvs] [38131cc5e56] master: Fix T70356: Scaling up 1x1 pixel image reads past buffer bounds

Campbell Barton noreply at git.blender.org
Fri Jul 16 08:58:47 CEST 2021


Commit: 38131cc5e565e2334538798941f49e58644344fd
Author: Campbell Barton
Date:   Fri Jul 16 15:41:02 2021 +1000
Branches: master
https://developer.blender.org/rB38131cc5e565e2334538798941f49e58644344fd

Fix T70356: Scaling up 1x1 pixel image reads past buffer bounds

Also resolve a crash when when displaying thumbnails, see T89868.

===================================================================

M	source/blender/imbuf/intern/scaling.c

===================================================================

diff --git a/source/blender/imbuf/intern/scaling.c b/source/blender/imbuf/intern/scaling.c
index 4a964c64917..757ec5f4b41 100644
--- a/source/blender/imbuf/intern/scaling.c
+++ b/source/blender/imbuf/intern/scaling.c
@@ -1195,22 +1195,9 @@ static ImBuf *scaleupx(struct ImBuf *ibuf, int newx)
 {
   uchar *rect, *_newrect = NULL, *newrect;
   float *rectf, *_newrectf = NULL, *newrectf;
-  float sample, add;
-  float val_a, nval_a, diff_a;
-  float val_b, nval_b, diff_b;
-  float val_g, nval_g, diff_g;
-  float val_r, nval_r, diff_r;
-  float val_af, nval_af, diff_af;
-  float val_bf, nval_bf, diff_bf;
-  float val_gf, nval_gf, diff_gf;
-  float val_rf, nval_rf, diff_rf;
   int x, y;
   bool do_rect = false, do_float = false;
 
-  val_a = nval_a = diff_a = val_b = nval_b = diff_b = 0;
-  val_g = nval_g = diff_g = val_r = nval_r = diff_r = 0;
-  val_af = nval_af = diff_af = val_bf = nval_bf = diff_bf = 0;
-  val_gf = nval_gf = diff_gf = val_rf = nval_rf = diff_rf = 0;
   if (ibuf == NULL) {
     return NULL;
   }
@@ -1236,119 +1223,158 @@ static ImBuf *scaleupx(struct ImBuf *ibuf, int newx)
     }
   }
 
-  add = (ibuf->x - 1.001) / (newx - 1.0);
-
   rect = (uchar *)ibuf->rect;
   rectf = (float *)ibuf->rect_float;
   newrect = _newrect;
   newrectf = _newrectf;
 
-  for (y = ibuf->y; y > 0; y--) {
-
-    sample = 0;
-
+  /* Special case, copy all columns, needed since the scaling logic assumes there is at least
+   * two rows to interpolate between causing out of bounds read for 1px images, see T70356. */
+  if (UNLIKELY(ibuf->x == 1)) {
     if (do_rect) {
-      val_a = rect[0];
-      nval_a = rect[4];
-      diff_a = nval_a - val_a;
-      val_a += 0.5f;
-
-      val_b = rect[1];
-      nval_b = rect[5];
-      diff_b = nval_b - val_b;
-      val_b += 0.5f;
-
-      val_g = rect[2];
-      nval_g = rect[6];
-      diff_g = nval_g - val_g;
-      val_g += 0.5f;
-
-      val_r = rect[3];
-      nval_r = rect[7];
-      diff_r = nval_r - val_r;
-      val_r += 0.5f;
-
-      rect += 8;
+      for (y = ibuf->y; y > 0; y--) {
+        for (x = newx; x > 0; x--) {
+          memcpy(newrect, rect, sizeof(char[4]));
+          newrect += 4;
+        }
+        rect += 4;
+      }
     }
     if (do_float) {
-      val_af = rectf[0];
-      nval_af = rectf[4];
-      diff_af = nval_af - val_af;
+      for (y = ibuf->y; y > 0; y--) {
+        for (x = newx; x > 0; x--) {
+          memcpy(newrectf, rectf, sizeof(float[4]));
+          newrectf += 4;
+        }
+        rectf += 4;
+      }
+    }
+  }
+  else {
+    const float add = (ibuf->x - 1.001) / (newx - 1.0);
+    float sample;
 
-      val_bf = rectf[1];
-      nval_bf = rectf[5];
-      diff_bf = nval_bf - val_bf;
+    float val_a, nval_a, diff_a;
+    float val_b, nval_b, diff_b;
+    float val_g, nval_g, diff_g;
+    float val_r, nval_r, diff_r;
+    float val_af, nval_af, diff_af;
+    float val_bf, nval_bf, diff_bf;
+    float val_gf, nval_gf, diff_gf;
+    float val_rf, nval_rf, diff_rf;
 
-      val_gf = rectf[2];
-      nval_gf = rectf[6];
-      diff_gf = nval_gf - val_gf;
+    val_a = nval_a = diff_a = val_b = nval_b = diff_b = 0;
+    val_g = nval_g = diff_g = val_r = nval_r = diff_r = 0;
+    val_af = nval_af = diff_af = val_bf = nval_bf = diff_bf = 0;
+    val_gf = nval_gf = diff_gf = val_rf = nval_rf = diff_rf = 0;
 
-      val_rf = rectf[3];
-      nval_rf = rectf[7];
-      diff_rf = nval_rf - val_rf;
+    for (y = ibuf->y; y > 0; y--) {
 
-      rectf += 8;
-    }
-    for (x = newx; x > 0; x--) {
-      if (sample >= 1.0f) {
-        sample -= 1.0f;
+      sample = 0;
 
-        if (do_rect) {
-          val_a = nval_a;
-          nval_a = rect[0];
-          diff_a = nval_a - val_a;
-          val_a += 0.5f;
-
-          val_b = nval_b;
-          nval_b = rect[1];
-          diff_b = nval_b - val_b;
-          val_b += 0.5f;
-
-          val_g = nval_g;
-          nval_g = rect[2];
-          diff_g = nval_g - val_g;
-          val_g += 0.5f;
-
-          val_r = nval_r;
-          nval_r = rect[3];
-          diff_r = nval_r - val_r;
-          val_r += 0.5f;
-          rect += 4;
-        }
-        if (do_float) {
-          val_af = nval_af;
-          nval_af = rectf[0];
-          diff_af = nval_af - val_af;
+      if (do_rect) {
+        val_a = rect[0];
+        nval_a = rect[4];
+        diff_a = nval_a - val_a;
+        val_a += 0.5f;
+
+        val_b = rect[1];
+        nval_b = rect[5];
+        diff_b = nval_b - val_b;
+        val_b += 0.5f;
+
+        val_g = rect[2];
+        nval_g = rect[6];
+        diff_g = nval_g - val_g;
+        val_g += 0.5f;
+
+        val_r = rect[3];
+        nval_r = rect[7];
+        diff_r = nval_r - val_r;
+        val_r += 0.5f;
+
+        rect += 8;
+      }
+      if (do_float) {
+        val_af = rectf[0];
+        nval_af = rectf[4];
+        diff_af = nval_af - val_af;
 
-          val_bf = nval_bf;
-          nval_bf = rectf[1];
-          diff_bf = nval_bf - val_bf;
+        val_bf = rectf[1];
+        nval_bf = rectf[5];
+        diff_bf = nval_bf - val_bf;
 
-          val_gf = nval_gf;
-          nval_gf = rectf[2];
-          diff_gf = nval_gf - val_gf;
+        val_gf = rectf[2];
+        nval_gf = rectf[6];
+        diff_gf = nval_gf - val_gf;
 
-          val_rf = nval_rf;
-          nval_rf = rectf[3];
-          diff_rf = nval_rf - val_rf;
-          rectf += 4;
-        }
-      }
-      if (do_rect) {
-        newrect[0] = val_a + sample * diff_a;
-        newrect[1] = val_b + sample * diff_b;
-        newrect[2] = val_g + sample * diff_g;
-        newrect[3] = val_r + sample * diff_r;
-        newrect += 4;
+        val_rf = rectf[3];
+        nval_rf = rectf[7];
+        diff_rf = nval_rf - val_rf;
+
+        rectf += 8;
       }
-      if (do_float) {
-        newrectf[0] = val_af + sample * diff_af;
-        newrectf[1] = val_bf + sample * diff_bf;
-        newrectf[2] = val_gf + sample * diff_gf;
-        newrectf[3] = val_rf + sample * diff_rf;
-        newrectf += 4;
+      for (x = newx; x > 0; x--) {
+        if (sample >= 1.0f) {
+          sample -= 1.0f;
+
+          if (do_rect) {
+            val_a = nval_a;
+            nval_a = rect[0];
+            diff_a = nval_a - val_a;
+            val_a += 0.5f;
+
+            val_b = nval_b;
+            nval_b = rect[1];
+            diff_b = nval_b - val_b;
+            val_b += 0.5f;
+
+            val_g = nval_g;
+            nval_g = rect[2];
+            diff_g = nval_g - val_g;
+            val_g += 0.5f;
+
+            val_r = nval_r;
+            nval_r = rect[3];
+            diff_r = nval_r - val_r;
+            val_r += 0.5f;
+            rect += 4;
+          }
+          if (do_float) {
+            val_af = nval_af;
+            nval_af = rectf[0];
+            diff_af = nval_af - val_af;
+
+            val_bf = nval_bf;
+            nval_bf = rectf[1];
+            diff_bf = nval_bf - val_bf;
+
+            val_gf = nval_gf;
+            nval_gf = rectf[2];
+            diff_gf = nval_gf - val_gf;
+
+            val_rf = nval_rf;
+            nval_rf = rectf[3];
+            diff_rf = nval_rf - val_rf;
+            rectf += 4;
+          }
+        }
+        if (do_rect) {
+          newrect[0] = val_a + sample * diff_a;
+          newrect[1] = val_b + sample * diff_b;
+          newrect[2] = val_g + sample * diff_g;
+          newrect[3] = val_r + sample * diff_r;
+          newrect += 4;
+        }
+        if (do_float) {
+          newrectf[0] = val_af + sample * diff_af;
+          newrectf[1] = val_bf + sample * diff_bf;
+          newrectf[2] = val_gf + sample * diff_gf;
+          newrectf[3] = val_rf + sample * diff_rf;
+          newrectf += 4;
+        }
+        sample += add;
       }
-      sample += add;
     }
   }
 
@@ -1371,22 +1397,9 @@ static ImBuf *scaleupy(struct ImBuf *ibuf, int newy)
 {
   uchar *rect, *_newrect = NULL, *newrect;
   float *rectf, *_newrectf = NULL, *newrectf;
-  float sample, add;
-  float val_a, nval_a, diff_a;
-  float val_b, nval_b, diff_b;
-  float val_g, nval_g, diff_g;
-  float val_r, nval_r, diff_r;
-  float val_af, nval_af, diff_af;
-  float val_bf, nval_bf, diff_bf;
-  float val_gf, nval_gf, diff_gf;
-  float val_rf, nval_rf, diff_rf;
   int x, y, skipx;
   bool do_rect = false, do_float = false;
 
-  val_a = nval_a = diff_a = val_b = nval_b = diff_b = 0;
-  val_g = nval_g = diff_g = val_r = nval_r = diff_r = 0;
-  val_af = nval_af = diff_af = val_bf = nval_bf = diff_bf = 0;
-  val_gf = nval_gf = diff_gf = val_rf = nval_rf = diff_rf = 0;
   if (ibuf == NULL) {
     return NULL;
   }
@@ -1412,126 +1425,159 @@ static ImBuf *scaleupy(struct ImBuf *ibuf, int newy)
     }
   }
 
-  add = (ibuf->y - 1.001) / (newy - 1.0);
-  skipx = 4 * ibuf->x;
-
   rect = (uchar *)ibuf->rect;
   rectf = (float *)ibuf->rect_float;
   newrect = _newrect;
   newrectf = _newrectf;
 
-  for (x = ibuf->x; x > 0; x--) {
+  skipx = 4 * ibuf->x;
 
-    sample = 0;
+  /* Special case, copy all rows, needed since the scaling logic assumes there is at least
+   * two rows to interpolate between causing out of bounds read for 1px images, see T70356. */
+  if (UNLIKELY(ibuf->y == 1)) {
     if (do_rect) {
-      rect = ((uchar *)ibuf->rect) + 4 * (x - 1);
-      newrect = _newrect + 4 * (x - 1);
-
-      val_a = rect[0];
-      nval_a = rect[skipx];
-      diff_a = nval_a - val_a;
-      val_a += 0.5f;
-
-      val_b = rect[1];
-      nval_b = rect[skipx + 1];
-      diff_b = nval_b - val_b;
-      val_b += 0.5f;
-
-      val_g = rect[2];
-      nval_g = rect[skipx + 2];
-      diff_g = nval_g - val_g;
-      val_g += 0.5f;
-
-      val_r = rect[3];
-      nval_r = rect[skipx + 3];
-      diff_r = nval_r - val_r;
-      val_r += 0.5f;
-
-      rect += 2 * skipx;
+      for (y = newy; y > 0; y--) {
+        memcpy(newrect, rect, sizeof(char) * skipx);
+        newrect += skipx;
+      }
     }
     if (do_float) {
-      rectf = ibuf->rect_float + 4 * (x - 1);
-      newrectf = _newrectf + 4 * (x - 1);
-
-      val_af = rectf[0];
-      nval_af = rectf[skipx];
-      diff_af = nval_af - val_af;
+      for (y = newy; y > 0; y--) {
+        memcpy(newrectf, rectf, sizeof(float) * skipx);
+        newrectf += skipx;
+      }

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list