diff options
author | Alex Musolino <alex@musolino.id.au> | 2020-11-27 11:19:49 +1030 |
---|---|---|
committer | Alex Musolino <alex@musolino.id.au> | 2020-11-27 11:19:49 +1030 |
commit | 2a907fd4597d57d94fdf573f37c1d553318a7104 (patch) | |
tree | a765f2e847839b40dbdb47c44e567258ea1a4a0b /sys/src/games | |
parent | 781a8f8d9f50221dc34c0dab5baf48e197444269 (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.c | 14 |
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; |