From f69fbb41c19af9bc32934b1a2fd4c3c1e3e4188d Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 22 Oct 2024 15:56:58 +1100 Subject: [PATCH] Fix #129225: Crash in modifiers & constraints with invalid enum values Even though this is generally avoided, drivers don't prevent invalid values being set. Further files from branches or files written in the future may contain enum values not yet known. Resolve by range checking enum values which are used to index arrays. --- .../blender/blenkernel/intern/constraint.cc | 30 ++++++++++++------- .../blender/blenkernel/intern/curve_deform.cc | 1 + source/blender/blenkernel/intern/object.cc | 3 +- source/blender/modifiers/intern/MOD_curve.cc | 9 +++--- .../modifiers/intern/MOD_simpledeform.cc | 2 +- 5 files changed, 29 insertions(+), 16 deletions(-) diff --git a/source/blender/blenkernel/intern/constraint.cc b/source/blender/blenkernel/intern/constraint.cc index 5bde2cfde7b..bef0776ca6c 100644 --- a/source/blender/blenkernel/intern/constraint.cc +++ b/source/blender/blenkernel/intern/constraint.cc @@ -1310,8 +1310,12 @@ static void trackto_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *tar /* NOTE(@joshualung): `targetmat[2]` instead of `ownermat[2]` is passed to #vectomat * for backwards compatibility it seems. */ sub_v3_v3v3(vec, cob->matrix[3], ct->matrix[3]); - vectomat( - vec, ct->matrix[2], short(data->reserved1), short(data->reserved2), data->flags, totmat); + vectomat(vec, + ct->matrix[2], + std::clamp(data->reserved1, 0, 5), + std::clamp(data->reserved2, 0, 2), + data->flags, + totmat); mul_m4_m3m4(cob->matrix, totmat, cob->matrix); } @@ -1540,7 +1544,9 @@ static void followpath_get_tarmat(Depsgraph * /*depsgraph*/, unit_m4(totmat); if (data->followflag & FOLLOWPATH_FOLLOW) { - quat_apply_track(quat, data->trackflag, data->upflag); + quat_apply_track(quat, + std::clamp(data->trackflag, 0, 5), + std::clamp(data->upflag, 0, 2)); quat_to_mat4(totmat, quat); } @@ -2962,7 +2968,7 @@ static void actcon_get_tarmat(Depsgraph *depsgraph, * normalization by the (max-min) range, to get predictable, valid values when that range is * zero. */ const float range = data->max - data->min; - if (range == 0.0f) { + if ((range == 0.0f) || (ushort(axis) > 2)) { s = 0.0f; } else { @@ -4819,23 +4825,27 @@ static void pivotcon_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *ta /* pivot correction */ float axis[3], angle; + const int rot_axis = std::clamp( + int(data->rotAxis), int(PIVOTCON_AXIS_NONE), int(PIVOTCON_AXIS_Z)); + /* firstly, check if pivoting should take place based on the current rotation */ - if (data->rotAxis != PIVOTCON_AXIS_NONE) { + if (rot_axis != PIVOTCON_AXIS_NONE) { + float rot[3]; /* extract euler-rotation of target */ mat4_to_eulO(rot, cob->rotOrder, cob->matrix); /* check which range might be violated */ - if (data->rotAxis < PIVOTCON_AXIS_X) { - /* negative rotations (data->rotAxis = 0 -> 2) */ - if (rot[data->rotAxis] > 0.0f) { + if (rot_axis < PIVOTCON_AXIS_X) { + /* Negative rotations (`rot_axis = 0 -> 2`). */ + if (rot[rot_axis] > 0.0f) { return; } } else { - /* positive rotations (data->rotAxis = 3 -> 5 */ - if (rot[data->rotAxis - PIVOTCON_AXIS_X] < 0.0f) { + /* Positive rotations (`rot_axis = 3 -> 5`). */ + if (rot[rot_axis - PIVOTCON_AXIS_X] < 0.0f) { return; } } diff --git a/source/blender/blenkernel/intern/curve_deform.cc b/source/blender/blenkernel/intern/curve_deform.cc index 3c3070b5a3a..777f62906f2 100644 --- a/source/blender/blenkernel/intern/curve_deform.cc +++ b/source/blender/blenkernel/intern/curve_deform.cc @@ -206,6 +206,7 @@ static void curve_deform_coords_impl(const Object *ob_curve, const short defaxis, const BMEditMesh *em_target) { + BLI_assert(ushort(defaxis) < 6); Curve *cu; int a; CurveDeform cd; diff --git a/source/blender/blenkernel/intern/object.cc b/source/blender/blenkernel/intern/object.cc index 15eab0a6b5a..0dc4c122275 100644 --- a/source/blender/blenkernel/intern/object.cc +++ b/source/blender/blenkernel/intern/object.cc @@ -3015,7 +3015,8 @@ static bool ob_parcurve(const Object *ob, Object *par, float r_mat[4][4]) par, ctime, vec, nullptr, (cu->flag & CU_FOLLOW) ? quat : nullptr, &radius, nullptr)) { if (cu->flag & CU_FOLLOW) { - quat_apply_track(quat, ob->trackflag, ob->upflag); + quat_apply_track( + quat, std::clamp(ob->trackflag, 0, 5), std::clamp(ob->upflag, 0, 2)); normalize_qt(quat); quat_to_mat4(r_mat, quat); } diff --git a/source/blender/modifiers/intern/MOD_curve.cc b/source/blender/modifiers/intern/MOD_curve.cc index bda5d39258f..7dcf1ad3ebc 100644 --- a/source/blender/modifiers/intern/MOD_curve.cc +++ b/source/blender/modifiers/intern/MOD_curve.cc @@ -103,7 +103,7 @@ static void deform_verts(ModifierData *md, /* Silly that defaxis and BKE_curve_deform_coords are off by 1 * but leave for now to save having to call do_versions */ - + const int defaxis = std::clamp(cmd->defaxis - 1, 0, 5); BKE_curve_deform_coords(cmd->object, ctx->object, reinterpret_cast(positions.data()), @@ -111,7 +111,7 @@ static void deform_verts(ModifierData *md, dvert, defgrp_index, cmd->flag, - cmd->defaxis - 1); + defaxis); } static void deform_verts_EM(ModifierData *md, @@ -136,6 +136,7 @@ static void deform_verts_EM(ModifierData *md, } } + const int defaxis = std::clamp(cmd->defaxis - 1, 0, 5); if (use_dverts) { BKE_curve_deform_coords_with_editmesh(cmd->object, ctx->object, @@ -143,7 +144,7 @@ static void deform_verts_EM(ModifierData *md, positions.size(), defgrp_index, cmd->flag, - cmd->defaxis - 1, + defaxis, em); } else { @@ -154,7 +155,7 @@ static void deform_verts_EM(ModifierData *md, nullptr, defgrp_index, cmd->flag, - cmd->defaxis - 1); + defaxis); } } diff --git a/source/blender/modifiers/intern/MOD_simpledeform.cc b/source/blender/modifiers/intern/MOD_simpledeform.cc index 4a6d2026b4f..61d9a3480a7 100644 --- a/source/blender/modifiers/intern/MOD_simpledeform.cc +++ b/source/blender/modifiers/intern/MOD_simpledeform.cc @@ -288,7 +288,7 @@ static void SimpleDeformModifier_do(SimpleDeformModifierData *smd, const MDeformVert *dvert; /* This is historically the lock axis, _not_ the deform axis as the name would imply */ - const int deform_axis = smd->deform_axis; + const int deform_axis = std::clamp(int(smd->deform_axis), 0, 2); int lock_axis = smd->axis; if (smd->mode == MOD_SIMPLEDEFORM_MODE_BEND) { /* Bend mode shouldn't have any lock axis */ lock_axis = 0;