Skip to content

Commit

Permalink
hfe: Protect HFEv3 against a broken run of 1s
Browse files Browse the repository at this point in the history
Move the is_v3 check out of the loop since we are checking it so
frequently.
  • Loading branch information
ejona86 committed Jul 5, 2024
1 parent 2ae1065 commit c0b408a
Showing 1 changed file with 42 additions and 29 deletions.
71 changes: 42 additions & 29 deletions src/image/hfe.c
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,7 @@ static bool_t hfe_write_track(struct image *im)
struct write *write = get_write(im, im->wr_cons);
struct image_buf *wr = &im->bufs.write_bc;
uint8_t *buf = wr->p;
uint8_t b;
unsigned int bufmask = wr->len - 1;
uint8_t *w, *wrbuf = im->bufs.write_data.p;
uint32_t i, space, c = wr->cons / 8, p = wr->prod / 8;
Expand Down Expand Up @@ -414,37 +415,49 @@ static bool_t hfe_write_track(struct image *im)
}
}

while (i < nr) {
if (is_v3 && (w[i] & 0xf) == 0xf) {
switch (w[i]) {
case OP_SkipBits:
/* Keep the write byte-aligned. This changes the length of
* the track by 8+skip bitcells, but overwriting OP_SkipBits
* should be rare. */
w[i++] = OP_Nop;
continue;

case OP_Bitrate:
/* Assume bitrate does not change significantly for the
* entire track, and write_bc_ticks already adjusted when
* reading. */
i += 2;
continue;

case OP_Nop:
case OP_Index:
default:
/* Preserve opcode. But making sure not to write past end of
* buffer. */
i++;
continue;

case OP_Rand:
/* Replace with data. */
break;
if (!is_v3) {
while (i < nr)
w[i++] = _rbit32(buf[c++ & bufmask]) >> 24;
} else {
while (i < nr) {
if ((w[i] & 0xf) == 0xf) {
switch (w[i]) {
case OP_SkipBits:
/* Keep the write byte-aligned. This changes the length
* of the track by 8+skip bitcells, but overwriting
* OP_SkipBits should be rare. */
w[i++] = OP_Nop;
continue;

case OP_Bitrate:
/* Assume bitrate does not change significantly for the
* entire track, and write_bc_ticks already adjusted
* when reading. */
i += 2;
continue;

case OP_Nop:
case OP_Index:
default:
/* Preserve opcode. But making sure not to write past
* end of buffer. */
i++;
continue;

case OP_Rand:
/* Replace with data. */
break;
}
}
b = _rbit32(buf[c++ & bufmask]) >> 24;
/* HFEv3 can't handle a run of 1s as it will appear like an
* opcode. If we encounter such a run, then either it is
* garbage or the file needs twice the bitrate. Assume garbage;
* a bad bitrate would fail rapidly. */
if ((b & 0xf) == 0xf)
b ^= 2;
w[i++] = b;
}
w[i++] = _rbit32(buf[c++ & bufmask]) >> 24;
}
im->hfe.write_batch.dirty = TRUE;

Expand Down

0 comments on commit c0b408a

Please sign in to comment.