summaryrefslogtreecommitdiff
path: root/src/vcr.c
diff options
context:
space:
mode:
authorVito Caputo <vcaputo@pengaru.com>2024-10-18 10:14:50 -0700
committerVito Caputo <vcaputo@pengaru.com>2024-10-18 10:14:50 -0700
commit3d158182ef29d19e61f1271380d54e49bf16de05 (patch)
tree211ad287f513895c6932d4264e2ab4614c0e796a /src/vcr.c
parent069d910388502aa5d374c78bd7dfb54af09d38ec (diff)
vcr: clip vcr_shift_below_row_up_one() for mem backend
There was an unintentional assumption that hierarchy_end wouldn't extend beyond the bottom, which just isn't always the case. I'm sure there's more of this kind of thing in the headless code since the original Xlib backend could lean on XRender clipping everything.
Diffstat (limited to 'src/vcr.c')
-rw-r--r--src/vcr.c21
1 files changed, 17 insertions, 4 deletions
diff --git a/src/vcr.c b/src/vcr.c
index 74e1c21..6913a6a 100644
--- a/src/vcr.c
+++ b/src/vcr.c
@@ -1347,10 +1347,7 @@ void vcr_clear_row(vcr_t *vcr, vcr_layer_t layer, int row, int x, int width)
}
-/* copy what's below a given row up the specified amount across all the layers */
-/* XXX: note for now we expect (and assert) rows == 1, to simplify TYPE_MEM,
- * this is acceptable for all existing call sites
- */
+/* copy what's below a given row up by one row across all the layers */
void vcr_shift_below_row_up_one(vcr_t *vcr, int row)
{
assert(vcr);
@@ -1391,6 +1388,22 @@ void vcr_shift_below_row_up_one(vcr_t *vcr, int row)
uint8_t *src = &vcr->mem.bits[(1 + row) * VCR_ROW_HEIGHT * vcr->mem.pitch];
size_t len = ((1 + *(vcr->hierarchy_end_ptr)) - (1 + row)) * VCR_ROW_HEIGHT * vcr->mem.pitch;
+ assert(*(vcr->hierarchy_end_ptr) >= row);
+
+ /* (hierarchy_end * VCR_ROW_HEIGHT) may overflow vcr->height, as it's not kept clipped.
+ * It more represents where the process hierarchy virtually ends - which may or may not stay within
+ * the chart's allocated area. So len must be clamped here to ensure we're not attempting
+ * to copy out of bounds.
+ */
+ len = MIN(len, &vcr->mem.bits[vcr->height * vcr->mem.pitch] - src);
+
+ assert(src + len <= vcr->mem.bits + vcr->mem.pitch * vcr->height);
+ assert(dest + len <= vcr->mem.bits + vcr->mem.pitch * vcr->height);
+
+ /* XXX the xlib backend enjoys some luxuries in dealing with clipping that must be dealt with manually here,
+ * and that just hasn't been entirely fleshed out beyond "do enough to at least not segfault"
+ */
+
memmove(dest, src, len);
break;
}
© All Rights Reserved