lookup of seven bits, the EOB code will be found in that first
lookup, and so will not require that too many bits be pulled from
the stream.
+
+ Note that NEEDBITS() can fail if the file is corrupt/truncated.
+ The GOTOFAILIFERROR, RETURNIFERROR and RETURN1IFERROR macros can
+ help.
*/
static ush mask_bits[] =
#define NEEDBITS(n) do {while(k<(n)){b|=((ulg)get_byte(gzio))<<k;k+=8;}} while (0)
#define DUMPBITS(n) do {b>>=(n);k-=(n);} while (0)
+#define RETURNIFERROR if (grub_errno != GRUB_ERR_NONE) return
+#define RETURN1IFERROR if (grub_errno != GRUB_ERR_NONE) return 1
+#define GOTOFAILIFERROR if (grub_errno != GRUB_ERR_NONE) goto fail
static int
get_byte (grub_gzio_t gzio)
{
+ grub_ssize_t bytes_read;
if (gzio->mem_input)
{
if (gzio->mem_input_off < gzio->mem_input_size)
|| gzio->inbuf_d == INBUFSIZ))
{
gzio->inbuf_d = 0;
- grub_file_read (gzio->file, gzio->inbuf, INBUFSIZ);
+ bytes_read = grub_file_read (gzio->file, gzio->inbuf, INBUFSIZ);
+ /*
+ * Only trigger if we get 0 bytes. If we get negative bytes there should
+ * be an existing GRUB error code that we don't want to overwrite.
+ */
+ if (bytes_read == 0)
+ {
+ grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, "File is too short");
+ return 0;
+ }
}
return gzio->inbuf[gzio->inbuf_d++];
return 1;
}
- NEEDBITS ((unsigned) gzio->bl);
+ NEEDBITS ((unsigned) gzio->bl); RETURN1IFERROR;
if ((e = (t = gzio->tl + ((unsigned) b & ml))->e) > 16)
do
{
}
DUMPBITS (t->b);
e -= 16;
- NEEDBITS (e);
+ NEEDBITS (e); RETURN1IFERROR;
}
while ((e = (t = t->v.t + ((unsigned) b & mask_bits[e]))->e) > 16);
DUMPBITS (t->b);
}
/* get length of block to copy */
- NEEDBITS (e);
+ NEEDBITS (e); RETURN1IFERROR;
n = t->v.n + ((unsigned) b & mask_bits[e]);
DUMPBITS (e);
}
/* decode distance of block to copy */
- NEEDBITS ((unsigned) gzio->bd);
+ NEEDBITS ((unsigned) gzio->bd); RETURN1IFERROR;
if ((e = (t = gzio->td + ((unsigned) b & md))->e) > 16)
do
{
}
DUMPBITS (t->b);
e -= 16;
- NEEDBITS (e);
+ NEEDBITS (e); RETURN1IFERROR;
}
while ((e = (t = t->v.t + ((unsigned) b & mask_bits[e]))->e)
> 16);
DUMPBITS (t->b);
- NEEDBITS (e);
+ NEEDBITS (e); RETURN1IFERROR;
d = w - t->v.n - ((unsigned) b & mask_bits[e]);
DUMPBITS (e);
gzio->code_state++;
DUMPBITS (k & 7);
/* get the length and its complement */
- NEEDBITS (16);
+ NEEDBITS (16); RETURNIFERROR;
gzio->block_len = ((unsigned) b & 0xffff);
DUMPBITS (16);
- NEEDBITS (16);
+ NEEDBITS (16); RETURNIFERROR;
if (gzio->block_len != (int) ((~b) & 0xffff))
grub_error (GRUB_ERR_BAD_COMPRESSED_DATA,
"the length of a stored block does not match");
k = gzio->bk;
/* read in table lengths */
- NEEDBITS (5);
+ NEEDBITS (5); RETURNIFERROR;
nl = 257 + ((unsigned) b & 0x1f); /* number of literal/length codes */
DUMPBITS (5);
- NEEDBITS (5);
+ NEEDBITS (5); RETURNIFERROR;
nd = 1 + ((unsigned) b & 0x1f); /* number of distance codes */
DUMPBITS (5);
- NEEDBITS (4);
+ NEEDBITS (4); RETURNIFERROR;
nb = 4 + ((unsigned) b & 0xf); /* number of bit length codes */
DUMPBITS (4);
if (nl > 286 || nd > 30)
/* read in bit-length-code lengths */
for (j = 0; j < nb; j++)
{
- NEEDBITS (3);
+ NEEDBITS (3); RETURNIFERROR;
ll[bitorder[j]] = (unsigned) b & 7;
DUMPBITS (3);
}
while ((unsigned) i < n)
{
- NEEDBITS ((unsigned) gzio->bl);
+ NEEDBITS ((unsigned) gzio->bl); GOTOFAILIFERROR;
j = (gzio->td = gzio->tl + ((unsigned) b & m))->b;
DUMPBITS (j);
j = gzio->td->v.n;
ll[i++] = l = j; /* save last length in l */
else if (j == 16) /* repeat last length 3 to 6 times */
{
- NEEDBITS (2);
+ NEEDBITS (2); GOTOFAILIFERROR;
j = 3 + ((unsigned) b & 3);
DUMPBITS (2);
if ((unsigned) i + j > n)
}
else if (j == 17) /* 3 to 10 zero length codes */
{
- NEEDBITS (3);
+ NEEDBITS (3); GOTOFAILIFERROR;
j = 3 + ((unsigned) b & 7);
DUMPBITS (3);
if ((unsigned) i + j > n)
else
/* j == 18: 11 to 138 zero length codes */
{
- NEEDBITS (7);
+ NEEDBITS (7); GOTOFAILIFERROR;
j = 11 + ((unsigned) b & 0x7f);
DUMPBITS (7);
if ((unsigned) i + j > n)
k = gzio->bk;
/* read in last block bit */
- NEEDBITS (1);
+ NEEDBITS (1); RETURNIFERROR;
gzio->last_block = (int) b & 1;
DUMPBITS (1);
/* read in block type */
- NEEDBITS (2);
+ NEEDBITS (2); RETURNIFERROR;
gzio->block_type = (unsigned) b & 3;
DUMPBITS (2);