From be48f3e41eaf0eaf6686c61c439095fc56883cec Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Thu, 20 Feb 2014 23:38:49 -0800 Subject: [PATCH] cbfstool: Propogate compression errors back to the caller. When compression fails for whatever reason, the caller should know about it rather than blindly assuming it worked correctly. That can prevent half compressed data from ending up in the image. This is currently happening for a segment of depthcharge which is triggering a failure in LZMA. The size of the "compressed" data is never set and is recorded as zero, and that segment effectively isn't loaded during boot. BUG=chrome-os-partner:26060 TEST=Built with this change and saw that cbfstool no longer seems to succeed or inserts a broken payload. BRANCH=None Change-Id: Idbff01f5413d030bbf5382712780bbd0b9e83bc7 Signed-off-by: Gabe Black Reviewed-on: https://chromium-review.googlesource.com/187364 Reviewed-by: Hung-Te Lin Tested-by: Gabe Black Commit-Queue: Gabe Black --- util/cbfstool/cbfs-mkpayload.c | 17 +++++++++++++---- util/cbfstool/cbfs-mkstage.c | 9 ++++++--- util/cbfstool/common.h | 6 +++--- util/cbfstool/compress.c | 7 ++++--- util/cbfstool/lzma/lzma.c | 21 ++++++++++++--------- 5 files changed, 38 insertions(+), 22 deletions(-) diff --git a/util/cbfstool/cbfs-mkpayload.c b/util/cbfstool/cbfs-mkpayload.c index be55753b9d..87688b9b38 100644 --- a/util/cbfstool/cbfs-mkpayload.c +++ b/util/cbfstool/cbfs-mkpayload.c @@ -188,8 +188,11 @@ int parse_elf_to_payload(const struct buffer *input, segs[segments].offset = doffset; int len; - compress((char *)&header[phdr[i].p_offset], - phdr[i].p_filesz, output->data + doffset, &len); + if (compress((char *)&header[phdr[i].p_offset], + phdr[i].p_filesz, output->data + doffset, &len)) { + buffer_delete(output); + return -1; + } segs[segments].len = len; /* If the compressed section is larger, then use the @@ -244,7 +247,10 @@ int parse_flat_binary_to_payload(const struct buffer *input, segs[0].mem_len = input->size; segs[0].offset = doffset; - compress(input->data, input->size, output->data + doffset, &len); + if (compress(input->data, input->size, output->data + doffset, &len)) { + buffer_delete(output); + return -1; + } segs[0].compression = algo; segs[0].len = len; @@ -370,7 +376,10 @@ int parse_fv_to_payload(const struct buffer *input, segs[0].mem_len = input->size; segs[0].offset = doffset; - compress(input->data, input->size, output->data + doffset, &len); + if (compress(input->data, input->size, output->data + doffset, &len)) { + buffer_delete(output); + return -1; + } segs[0].compression = algo; segs[0].len = len; diff --git a/util/cbfstool/cbfs-mkstage.c b/util/cbfstool/cbfs-mkstage.c index 6538d5f90e..18b847e379 100644 --- a/util/cbfstool/cbfs-mkstage.c +++ b/util/cbfstool/cbfs-mkstage.c @@ -155,9 +155,12 @@ int parse_elf_to_stage(const struct buffer *input, struct buffer *output, * - the output header is a known size (not always true in many xdr's) * - we do need to know the compressed output size first */ - compress(buffer, data_end - data_start, - (output->data + sizeof(struct cbfs_stage)), - &outlen); + if (compress(buffer, data_end - data_start, + (output->data + sizeof(struct cbfs_stage)), + &outlen) < 0) { + free(buffer); + return -1; + } free(buffer); /* Set up for output marshaling. */ diff --git a/util/cbfstool/common.h b/util/cbfstool/common.h index c27151ef36..f882b86e54 100644 --- a/util/cbfstool/common.h +++ b/util/cbfstool/common.h @@ -76,7 +76,7 @@ uint32_t string_to_arch(const char *arch_string); int iself(unsigned char *input); -typedef void (*comp_func_ptr) (char *, int, char *, int *); +typedef int (*comp_func_ptr) (char *, int, char *, int *); typedef enum { CBFS_COMPRESS_NONE = 0, CBFS_COMPRESS_LZMA = 1 } comp_algo; comp_func_ptr compression_function(comp_algo algo); @@ -100,8 +100,8 @@ int parse_elf_to_stage(const struct buffer *input, struct buffer *output, /* lzma/lzma.c */ -void do_lzma_compress(char *in, int in_len, char *out, int *out_len); -void do_lzma_uncompress(char *dst, int dst_len, char *src, int src_len); +int do_lzma_compress(char *in, int in_len, char *out, int *out_len); +int do_lzma_uncompress(char *dst, int dst_len, char *src, int src_len); /* xdr.c */ struct xdr { uint16_t (*get16)(struct buffer *input); diff --git a/util/cbfstool/compress.c b/util/cbfstool/compress.c index 38fa03dbed..5b916cee11 100644 --- a/util/cbfstool/compress.c +++ b/util/cbfstool/compress.c @@ -26,15 +26,16 @@ #include #include "common.h" -static void lzma_compress(char *in, int in_len, char *out, int *out_len) +static int lzma_compress(char *in, int in_len, char *out, int *out_len) { - do_lzma_compress(in, in_len, out, out_len); + return do_lzma_compress(in, in_len, out, out_len); } -static void none_compress(char *in, int in_len, char *out, int *out_len) +static int none_compress(char *in, int in_len, char *out, int *out_len) { memcpy(out, in, in_len); *out_len = in_len; + return 0; } comp_func_ptr compression_function(comp_algo algo) diff --git a/util/cbfstool/lzma/lzma.c b/util/cbfstool/lzma/lzma.c index 330e42cd6b..c1c9454e2c 100644 --- a/util/cbfstool/lzma/lzma.c +++ b/util/cbfstool/lzma/lzma.c @@ -99,11 +99,11 @@ static ISeqOutStream os = { Write }; * @param out_len a pointer to the compressed length of in */ -void do_lzma_compress(char *in, int in_len, char *out, int *out_len) +int do_lzma_compress(char *in, int in_len, char *out, int *out_len) { if (in_len == 0) { ERROR("LZMA: Input length is zero.\n"); - return; + return -1; } CLzmaEncProps props; @@ -135,7 +135,7 @@ void do_lzma_compress(char *in, int in_len, char *out, int *out_len) int res = LzmaEnc_SetProps(p, &props); if (res != SZ_OK) { ERROR("LZMA: LzmaEnc_SetProps failed.\n"); - return; + return -1; } unsigned char propsEncoded[LZMA_PROPS_SIZE + 8]; @@ -143,7 +143,7 @@ void do_lzma_compress(char *in, int in_len, char *out, int *out_len) res = LzmaEnc_WriteProperties(p, propsEncoded, &propsSize); if (res != SZ_OK) { ERROR("LZMA: LzmaEnc_WriteProperties failed.\n"); - return; + return -1; } instream.p = in; @@ -160,17 +160,18 @@ void do_lzma_compress(char *in, int in_len, char *out, int *out_len) res = LzmaEnc_Encode(p, &os, &is, 0, &LZMAalloc, &LZMAalloc); if (res != SZ_OK) { ERROR("LZMA: LzmaEnc_Encode failed %d.\n", res); - return; + return -1; } *out_len = outstream.pos; + return 0; } -void do_lzma_uncompress(char *dst, int dst_len, char *src, int src_len) +int do_lzma_uncompress(char *dst, int dst_len, char *src, int src_len) { if (src_len <= LZMA_PROPS_SIZE + 8) { ERROR("LZMA: Input length is too small.\n"); - return; + return -1; } uint64_t out_sizemax = get_64(&src[LZMA_PROPS_SIZE]); @@ -178,7 +179,7 @@ void do_lzma_uncompress(char *dst, int dst_len, char *src, int src_len) if (out_sizemax > (size_t) dst_len) { ERROR("Not copying %d bytes to %d-byte buffer!\n", (unsigned int)out_sizemax, dst_len); - return; + return -1; } ELzmaStatus status; @@ -195,6 +196,8 @@ void do_lzma_uncompress(char *dst, int dst_len, char *src, int src_len) if (res != SZ_OK) { ERROR("Error while decompressing.\n"); - return; + return -1; } + + return 0; }