summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Musolino <alex@musolino.id.au>2020-11-27 11:19:49 +1030
committerAlex Musolino <alex@musolino.id.au>2020-11-27 11:19:49 +1030
commit2a907fd4597d57d94fdf573f37c1d553318a7104 (patch)
treea765f2e847839b40dbdb47c44e567258ea1a4a0b
parent781a8f8d9f50221dc34c0dab5baf48e197444269 (diff)
downloadplan9front-2a907fd4597d57d94fdf573f37c1d553318a7104.tar.xz
games/mix: fix implementation of MOVE instruction (thanks nicolagi)
Plan 9 memcpy(2) uses the same implementation as memmove(2) to handle overlapping ranges. Hovewer, the MIX MOVE instruction, as described in TAOCP, specifically does not do this. It copies words one at a time starting from the lowest address. This change also expands the address validation to check that all addresses within the source and destination ranges are valid before proceeding.
-rw-r--r--sys/src/games/mix/mix.c14
1 files changed, 10 insertions, 4 deletions
diff --git a/sys/src/games/mix/mix.c b/sys/src/games/mix/mix.c
index b7f451c0c..071d10f95 100644
--- a/sys/src/games/mix/mix.c
+++ b/sys/src/games/mix/mix.c
@@ -729,14 +729,20 @@ void
mixmove(int s, int f)
{
int d;
+ u32int *p, *q, *pe;
if(f == 0)
return;
-
+ if(s < 0 || s >= 4000 || s+f < 0 || s+f > 4000)
+ vmerror("Bad src range MOVE %d:%d", s, s+f-1);
d = mval(ri[1], 0, MASK2);
- if(d < 0 || d > 4000)
- vmerror("Bad address MOVE %d", d);
- memcpy(cells+d, cells+s, f*sizeof(u32int));
+ if(d < 0 || d >= 4000 || d+f < 0 || d+f > 4000)
+ vmerror("Bad dst range MOVE %d:%d", d, d+f-1);
+ p = cells+d;
+ q = cells+s;
+ pe = p+f;
+ while(p < pe)
+ *p++ = *q++;
d += f;
d &= MASK2;
ri[1] = d < 0 ? -d|SIGNB : d;