diff --git a/CHANGELOG.md b/CHANGELOG.md index a4c22bf6..93f80251 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -79,8 +79,11 @@ * Out-of-bounds read when parsing URIs with malformed %-encoded content ([#2353][2353]). +* DECCRA not clamping or verifying the destination rectangle + ([#2352][2352]). [2353]: https://codeberg.org/dnkl/foot/issues/2353 +[2352]: https://codeberg.org/dnkl/foot/issues/2352 ### Security diff --git a/csi.c b/csi.c index 87af215e..176cc3ac 100644 --- a/csi.c +++ b/csi.c @@ -774,7 +774,7 @@ params_to_rectangular_area(const struct terminal *term, int first_idx, int rel_bottom = vt_param_get(term, first_idx + 2, term->rows) - 1; *right = min(vt_param_get(term, first_idx + 3, term->cols) - 1, term->cols - 1); - if (rel_top > rel_bottom || *left > *right) + if (unlikely(rel_top > rel_bottom || *left > *right)) return false; *top = term_row_rel_to_abs(term, rel_top); @@ -2005,9 +2005,8 @@ csi_dispatch(struct terminal *term, uint8_t final) } int src_page = vt_param_get(term, 4, 1); - int dst_rel_top = vt_param_get(term, 5, 1) - 1; - int dst_left = vt_param_get(term, 6, 1) - 1; + int dst_left = min(vt_param_get(term, 6, 1) - 1, term->cols - 1); int dst_page = vt_param_get(term, 7, 1); if (unlikely(src_page != 1 || dst_page != 1)) { @@ -2021,6 +2020,18 @@ csi_dispatch(struct terminal *term, uint8_t final) int dst_top = term_row_rel_to_abs(term, dst_rel_top); int dst_bottom = term_row_rel_to_abs(term, dst_rel_bottom); + if (unlikely(dst_left > dst_right || dst_bottom > dst_top)) + break; + + /* + * src validated by params_to_rectangular_area() + * dst validated above + */ + xassert(src_bottom - src_top >= 0); + xassert(dst_bottom - dst_top >= 0); + xassert(src_right - src_left >= 0); + xassert(dst_right - dst_left >= 0); + /* Target area outside the screen is clipped */ const size_t row_count = min(src_bottom - src_top, dst_bottom - dst_top) + 1;