From 1e52e51ce11a491d127a78d079ffb750554e21c5 Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Fri, 3 Jun 2022 13:58:58 +0100 Subject: [PATCH] VarAction2: Add bounds checks to previous adjust accesses --- src/newgrf.cpp | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/newgrf.cpp b/src/newgrf.cpp index 5da73afb47..9e3b19792d 100644 --- a/src/newgrf.cpp +++ b/src/newgrf.cpp @@ -5798,7 +5798,7 @@ static void OptimiseVarAction2Adjust(VarAction2OptimiseState &state, const GrfSp /* Operation always returns 0, replace it and any useless prior operations */ replace_with_constant_load(0); } else { - if (adjust.variable == 0x7D && adjust.shift_num == 0 && adjust.and_mask == get_full_mask() && IsEvalAdjustOperationCommutative(adjust.operation)) { + if (adjust.variable == 0x7D && adjust.shift_num == 0 && adjust.and_mask == get_full_mask() && IsEvalAdjustOperationCommutative(adjust.operation) && group->adjusts.size() >= 2) { DeterministicSpriteGroupAdjust &prev = group->adjusts[group->adjusts.size() - 2]; if (group->adjusts.size() >= 3 && prev.operation == DSGA_OP_RST) { const DeterministicSpriteGroupAdjust &prev2 = group->adjusts[group->adjusts.size() - 3]; @@ -5814,7 +5814,7 @@ static void OptimiseVarAction2Adjust(VarAction2OptimiseState &state, const GrfSp } switch (adjust.operation) { case DSGA_OP_SUB: - if (adjust.variable == 0x7D && adjust.shift_num == 0 && adjust.and_mask == 0xFFFFFFFF) { + if (adjust.variable == 0x7D && adjust.shift_num == 0 && adjust.and_mask == 0xFFFFFFFF && group->adjusts.size() >= 2) { DeterministicSpriteGroupAdjust &prev = group->adjusts[group->adjusts.size() - 2]; if (group->adjusts.size() >= 3 && prev.operation == DSGA_OP_RST) { const DeterministicSpriteGroupAdjust &prev2 = group->adjusts[group->adjusts.size() - 3]; @@ -5830,7 +5830,7 @@ static void OptimiseVarAction2Adjust(VarAction2OptimiseState &state, const GrfSp } break; case DSGA_OP_SMIN: - if (adjust.variable == 0x1A && adjust.shift_num == 0 && adjust.and_mask == 1) { + if (adjust.variable == 0x1A && adjust.shift_num == 0 && adjust.and_mask == 1 && group->adjusts.size() >= 2) { DeterministicSpriteGroupAdjust &prev = group->adjusts[group->adjusts.size() - 2]; if (prev.operation == DSGA_OP_SCMP) { prev.operation = DSGA_OP_SGE; @@ -5853,7 +5853,7 @@ static void OptimiseVarAction2Adjust(VarAction2OptimiseState &state, const GrfSp if (adjust.and_mask <= 1 && (prev_inference & VA2AIF_SIGNED_NON_NEGATIVE)) state.inference = VA2AIF_SIGNED_NON_NEGATIVE | VA2AIF_ONE_OR_ZERO; break; case DSGA_OP_SMAX: - if (adjust.variable == 0x1A && adjust.shift_num == 0 && adjust.and_mask == 0) { + if (adjust.variable == 0x1A && adjust.shift_num == 0 && adjust.and_mask == 0 && group->adjusts.size() >= 2) { DeterministicSpriteGroupAdjust &prev = group->adjusts[group->adjusts.size() - 2]; if (group->adjusts.size() >= 3 && prev.operation == DSGA_OP_SUB && prev.type == DSGA_TYPE_NONE && prev.variable == 0x1A && prev.shift_num == 0 && prev.and_mask == 1) { @@ -5881,7 +5881,7 @@ static void OptimiseVarAction2Adjust(VarAction2OptimiseState &state, const GrfSp } break; case DSGA_OP_AND: - if ((prev_inference & VA2AIF_PREV_MASK_ADJUST) && adjust.variable == 0x1A && adjust.shift_num == 0) { + if ((prev_inference & VA2AIF_PREV_MASK_ADJUST) && adjust.variable == 0x1A && adjust.shift_num == 0 && group->adjusts.size() >= 2) { /* Propagate and into immediately prior variable read */ DeterministicSpriteGroupAdjust &prev = group->adjusts[group->adjusts.size() - 2]; prev.and_mask &= adjust.and_mask; @@ -5890,7 +5890,7 @@ static void OptimiseVarAction2Adjust(VarAction2OptimiseState &state, const GrfSp group->adjusts.pop_back(); break; } - if (adjust.variable == 0x1A && adjust.shift_num == 0 && adjust.and_mask == 1) { + if (adjust.variable == 0x1A && adjust.shift_num == 0 && adjust.and_mask == 1 && group->adjusts.size() >= 2) { DeterministicSpriteGroupAdjust &prev = group->adjusts[group->adjusts.size() - 2]; if (prev.operation == DSGA_OP_SCMP || prev.operation == DSGA_OP_UCMP) { prev.operation = DSGA_OP_EQ; @@ -5915,7 +5915,7 @@ static void OptimiseVarAction2Adjust(VarAction2OptimiseState &state, const GrfSp if (adjust.and_mask <= 1) state.inference = prev_inference & (VA2AIF_SIGNED_NON_NEGATIVE | VA2AIF_ONE_OR_ZERO); break; case DSGA_OP_XOR: - if (adjust.variable == 0x1A && adjust.shift_num == 0 && adjust.and_mask == 1) { + if (adjust.variable == 0x1A && adjust.shift_num == 0 && adjust.and_mask == 1 && group->adjusts.size() >= 2) { DeterministicSpriteGroupAdjust &prev = group->adjusts[group->adjusts.size() - 2]; if (prev.operation == DSGA_OP_SLT || prev.operation == DSGA_OP_SGE || prev.operation == DSGA_OP_SLE || prev.operation == DSGA_OP_SGT) { prev.operation = (DeterministicSpriteGroupAdjustOperation)(prev.operation ^ 1); @@ -5935,7 +5935,7 @@ static void OptimiseVarAction2Adjust(VarAction2OptimiseState &state, const GrfSp if (adjust.and_mask <= 1) state.inference = prev_inference & (VA2AIF_SIGNED_NON_NEGATIVE | VA2AIF_ONE_OR_ZERO); break; case DSGA_OP_MUL: { - if ((prev_inference & VA2AIF_ONE_OR_ZERO) && adjust.variable == 0x1A && adjust.shift_num == 0) { + if ((prev_inference & VA2AIF_ONE_OR_ZERO) && adjust.variable == 0x1A && adjust.shift_num == 0 && group->adjusts.size() >= 2) { /* Found a ternary operator */ adjust.operation = DSGA_OP_TERNARY; while (group->adjusts.size() > 1) { @@ -5998,7 +5998,7 @@ static void OptimiseVarAction2Adjust(VarAction2OptimiseState &state, const GrfSp } break; case DSGA_OP_RST: - if ((prev_inference & VA2AIF_PREV_STORE_TMP) && adjust.variable == 0x7D && adjust.shift_num == 0 && adjust.and_mask == get_full_mask()) { + if ((prev_inference & VA2AIF_PREV_STORE_TMP) && adjust.variable == 0x7D && adjust.shift_num == 0 && adjust.and_mask == get_full_mask() && group->adjusts.size() >= 2) { const DeterministicSpriteGroupAdjust &prev = group->adjusts[group->adjusts.size() - 2]; if (prev.type == DSGA_TYPE_NONE && prev.operation == DSGA_OP_STO && prev.variable == 0x1A && prev.shift_num == 0 && prev.and_mask == adjust.parameter) { /* Redundant load from temp store after store to temp store */ @@ -6009,7 +6009,7 @@ static void OptimiseVarAction2Adjust(VarAction2OptimiseState &state, const GrfSp } add_inferences_from_mask(adjust.and_mask); state.inference |= VA2AIF_PREV_MASK_ADJUST | VA2AIF_SINGLE_LOAD; - if ((prev_inference & VA2AIF_PREV_MASK_ADJUST) && adjust.variable == 0x7B) { + if ((prev_inference & VA2AIF_PREV_MASK_ADJUST) && adjust.variable == 0x7B && group->adjusts.size() >= 2) { const DeterministicSpriteGroupAdjust &prev = group->adjusts[group->adjusts.size() - 2]; if (prev.variable == 0x1A) { /* Extract constant to remove indirect access via variable 7B */ @@ -6027,7 +6027,7 @@ static void OptimiseVarAction2Adjust(VarAction2OptimiseState &state, const GrfSp } break; case DSGA_OP_SHR: - if ((prev_inference & VA2AIF_PREV_MASK_ADJUST) && adjust.variable == 0x1A && adjust.shift_num == 0) { + if ((prev_inference & VA2AIF_PREV_MASK_ADJUST) && adjust.variable == 0x1A && adjust.shift_num == 0 && group->adjusts.size() >= 2) { /* Propagate shift right into immediately prior variable read */ DeterministicSpriteGroupAdjust &prev = group->adjusts[group->adjusts.size() - 2]; if (prev.shift_num + adjust.and_mask < 32) {