[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [42527] trunk/blender/source/blender/ editors/sculpt_paint/paint_vertex.c: possible/partial fix for [#29521], in many places the deform group index was not checked which could crash blender .

Campbell Barton ideasman42 at gmail.com
Fri Dec 9 08:18:16 CET 2011


Revision: 42527
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=42527
Author:   campbellbarton
Date:     2011-12-09 07:18:04 +0000 (Fri, 09 Dec 2011)
Log Message:
-----------
possible/partial fix for [#29521], in many places the deform group index was not checked which could crash blender.

Modified Paths:
--------------
    trunk/blender/source/blender/editors/sculpt_paint/paint_vertex.c

Modified: trunk/blender/source/blender/editors/sculpt_paint/paint_vertex.c
===================================================================
--- trunk/blender/source/blender/editors/sculpt_paint/paint_vertex.c	2011-12-09 06:21:26 UTC (rev 42526)
+++ trunk/blender/source/blender/editors/sculpt_paint/paint_vertex.c	2011-12-09 07:18:04 UTC (rev 42527)
@@ -967,11 +967,11 @@
 				index= view3d_sample_backbuf(&vc, win->eventstate->x - vc.ar->winrct.xmin, win->eventstate->y - vc.ar->winrct.ymin);
 
 				if(index && index<=me->totface) {
-					const int totgroup= BLI_countlist(&vc.obact->defbase);
-					if(totgroup) {
+					const int defbase_tot= BLI_countlist(&vc.obact->defbase);
+					if(defbase_tot) {
 						MFace *mf= ((MFace *)me->mface) + index-1;
 						unsigned int fidx= mf->v4 ? 3:2;
-						int *groups= MEM_callocN(totgroup*sizeof(int), "groups");
+						int *groups= MEM_callocN(defbase_tot*sizeof(int), "groups");
 						int found= FALSE;
 
 						do {
@@ -979,8 +979,10 @@
 							int i= dvert->totweight;
 							MDeformWeight *dw;
 							for(dw= dvert->dw; i > 0; dw++, i--) {
-								groups[dw->def_nr]= TRUE;
-								found= TRUE;
+								if (dw->def_nr < defbase_tot) {
+									groups[dw->def_nr]= TRUE;
+									found= TRUE;
+								}
 							}
 						} while (fidx--);
 
@@ -992,7 +994,7 @@
 							int totitem= 0;
 							int i= 0;
 							bDeformGroup *dg;
-							for(dg= vc.obact->defbase.first; dg && i<totgroup; i++, dg= dg->next) {
+							for(dg= vc.obact->defbase.first; dg && i<defbase_tot; i++, dg= dg->next) {
 								if(groups[i]) {
 									item_tmp.identifier= item_tmp.name= dg->name;
 									item_tmp.value= i;
@@ -1091,7 +1093,8 @@
 #endif
 
 /* the active group should be involved in auto normalize */
-static void do_weight_paint_auto_normalize_all_groups(MDeformVert *dvert, const char *vgroup_validmap, char do_auto_normalize)
+static void do_weight_paint_auto_normalize_all_groups(MDeformVert *dvert, const int defbase_tot,
+                                                      const char *vgroup_validmap, char do_auto_normalize)
 {
 	if (do_auto_normalize == FALSE) {
 		return;
@@ -1102,9 +1105,11 @@
 		MDeformWeight *dw;
 
 		for (i= dvert->totweight, dw= dvert->dw; i != 0; i--, dw++) {
-			if (vgroup_validmap[dw->def_nr]) {
-				tot++;
-				sum += dw->weight;
+			if (dw->def_nr < defbase_tot) {
+				if (vgroup_validmap[dw->def_nr]) {
+					tot++;
+					sum += dw->weight;
+				}
 			}
 		}
 
@@ -1115,8 +1120,10 @@
 		fac= 1.0f / sum;
 
 		for (i= dvert->totweight, dw= dvert->dw; i != 0; i--, dw++) {
-			if (vgroup_validmap[dw->def_nr]) {
-				dw->weight *= fac;
+			if (dw->def_nr < defbase_tot) {
+				if (vgroup_validmap[dw->def_nr]) {
+					dw->weight *= fac;
+				}
 			}
 		}
 	}
@@ -1125,12 +1132,17 @@
 /*
 See if the current deform vertex has a locked group
 */
-static char has_locked_group(MDeformVert *dvert, const char *lock_flags)
+static char has_locked_group(MDeformVert *dvert, const int defbase_tot,
+                             const char *lock_flags)
 {
 	int i;
-	for(i = 0; i < dvert->totweight; i++) {
-		if(lock_flags[dvert->dw[i].def_nr] && dvert->dw[i].weight > 0.0f) {
-			return TRUE;
+	MDeformWeight *dw;
+
+	for (i= dvert->totweight, dw= dvert->dw; i != 0; i--, dw++) {
+		if (dw->def_nr < defbase_tot) {
+			if (lock_flags[dw->def_nr] && dw->weight > 0.0f) {
+				return TRUE;
+			}
 		}
 	}
 	return FALSE;
@@ -1188,7 +1200,7 @@
 #endif
 
 
-static void multipaint_selection(MDeformVert *dvert, float change, const char *defbase_sel, int defbase_tot)
+static void multipaint_selection(MDeformVert *dvert, const int defbase_tot, float change, const char *defbase_sel)
 {
 	int i;
 	MDeformWeight *dw;
@@ -1227,7 +1239,10 @@
 /* move all change onto valid, unchanged groups.  If there is change left over,
  * then return it.
  * assumes there are valid groups to shift weight onto */
-static float redistribute_change(MDeformVert *ndv, char *change_status, int changeme, int changeto, float totchange, float total_valid, char do_auto_normalize)
+static float redistribute_change(MDeformVert *ndv, const int defbase_tot,
+                                 char *change_status, const char change_me, int changeto,
+                                 float totchange, float total_valid,
+                                 char do_auto_normalize)
 {
 	float was_change;
 	float change;
@@ -1241,31 +1256,36 @@
 		change = totchange/total_valid;
 		for(i = 0; i < ndv->totweight && total_valid && totchange; i++) {
 			ndw = (ndv->dw+i);
-			/* change only the groups with a valid status */
-			if(change_status[ndw->def_nr] == changeme) {
-				oldval = ndw->weight;
-				/* if auto normalize is active, don't worry about upper bounds */
-				if(do_auto_normalize == FALSE && ndw->weight + change > 1) {
-					totchange -= 1-ndw->weight;
-					ndw->weight = 1;
-					/* stop the changes to this group */
-					change_status[ndw->def_nr] = changeto;
-					total_valid--;
+
+			/* ignore anything outside the value range */
+			if (ndw->def_nr < defbase_tot) {
+
+				/* change only the groups with a valid status */
+				if(change_status[ndw->def_nr] == change_me) {
+					oldval = ndw->weight;
+					/* if auto normalize is active, don't worry about upper bounds */
+					if(do_auto_normalize == FALSE && ndw->weight + change > 1) {
+						totchange -= 1-ndw->weight;
+						ndw->weight = 1;
+						/* stop the changes to this group */
+						change_status[ndw->def_nr] = changeto;
+						total_valid--;
+					}
+					else if(ndw->weight + change < 0) { /* check the lower bound */
+						totchange -= ndw->weight;
+						ndw->weight = 0;
+						change_status[ndw->def_nr] = changeto;
+						total_valid--;
+					}
+					else {/* a perfectly valid change occurred to ndw->weight */
+						totchange -= change;
+						ndw->weight += change;
+					}
+					/* see if there was a change */
+					if(oldval != ndw->weight) {
+						was_change = TRUE;
+					}
 				}
-				else if(ndw->weight + change < 0) { /* check the lower bound */
-					totchange -= ndw->weight;
-					ndw->weight = 0;
-					change_status[ndw->def_nr] = changeto;
-					total_valid--;
-				}
-				else {/* a perfectly valid change occurred to ndw->weight */
-					totchange -= change;
-					ndw->weight += change;
-				}
-				/* see if there was a change */
-				if(oldval != ndw->weight) {
-					was_change = TRUE;
-				}
 			}
 		}
 		/* don't go again if there was no change, if there is no valid group,
@@ -1274,12 +1294,14 @@
 	/* left overs */
 	return totchange;
 }
-static float get_mp_change(MDeformVert *odv, const char *defbase_sel, float brush_change);
+static float get_mp_change(MDeformVert *odv, const int defbase_tot, const char *defbase_sel, float brush_change);
 /* observe the changes made to the weights of groups.
  * make sure all locked groups on the vertex have the same deformation
  * by moving the changes made to groups onto other unlocked groups */
-static void enforce_locks(MDeformVert *odv, MDeformVert *ndv, int defbase_tot, const char *defbase_sel,
-                          const char *lock_flags, const char *vgroup_validmap, char do_auto_normalize, char do_multipaint)
+static void enforce_locks(MDeformVert *odv, MDeformVert *ndv,
+                          const int defbase_tot, const char *defbase_sel,
+                          const char *lock_flags, const char *vgroup_validmap,
+                          char do_auto_normalize, char do_multipaint)
 {
 	float totchange = 0.0f;
 	float totchange_allowed = 0.0f;
@@ -1295,7 +1317,7 @@
 
 	char *change_status;
 
-	if(!lock_flags || !has_locked_group(ndv, lock_flags)) {
+	if(!lock_flags || !has_locked_group(ndv, defbase_tot, lock_flags)) {
 		return;
 	}
 	/* record if a group was changed, unlocked and not changed, or locked */
@@ -1359,17 +1381,17 @@
 				totchange_allowed = -totchange;
 			}
 			/* move the weight evenly between the allowed groups, move excess back onto the used groups based on the change */
-			totchange_allowed = redistribute_change(ndv, change_status, 1, -1, totchange_allowed, total_valid, do_auto_normalize);
+			totchange_allowed = redistribute_change(ndv, defbase_tot, change_status, 1, -1, totchange_allowed, total_valid, do_auto_normalize);
 			left_over += totchange_allowed;
 			if(left_over) {
 				/* more than one nonzero weights were changed with the same ratio with multipaint, so keep them changed that way! */
 				if(total_changed > 1 && do_multipaint) {
-					float undo_change = get_mp_change(ndv, defbase_sel, left_over);
-					multipaint_selection(ndv, undo_change, defbase_sel, defbase_tot);
+					float undo_change = get_mp_change(ndv, defbase_tot, defbase_sel, left_over);
+					multipaint_selection(ndv, defbase_tot, undo_change, defbase_sel);
 				}	
 				/* or designatedw is still -1 put weight back as evenly as possible */
 				else {
-					redistribute_change(ndv, change_status, 2, -2, left_over, total_changed, do_auto_normalize);
+					redistribute_change(ndv, defbase_tot, change_status, 2, -2, left_over, total_changed, do_auto_normalize);
 				}
 			}
 		}
@@ -1389,15 +1411,17 @@
 }
 
 /* multi-paint's initial, potential change is computed here based on the user's stroke */
-static float get_mp_change(MDeformVert *odv, const char *defbase_sel, float brush_change)
+static float get_mp_change(MDeformVert *odv, const int defbase_tot, const char *defbase_sel, float brush_change)
 {
 	float selwsum = 0.0f;
 	unsigned int i;
 	MDeformWeight *dw= odv->dw;
 
 	for (i= odv->totweight; i != 0; i--, dw++) {
-		if(defbase_sel[dw->def_nr]) {
-			selwsum += dw->weight;
+		if (dw->def_nr < defbase_tot) {
+			if(defbase_sel[dw->def_nr]) {
+				selwsum += dw->weight;
+			}
 		}
 	}
 	if(selwsum && selwsum+brush_change > 0) {
@@ -1449,7 +1473,7 @@
 	                          * length of defbase_tot, cant be const because of how its passed */
 
 	const char *vgroup_validmap; /* same as WeightPaintData.vgroup_validmap,
-	                        * only added here for convenience */
+	                              * only added here for convenience */
 
 	char do_flip;
 	char do_multipaint;
@@ -1458,7 +1482,10 @@
 
 /* fresh start to make multi-paint and locking modular */
 /* returns TRUE if it thinks you need to reset the weights due to
- * normalizing while multi-painting */
+ * normalizing while multi-painting
+ *
+ * note: this assumes dw->def_nr range has been checked by the caller
+ */
 static int apply_mp_locks_normalize(Mesh *me, const WeightPaintInfo *wpi,

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list