summaryrefslogtreecommitdiff
path: root/sys/src/games
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 /sys/src/games
parent781a8f8d9f50221dc34c0dab5baf48e197444269 (diff)
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.
Diffstat (limited to 'sys/src/games')
-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;