[gimp/soc-2010-cage-2] Fix a memory allocation issue mid recursion and put a depth limit in place



commit f5935620553ce2979c90f5e5d35bac30bdf207ac
Author: Alexia Death <alexiadeath gmail com>
Date:   Tue Aug 10 22:01:18 2010 +0300

    Fix a memory allocation issue mid recursion and put a depth limit in place
    
    The limit can be set to say 7 or 8 when bugs are out of the coef calc.

 app/gegl/gimpoperationcagetransform.c |  204 +++++++++++++++++++--------------
 1 files changed, 119 insertions(+), 85 deletions(-)
---
diff --git a/app/gegl/gimpoperationcagetransform.c b/app/gegl/gimpoperationcagetransform.c
index 8a24778..7f1ffbf 100644
--- a/app/gegl/gimpoperationcagetransform.c
+++ b/app/gegl/gimpoperationcagetransform.c
@@ -44,12 +44,18 @@ static gboolean       gimp_operation_cage_transform_process                   (G
                                                                                GeglBuffer          *aux_buf,
                                                                                GeglBuffer          *out_buf,
                                                                                const GeglRectangle *roi);
-static void           gimp_operation_cage_transform_interpolate_source_coords_recurs  (GimpOperationCageTransform  *oct,
-                                                                                GeglBuffer *out_buf,
-                                                                                const GeglRectangle *roi,
-                                                                                GimpCoords p1_s, GimpCoords p1_d,
-                                                                                GimpCoords p2_s, GimpCoords p2_d,
-                                                                                GimpCoords p3_s, GimpCoords p3_d);
+static void           gimp_operation_cage_transform_interpolate_source_coords_recurs
+                                                                              (GimpOperationCageTransform  *oct,
+                                                                               GeglBuffer *out_buf,
+                                                                               const GeglRectangle *roi,
+                                                                               GimpCoords p1_s,
+                                                                               GimpCoords p1_d,
+                                                                               GimpCoords p2_s,
+                                                                               GimpCoords p2_d,
+                                                                               GimpCoords p3_s,
+                                                                               GimpCoords p3_d,
+                                                                               gint recursion_depth,
+                                                                               gfloat *coords);
 static GimpCoords     gimp_cage_transform_compute_destination                 (GimpCageConfig *config,
                                                                                GeglBuffer *coef_buf,
                                                                                GimpCoords coords);
@@ -60,7 +66,7 @@ GeglRectangle         gimp_operation_cage_transform_get_required_for_output   (G
                                                                                const GeglRectangle *roi);
 GeglRectangle         gimp_operation_cage_get_bounding_box                    (GeglOperation *operation);
 
-G_DEFINE_TYPE (GimpOperationCageTransform, gimp_operation_cage_transform, 
+G_DEFINE_TYPE (GimpOperationCageTransform, gimp_operation_cage_transform,
                       GEGL_TYPE_OPERATION_COMPOSER)
 
 #define parent_class gimp_operation_cage_transform_parent_class
@@ -85,14 +91,14 @@ gimp_operation_cage_transform_class_init (GimpOperationCageTransformClass *klass
   operation_class->description  = "GIMP cage reverse transform";
 
   operation_class->prepare      = gimp_operation_cage_transform_prepare;
-  
+
   operation_class->get_required_for_output = gimp_operation_cage_transform_get_required_for_output;
   operation_class->get_cached_region = gimp_operation_cage_transform_get_cached_region;
   operation_class->no_cache     = FALSE;
   operation_class->get_bounding_box = gimp_operation_cage_get_bounding_box;
-  
+
   filter_class->process         = gimp_operation_cage_transform_process;
-  
+
   g_object_class_install_property (object_class,
                                  GIMP_OPERATION_CAGE_TRANSFORM_PROP_CONFIG,
                                  g_param_spec_object ("config", NULL, NULL,
@@ -117,7 +123,7 @@ gimp_operation_cage_transform_finalize  (GObject  *object)
       g_object_unref (self->config);
       self->config = NULL;
     }
-  
+
   G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
@@ -169,7 +175,7 @@ gimp_operation_cage_transform_prepare (GeglOperation  *operation)
 {
   GimpOperationCageTransform    *oct    = GIMP_OPERATION_CAGE_TRANSFORM (operation);
   GimpCageConfig                *config = GIMP_CAGE_CONFIG (oct->config);
-  
+
   gegl_operation_set_format (operation, "input", babl_format_n (babl_type ("float"), 2 * config->cage_vertice_number));
   gegl_operation_set_format (operation, "output", babl_format_n (babl_type ("float"), 2));
 }
@@ -183,31 +189,31 @@ gimp_operation_cage_transform_process (GeglOperation       *operation,
 {
   GimpOperationCageTransform    *oct    = GIMP_OPERATION_CAGE_TRANSFORM (operation);
   GimpCageConfig                *config = GIMP_CAGE_CONFIG (oct->config);
-  
+
   gint x, y;
   GeglRectangle cage_bb = gimp_cage_config_get_bounding_box (config);
   GeglRectangle buffer_bb = *gegl_operation_source_get_bounding_box (operation, "input");
-  
-  
+
+
   /* pre-fill the out buffer with no-displacement coordinate */
   GeglBufferIterator *it = gegl_buffer_iterator_new (out_buf, roi, NULL, GEGL_BUFFER_WRITE);
-  
+
   while (gegl_buffer_iterator_next (it))
   {
     /* iterate inside the roi */
     gint        n_pixels = it->length;
     gint        x = it->roi->x; /* initial x                   */
     gint        y = it->roi->y; /*           and y coordinates */
-    
+
     gfloat      *output = it->data[0];
-    
+
     while(n_pixels--)
     {
       output[0] = x;
       output[1] = y;
 
       output += 2;
-      
+
       /* update x and y coordinates */
       x++;
       if (x >= (it->roi->x + it->roi->width))
@@ -217,7 +223,7 @@ gimp_operation_cage_transform_process (GeglOperation       *operation,
       }
     }
   }
-  
+
   /* compute, reverse and interpolate the transformation */
   for (x = cage_bb.x; x < cage_bb.x + cage_bb.width - 1; x++)
   {
@@ -227,27 +233,35 @@ gimp_operation_cage_transform_process (GeglOperation       *operation,
       GimpCoords p2_s = {x+1, y, };
       GimpCoords p3_s = {x+1, y+1, };
       GimpCoords p4_s = {x, y+1, };
-      
+
       GimpCoords p1_d, p2_d, p3_d, p4_d;
-      
+      gfloat *coords;
+
+      coords = g_malloc( 2 * sizeof (gfloat));
+
       p1_d = gimp_cage_transform_compute_destination (config, aux_buf, p1_s);
       p2_d = gimp_cage_transform_compute_destination (config, aux_buf, p2_s);
       p3_d = gimp_cage_transform_compute_destination (config, aux_buf, p3_s);
       p4_d = gimp_cage_transform_compute_destination (config, aux_buf, p4_s);
-      
+
       gimp_operation_cage_transform_interpolate_source_coords_recurs  (oct,
                                                                       out_buf,
                                                                       &buffer_bb,
                                                                       p1_s, p1_d,
                                                                       p2_s, p2_d,
-                                                                      p3_s, p3_d);
-      
+                                                                      p3_s, p3_d,
+                                                                      0,
+                                                                      coords);
+
       gimp_operation_cage_transform_interpolate_source_coords_recurs  (oct,
                                                                       out_buf,
                                                                       &buffer_bb,
                                                                       p1_s, p1_d,
                                                                       p3_s, p3_d,
-                                                                      p4_s, p4_d);
+                                                                      p4_s, p4_d,
+                                                                      0,
+                                                                      coords);
+      g_free (coords);
     }
   }
 
@@ -256,81 +270,91 @@ gimp_operation_cage_transform_process (GeglOperation       *operation,
 
 
 static void
-gimp_operation_cage_transform_interpolate_source_coords_recurs  (GimpOperationCageTransform  *oct,
+gimp_operation_cage_transform_interpolate_source_coords_recurs (GimpOperationCageTransform  *oct,
                                                                 GeglBuffer *out_buf,
                                                                 const GeglRectangle *roi,
-                                                                GimpCoords p1_s, GimpCoords p1_d,
-                                                                GimpCoords p2_s, GimpCoords p2_d,
-                                                                GimpCoords p3_s, GimpCoords p3_d)
+                                                                GimpCoords p1_s,
+                                                                GimpCoords p1_d,
+                                                                GimpCoords p2_s,
+                                                                GimpCoords p2_d,
+                                                                GimpCoords p3_s,
+                                                                GimpCoords p3_d,
+                                                                gint recursion_depth,
+                                                                gfloat *coords)
 {
   gint xmin, xmax, ymin, ymax;
   GeglRectangle rect = {0, 0, 1, 1};
-  gfloat *coords;  
-  
-  coords = g_malloc( 2 * sizeof (gfloat));
-  
+
   if (p1_d.x > roi->width) return;
   if (p2_d.x > roi->width) return;
   if (p3_d.x > roi->width) return;
-  if (p1_d.x < 0) return;
-  if (p2_d.x < 0) return;
-  if (p3_d.x < 0) return;
   if (p1_d.y > roi->height) return;
   if (p2_d.y > roi->height) return;
   if (p3_d.y > roi->height) return;
+
+  if (p1_d.x < 0) return;
+  if (p2_d.x < 0) return;
+  if (p3_d.x < 0) return;
   if (p1_d.y < 0) return;
   if (p2_d.y < 0) return;
   if (p3_d.y < 0) return;
-  
+
   xmin = xmax = p1_d.x;
   ymin = ymax = p1_d.y;
-  
+
   if (xmin > p2_d.x) xmin = p2_d.x;
   if (xmin > p3_d.x) xmin = p3_d.x;
-  
+
   if (xmax < p2_d.x) xmax = p2_d.x;
   if (xmax < p3_d.x) xmax = p3_d.x;
-  
+
   if (ymin > p2_d.y) ymin = p2_d.y;
   if (ymin > p3_d.y) ymin = p3_d.y;
-  
+
   if (ymax < p2_d.y) ymax = p2_d.y;
   if (ymax < p3_d.y) ymax = p3_d.y;
-  
+
   /* test if there is no more pixel in the triangle */
   if (xmin == xmax || ymin == ymax)
     return;
-  
+
+  /* test if the triangle is implausibly large as manifested by too deep recursion */
+  if (recursion_depth > 4)
+    return;
+
   /* test if the triangle is small enough.
    * if yes, we compute the coefficient of the barycenter for the pixel (x,y) and see if a pixel is inside (ie the 3 coef have the same sign).
    */
   if (xmax - xmin == 1 && ymax - ymin == 1)
   {
+
     gfloat a, b, c, denom, x, y;
-    
+
     rect.x = xmax;
     rect.y = ymax;
-    
+
     x = (gfloat) xmax;
     y = (gfloat) ymax;
-    
+
     denom = (p2_d.x - p1_d.x) * p3_d.y + (p1_d.x - p3_d.x) * p2_d.y + (p3_d.x - p2_d.x) * p1_d.y;
     a = ((p2_d.x - x) * p3_d.y + (x - p3_d.x) * p2_d.y + (p3_d.x - p2_d.x) * y) / denom;
     b = - ((p1_d.x - x) * p3_d.y + (x - p3_d.x) * p1_d.y + (p3_d.x - p1_d.x) * y) / denom;
     c = 1.0 - a - b;
-    
+
     /* if a pixel is inside, we compute his source coordinate and set it in the output buffer */
     if ((a > 0 && b > 0 && c > 0) || (a < 0 && b < 0 && c < 0))
     {
       coords[0] = (a * p1_s.x + b * p2_s.x + c * p3_s.x);
       coords[1] = (a * p1_s.y + b * p2_s.y + c * p3_s.y);
-      
+
       gegl_buffer_set(out_buf,
                       &rect,
                       oct->format_coords,
                       coords,
                       GEGL_AUTO_ROWSTRIDE);
     }
+
+    return;
   }
   else
   {
@@ -340,60 +364,70 @@ gimp_operation_cage_transform_interpolate_source_coords_recurs  (GimpOperationCa
      *      /__\
      *     /\  /\
      *    /__\/__\
-     * 
+     *
      */
-    
+
     GimpCoords pm1_d, pm2_d, pm3_d;
     GimpCoords pm1_s, pm2_s, pm3_s;
-    
+
+    gint next_depth = recursion_depth + 1;
+
     pm1_d.x = (p1_d.x + p2_d.x) / 2.0;
     pm1_d.y = (p1_d.y + p2_d.y) / 2.0;
-    
+
     pm2_d.x = (p2_d.x + p3_d.x) / 2.0;
     pm2_d.y = (p2_d.y + p3_d.y) / 2.0;
-    
+
     pm3_d.x = (p3_d.x + p1_d.x) / 2.0;
     pm3_d.y = (p3_d.y + p1_d.y) / 2.0;
-    
+
     pm1_s.x = (p1_s.x + p2_s.x) / 2.0;
     pm1_s.y = (p1_s.y + p2_s.y) / 2.0;
-    
+
     pm2_s.x = (p2_s.x + p3_s.x) / 2.0;
     pm2_s.y = (p2_s.y + p3_s.y) / 2.0;
-    
+
     pm3_s.x = (p3_s.x + p1_s.x) / 2.0;
     pm3_s.y = (p3_s.y + p1_s.y) / 2.0;
-    
-    gimp_operation_cage_transform_interpolate_source_coords_recurs  (oct,
+
+    gimp_operation_cage_transform_interpolate_source_coords_recurs (oct,
                                                                     out_buf,
                                                                     roi,
                                                                     p1_s, p1_d,
                                                                     pm1_s, pm1_d,
-                                                                    pm3_s, pm3_d);
-                                                                    
-    gimp_operation_cage_transform_interpolate_source_coords_recurs  (oct,
+                                                                    pm3_s, pm3_d,
+                                                                    next_depth,
+                                                                    coords);
+
+    gimp_operation_cage_transform_interpolate_source_coords_recurs (oct,
                                                                     out_buf,
                                                                     roi,
                                                                     pm1_s, pm1_d,
                                                                     p2_s, p2_d,
-                                                                    pm2_s, pm2_d);
+                                                                    pm2_s, pm2_d,
+                                                                    next_depth,
+                                                                    coords);
 
-    gimp_operation_cage_transform_interpolate_source_coords_recurs  (oct,
+    gimp_operation_cage_transform_interpolate_source_coords_recurs (oct,
                                                                     out_buf,
                                                                     roi,
                                                                     pm1_s, pm1_d,
                                                                     pm2_s, pm2_d,
-                                                                    pm3_s, pm3_d);
-                                                                  
-    gimp_operation_cage_transform_interpolate_source_coords_recurs  (oct,
+                                                                    pm3_s, pm3_d,
+                                                                    next_depth,
+                                                                    coords);
+
+    gimp_operation_cage_transform_interpolate_source_coords_recurs (oct,
                                                                     out_buf,
                                                                     roi,
                                                                     pm3_s, pm3_d,
                                                                     pm2_s, pm2_d,
-                                                                    p3_s, p3_d);
+                                                                    p3_s, p3_d,
+                                                                    next_depth,
+                                                                    coords);
   }
-      
-  g_free (coords);
+
+
 }
 
 static GimpCoords
@@ -408,50 +442,50 @@ gimp_cage_transform_compute_destination (GimpCageConfig *config,
   GimpCoords result;
   gint cvn = config->cage_vertice_number;
   Babl *format_coef = babl_format_n (babl_type ("float"), 2 * cvn);
-  
+
   rect.height = 1;
   rect.width = 1;
   rect.x = coords.x;
   rect.y = coords.y;
-  
+
   coef = g_malloc (config->cage_vertice_number * 2 * sizeof(gfloat));
-  
+
   gegl_buffer_get (coef_buf, 1, &rect, format_coef, coef, GEGL_AUTO_ROWSTRIDE);
-  
+
   pos_x = 0;
   pos_y = 0;
-  
+
   for(i = 0; i < cvn; i++)
   {
-    
+
     if (!isnan(coef[i]))
     {
       pos_x += coef[i] * config->cage_vertices_d[i].x;
       pos_y += coef[i] * config->cage_vertices_d[i].y;
     }
-    
+
     g_assert (!isnan(pos_x));
     g_assert (!isnan(pos_y));
   }
-  
+
   for(i = 0; i < cvn; i++)
   {
-    
+
     if (!isnan(coef[i]))
     {
       pos_x += coef[i + cvn] * config->scaling_factor[i] * gimp_cage_config_get_edge_normal (config, i).x;
       pos_y += coef[i + cvn] * config->scaling_factor[i] * gimp_cage_config_get_edge_normal (config, i).y;
     }
-    
+
     g_assert (!isnan(pos_x));
     g_assert (!isnan(pos_y));
   }
-  
+
   result.x = pos_x;
   result.y = pos_y;
-  
+
   g_free (coef);
-  
+
   return result;
 }
 
@@ -470,7 +504,7 @@ gimp_operation_cage_transform_get_required_for_output (GeglOperation        *ope
                                                        const GeglRectangle  *roi)
 {
   GeglRectangle result = *gegl_operation_source_get_bounding_box (operation, "input");
-  
+
   return result;
 }
 
@@ -478,6 +512,6 @@ GeglRectangle
 gimp_operation_cage_get_bounding_box  (GeglOperation *operation)
 {
   GeglRectangle result = *gegl_operation_source_get_bounding_box (operation, "input");
-  
+
   return result;
 }



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]