[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [PATCH v2] libxc: add LZ4 decompression support



>>> On 24.09.13 at 18:53, Ian Campbell <Ian.Campbell@xxxxxxxxxx> wrote:
> On Tue, 2013-09-24 at 17:29 +0100, Jan Beulich wrote:
>> @@ -573,6 +575,124 @@ int xc_try_xz_decode(struct xc_dom_image
>>  
>>  #endif /* !__MINIOS__ */
>>  
>> +#define CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
>> +#define STATIC static
>> +#define u8 uint8_t
>> +#define u16 uint16_t
>> +#define u32 uint32_t
>> +#define u64 uint64_t
>> +#define INIT
>> +#define unlikely(x) (x)
> 
> I think rather than pollute this file with this sort of thing (which
> might have unexpected consequences in the future) this would be better
> of placed in a separate file compiled for both regular and stub use.

So you mean to move the whole thing quoted above down to ...

>> +
>> +static inline uint_fast16_t le16_to_cpup(const unsigned char *buf)
>> +{
>> +    return buf[0] | (buf[1] << 8);
>> +}
>> +
>> +static inline uint_fast32_t le32_to_cpup(const unsigned char *buf)
>> +{
>> +    return le16_to_cpup(buf) | ((uint32_t)le16_to_cpup(buf + 2) << 16);
>> +}
>> +
>> +#include "../../xen/common/lz4/decompress.c"

... here out into a separate file. I can surely do that. Any
preference for the name (xc_dom_decompress_unsafe_lz4.c
would seem the prime candidate, albeit the other similarly
named files have a slightly different purpose).

The main problem doing so is going to be the uses of
get_unaligned_le32() in xc_try_lz4_decode() - they'd need to
be adjusted, increasing the amount of change from the original.
And lz4_decompress() would the also need to be declared in
some (new?) header. All of which didn't seem very desirable...

>> +
>> +/*
>> + * Note: Uncompressed chunk size is used in the compressor side
>> + * (userspace side for compression).
>> + * It is hardcoded because there is not proper way to extract it
>> + * from the binary stream which is generated by the preliminary
>> + * version of LZ4 tool so far.
>> + */
>> +#define LZ4_DEFAULT_UNCOMPRESSED_CHUNK_SIZE (8 << 20)
>> +#define ARCHIVE_MAGICNUMBER 0x184C2102
>> +
>> +static int xc_try_lz4_decode(
>> +    struct xc_dom_image *dom, void **blob, size_t *psize)
>> +{
>> +    int ret = -1;
>> +    size_t uncomp_chunksize = LZ4_DEFAULT_UNCOMPRESSED_CHUNK_SIZE;
>> +    unsigned char *inp = *blob, *output, *outp;
>> +    ssize_t size = *psize - 4;
>> +    size_t out_size, out_len, dest_len, chunksize;
>> +    const char *msg;
>> +
>> +    if (size < 4) {
>> +            msg = "input too small";
>> +            goto exit_0;
> 
> The exit_0 loop is after the error print, so these errors don't get
> printed.

Oops - fixed.

> I don't really like exit_0 and exit_2 as names (what happened to
> exit_1?). "err" and "err_free" would be more usual.

I didn't like those too, but tried to modify the original as little
as possible. exit_1 disappeared as having got orphaned in the
process of the adaptation.

>> +    }
>> +
>> +    out_size = out_len = get_unaligned_le32(inp + size);
>> +    if (xc_dom_kernel_check_size(dom, out_len)) {
>> +            msg = "Decompressed image too large";
>> +            goto exit_0;
>> +    }
>> +
>> +    output = malloc(out_len);
>> +    if (!output) {
>> +            msg = "Could not allocate output buffer";
>> +            goto exit_0;
>> +    }
>> +    outp = output;
>> +
>> +    chunksize = get_unaligned_le32(inp);
>> +    if (chunksize == ARCHIVE_MAGICNUMBER) {
>> +            inp += 4;
>> +            size -= 4;
>> +    } else {
>> +            msg = "invalid header";
>> +            goto exit_2;
>> +    }
>> +
>> +    for (;;) {
>> +            if (size < 4) {
>> +                    msg = "missing data";
>> +                    goto exit_2;
>> +            }
>> +            chunksize = get_unaligned_le32(inp);
>> +            if (chunksize == ARCHIVE_MAGICNUMBER) {
>> +                    inp += 4;
>> +                    size -= 4;
>> +                    continue;
>> +            }
>> +            inp += 4;
>> +            size -= 4;
> 
> We know size is at least 4 from the check at the head of the loop, but
> now we subtracted 4 so size could be 0, but lz4_decompress doesn't take
> size as an argument so whatever it does it isn't basing the return value
> in &chunksize on it, so I assume it reads over the end of the buffer via
> inp.
> 
> I didn't look to see what the minimum number of bytes which
> lz4_decompress will consume is, but I think we need a check of some
> description.

Sadly there doesn't appear to be a minimum - the main loop in
lz4_uncompress() has just a single exit point, which isn't
dependent upon the input size at all (the function doesn't even
know how much input there is).

Immediately before the call to lz4_decompress() chunksize gets
read, but I can't tell whether we could expect that to be the
required amount of bytes to follow. Yann - can you clarify this?

Jan

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.