[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH v2 4/6] gzip: refactor state tracking
On 17/04/2024 3:37 pm, Daniel P. Smith wrote: > diff --git a/xen/common/gzip/gunzip.c b/xen/common/gzip/gunzip.c > index 1b448d6e3655..8178a05a0190 100644 > --- a/xen/common/gzip/gunzip.c > +++ b/xen/common/gzip/gunzip.c > @@ -4,18 +4,25 @@ > #include <xen/lib.h> > #include <xen/mm.h> > > -static unsigned char *__initdata window; > - > #define WSIZE 0x80000000U > > -static unsigned char *__initdata inbuf; > -static unsigned int __initdata insize; > +struct gzip_state { > + unsigned char *window; > + > + unsigned char *inbuf; > + unsigned int insize; > + > + /* Index of next byte to be processed in inbuf: */ > + unsigned int inptr; perform_gunzip() passes in an unsigned long size, which means it's truncated in this state. Please at least make these size_t. Life is too short to deal with the fallout of this going wrong. > > -/* Index of next byte to be processed in inbuf: */ > -static unsigned int __initdata inptr; > + /* Bytes in output buffer: */ > + unsigned int outcnt; See later, but I think the comment for outcnt is wrong. > > -/* Bytes in output buffer: */ > -static unsigned int __initdata outcnt; > + long bytes_out; See later, but I don't think this can be signed. It's only used to cross-check the header-reported length, which is done as an unsigned long. > + > + unsigned long bb; /* bit buffer */ > + unsigned bk; /* bits in bit buffer */ As this is effectively new code, "unsigned int" please. > @@ -27,7 +34,7 @@ typedef unsigned char uch; > typedef unsigned short ush; > typedef unsigned long ulg; > > -#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf()) > +#define get_byte() (s->inptr < s->insize ? s->inbuf[s->inptr++] : > fill_inbuf()) This is a bit weird: > $ git grep -w get_byte common/gzip > common/gzip/gunzip.c:40:#define get_byte() (s->inptr < s->insize ? > s->inbuf[s->inptr++] : fill_inbuf()) > common/gzip/inflate.c:224:#define NEXTBYTE(s) ({ int v = get_byte(); > if (v < 0) goto underrun; (uch)v; }) > common/gzip/inflate.c:1131: flags = (uch)get_byte(); NEXTBYTE() gets an s parameter, but doesn't pass it to get_byte() and instead relies on state always having the name 's' in scope. I'd suggest turning get_byte() into a proper static function. It will be more readable that throwing extra ()'s around s in the existing macro. Except... fill_inbuf() is a fatal error anyway, so that can be folded together to simplify the result. > @@ -72,16 +78,16 @@ static __init void flush_window(void) > unsigned int n; > unsigned char *in, ch; > > - in = window; > - for ( n = 0; n < outcnt; n++ ) > + in = s->window; > + for ( n = 0; n < s->outcnt; n++ ) > { > ch = *in++; > c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8); > } > crc = c; > > - bytes_out += (unsigned long)outcnt; > - outcnt = 0; > + s->bytes_out += (unsigned long)s->outcnt; I can't figure out why this was written this way, even originally. AFAICT, outcnt doesn't even match it's comment. /* Bytes in output buffer: */ It looks like it's the number of bytes in window. This also matches the "wp" define which I guess is "window position". Anyway, irrespective of naming, the cast is useless so lets drop it while modifying the line. > diff --git a/xen/common/gzip/inflate.c b/xen/common/gzip/inflate.c > index 512d9bf0ee2e..5735bbcf7eb4 100644 > --- a/xen/common/gzip/inflate.c > +++ b/xen/common/gzip/inflate.c > @@ -119,7 +119,7 @@ static char rcsid[] = "#Id: inflate.c,v 0.14 1993/06/10 > 13:27:04 jloup Exp #"; > > #endif /* !__XEN__ */ > > -#define slide window > +#define slide s->window Given only 8 uses, I'd expand this in place and drop the macro. But, there's an entire comment block discussing "slide" which I think is wrong for Xen's implementation. That wants to go too, I think. > > /* > * Huffman code lookup table entry--this entry is four bytes for machines > @@ -143,12 +143,12 @@ struct huft { > static int huft_build OF((unsigned *, unsigned, unsigned, > const ush *, const ush *, struct huft **, int *)); > static int huft_free OF((struct huft *)); > -static int inflate_codes OF((struct huft *, struct huft *, int, int)); > -static int inflate_stored OF((void)); > -static int inflate_fixed OF((void)); > -static int inflate_dynamic OF((void)); > -static int inflate_block OF((int *)); > -static int inflate OF((void)); > +static int inflate_codes OF((struct gzip_state *, struct huft *, struct huft > *, int, int)); > +static int inflate_stored OF((struct gzip_state *)); > +static int inflate_fixed OF((struct gzip_state *)); > +static int inflate_dynamic OF((struct gzip_state *)); > +static int inflate_block OF((struct gzip_state *, int *)); > +static int inflate OF((struct gzip_state *)); These are the only users of OF, and it turns out it's a no-op macro. This code would be far-less WTF-worthy if it was expanded as part of patch 1. > > /* > * The inflate algorithm uses a sliding 32 K byte window on the uncompressed > @@ -162,8 +162,8 @@ static int inflate OF((void)); > * must be in unzip.h, included above. > */ > /* unsigned wp; current position in slide */ > -#define wp outcnt > -#define flush_output(w) (wp=(w),flush_window()) > +#define wp s->outcnt > +#define flush_output(s, w) (wp=(w),flush_window(s)) The combination of these two isn't safe, I don't think, especially as one caller passes wp into flush_output(). There are very few users of wp, so expand it in line, and turn flush_output() into a static function. In particular, it will make ... > @@ -560,8 +557,8 @@ static int __init inflate_codes( > > > /* make local copies of globals */ > - b = bb; /* initialize bit buffer */ > - k = bk; > + b = s->bb; /* initialize bit buffer */ > + k = s->bk; > w = wp; /* initialize window position */ ... this look less weird. I'd suggest dropping the remark about "globals". > @@ -1157,18 +1157,18 @@ static int __init gunzip(void) > error("Input has invalid flags"); > return -1; > } > - NEXTBYTE(); /* Get timestamp */ > - NEXTBYTE(); > - NEXTBYTE(); > - NEXTBYTE(); > + NEXTBYTE(s); /* Get timestamp */ > + NEXTBYTE(s); > + NEXTBYTE(s); > + NEXTBYTE(s); > > - (void)NEXTBYTE(); /* Ignore extra flags for the moment */ > - (void)NEXTBYTE(); /* Ignore OS type for the moment */ > + (void)NEXTBYTE(s); /* Ignore extra flags for the moment */ > + (void)NEXTBYTE(s); /* Ignore OS type for the moment */ I'd drop these (void) casts. They're not different to the timestamp above. > @@ -1224,13 +1224,13 @@ static int __init gunzip(void) > error("crc error"); > return -1; > } > - if (orig_len != bytes_out) { > + if (orig_len != s->bytes_out) { > error("length error"); > return -1; > } > return 0; > > - underrun: /* NEXTBYTE() goto's here if needed */ > + underrun: /* NEXTBYTE(s) goto's here if needed */ > error("out of input data"); > return -1; Just for completeness, this is a dead path because fill_inbuf() is implemented as panic(). Fixing this wants putting on a todo list somewhere. ~Andrew
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |