aboutsummaryrefslogtreecommitdiff
path: root/linux/lib/xz
diff options
context:
space:
mode:
authorLasse Collin <lasse.collin@tukaani.org>2009-04-27 12:32:42 +0300
committerLasse Collin <lasse.collin@tukaani.org>2009-04-27 12:32:42 +0300
commitb13c3147022a277d0bbb65a639d5eee3ec6bda80 (patch)
tree6d835a9903c00075a8c3f965b7f11daa850d9d96 /linux/lib/xz
parent6ffa14f3b019919dd7c8d3a768606c05f87fe729 (diff)
downloadxz-embedded-b13c3147022a277d0bbb65a639d5eee3ec6bda80.tar.gz
Refactor xz_dec_stream.c to silence a checkpatch.pl warning.
Diffstat (limited to 'linux/lib/xz')
-rw-r--r--linux/lib/xz/xz_dec_stream.c428
1 files changed, 232 insertions, 196 deletions
diff --git a/linux/lib/xz/xz_dec_stream.c b/linux/lib/xz/xz_dec_stream.c
index af878c4..231b521 100644
--- a/linux/lib/xz/xz_dec_stream.c
+++ b/linux/lib/xz/xz_dec_stream.c
@@ -26,9 +26,7 @@ struct xz_dec {
SEQ_BLOCK_UNCOMPRESS,
SEQ_BLOCK_PADDING,
SEQ_BLOCK_CHECK,
- SEQ_INDEX_COUNT,
- SEQ_INDEX_UNPADDED,
- SEQ_INDEX_UNCOMPRESSED,
+ SEQ_INDEX,
SEQ_INDEX_PADDING,
SEQ_INDEX_CRC32,
SEQ_STREAM_FOOTER
@@ -97,6 +95,13 @@ struct xz_dec {
/* Variables needed when verifying the Index field */
struct {
+ /* Position in dec_index() */
+ enum {
+ SEQ_INDEX_COUNT,
+ SEQ_INDEX_UNPADDED,
+ SEQ_INDEX_UNCOMPRESSED
+ } sequence;
+
/* Size of the Index in bytes */
vli_type size;
@@ -131,17 +136,6 @@ struct xz_dec {
#endif
};
-/* Call the raw filter decoder chain. */
-static enum xz_ret XZ_FUNC xz_dec_raw(struct xz_dec *s, struct xz_buf *b)
-{
-#ifdef XZ_DEC_BCJ
- if (s->bcj_active)
- return xz_dec_bcj_run(s->bcj, s->lzma2, b);
-#endif
-
- return xz_dec_lzma2_run(s->lzma2, b);
-}
-
/*
* Fill s->temp by copying data starting from b->in[b->in_pos]. Caller
* must have set s->temp.pos to indicate how much data we are supposed
@@ -197,6 +191,75 @@ static enum xz_ret XZ_FUNC dec_vli(struct xz_dec *s,
return XZ_OK;
}
+/*
+ * Decode the Compressed Data field from a Block. Update and validate
+ * the observed compressed and uncompressed sizes of the Block so that
+ * they don't exceed the values possibly stored in the Block Header
+ * (validation assumes that no integer overflow occurs, since vli_type
+ * is normally uint64_t). Update the CRC32 if presence of the CRC32
+ * field was indicated in Stream Header.
+ *
+ * Once the decoding is finished, validate that the observed sizes match
+ * the sizes possibly stored in the Block Header. Update the hash and
+ * Block count, which are later used to validate the Index field.
+ */
+static enum xz_ret dec_block(struct xz_dec *s, struct xz_buf *b)
+{
+ enum xz_ret ret;
+
+ s->in_start = b->in_pos;
+ s->out_start = b->out_pos;
+
+#ifdef XZ_DEC_BCJ
+ if (s->bcj_active)
+ ret = xz_dec_bcj_run(s->bcj, s->lzma2, b);
+ else
+#endif
+ ret = xz_dec_lzma2_run(s->lzma2, b);
+
+ s->block.compressed += b->in_pos - s->in_start;
+ s->block.uncompressed += b->out_pos - s->out_start;
+
+ /*
+ * There is no need to separately check for VLI_UNKNOWN, since
+ * the observed sizes are always smaller than VLI_UNKNOWN.
+ */
+ if (s->block.compressed > s->block_header.compressed
+ || s->block.uncompressed
+ > s->block_header.uncompressed)
+ return XZ_DATA_ERROR;
+
+ if (s->has_crc32)
+ s->crc32 = xz_crc32(b->out + s->out_start,
+ b->out_pos - s->out_start, s->crc32);
+
+ if (ret == XZ_STREAM_END) {
+ if (s->block_header.compressed != VLI_UNKNOWN
+ && s->block_header.compressed
+ != s->block.compressed)
+ return XZ_DATA_ERROR;
+
+ if (s->block_header.uncompressed != VLI_UNKNOWN
+ && s->block_header.uncompressed
+ != s->block.uncompressed)
+ return XZ_DATA_ERROR;
+
+ s->block.hash.unpadded += s->block_header.size
+ + s->block.compressed;
+ if (s->has_crc32)
+ s->block.hash.unpadded += 4;
+
+ s->block.hash.uncompressed += s->block.uncompressed;
+ s->block.hash.crc32 = xz_crc32(
+ (const uint8_t *)&s->block.hash,
+ sizeof(s->block.hash), s->block.hash.crc32);
+
+ ++s->block.count;
+ }
+
+ return ret;
+}
+
/* Update the Index size and the CRC32 value. */
static void XZ_FUNC index_update(struct xz_dec *s, const struct xz_buf *b)
{
@@ -206,6 +269,60 @@ static void XZ_FUNC index_update(struct xz_dec *s, const struct xz_buf *b)
}
/*
+ * Decode the Number of Records, Unpadded Size, and Uncompressed Size
+ * fields from the Index field. That is, Index Padding and CRC32 are not
+ * decoded by this function.
+ *
+ * This can return XZ_OK (more input needed), XZ_STREAM_END (everything
+ * successfully decoded), or XZ_DATA_ERROR (input is corrupt).
+ */
+static enum xz_ret dec_index(struct xz_dec *s, struct xz_buf *b)
+{
+ enum xz_ret ret;
+
+ do {
+ ret = dec_vli(s, b->in, &b->in_pos, b->in_size);
+ if (ret != XZ_STREAM_END) {
+ index_update(s, b);
+ return ret;
+ }
+
+ switch (s->index.sequence) {
+ case SEQ_INDEX_COUNT:
+ s->index.count = s->vli;
+
+ /*
+ * Validate that the Number of Records field
+ * indicates the same number of Records as
+ * there were Blocks in the Stream.
+ */
+ if (s->index.count != s->block.count)
+ return XZ_DATA_ERROR;
+
+ s->index.sequence = SEQ_INDEX_UNPADDED;
+ break;
+
+ case SEQ_INDEX_UNPADDED:
+ s->index.hash.unpadded += s->vli;
+ s->index.sequence = SEQ_INDEX_UNCOMPRESSED;
+ break;
+
+ case SEQ_INDEX_UNCOMPRESSED:
+ s->index.hash.uncompressed += s->vli;
+ s->index.hash.crc32 = xz_crc32(
+ (const uint8_t *)&s->index.hash,
+ sizeof(s->index.hash),
+ s->index.hash.crc32);
+ --s->index.count;
+ s->index.sequence = SEQ_INDEX_UNPADDED;
+ break;
+ }
+ } while (s->index.count > 0);
+
+ return XZ_STREAM_END;
+}
+
+/*
* Validate that the next four input bytes match the value of s->crc32.
* s->pos must be zero when starting to validate the first byte.
*/
@@ -389,220 +506,139 @@ static enum xz_ret XZ_FUNC dec_main(struct xz_dec *s, struct xz_buf *b)
*/
s->in_start = b->in_pos;
- while (true)
- switch (s->sequence) {
- case SEQ_STREAM_HEADER:
- /*
- * Stream Header is copied to s->temp, and then decoded
- * from there. This way if the caller gives us only little
- * input at a time, we can still keep the Stream Header
- * decoding code still simple. Similar approach is used
- * in many places in this file.
- */
- if (!fill_temp(s, b))
- return XZ_OK;
+ while (true) {
+ switch (s->sequence) {
+ case SEQ_STREAM_HEADER:
+ /*
+ * Stream Header is copied to s->temp, and then
+ * decoded from there. This way if the caller
+ * gives us only little input at a time, we can
+ * still keep the Stream Header decoding code
+ * simple. Similar approach is used in many places
+ * in this file.
+ */
+ if (!fill_temp(s, b))
+ return XZ_OK;
- ret = dec_stream_header(s);
- if (ret != XZ_OK)
- return ret;
+ ret = dec_stream_header(s);
+ if (ret != XZ_OK)
+ return ret;
- s->sequence = SEQ_BLOCK_START;
+ s->sequence = SEQ_BLOCK_START;
- case SEQ_BLOCK_START:
- /* We need one byte of input to continue. */
- if (b->in_pos == b->in_size)
- return XZ_OK;
+ case SEQ_BLOCK_START:
+ /* We need one byte of input to continue. */
+ if (b->in_pos == b->in_size)
+ return XZ_OK;
- /* See if this is the beginning of the Index field. */
- if (b->in[b->in_pos] == 0) {
- s->in_start = b->in_pos++;
- s->sequence = SEQ_INDEX_COUNT;
- break;
- }
+ /* See if this is the beginning of the Index field. */
+ if (b->in[b->in_pos] == 0) {
+ s->in_start = b->in_pos++;
+ s->sequence = SEQ_INDEX;
+ break;
+ }
- /*
- * Calculate the size of the Block Header and prepare
- * to decode it.
- */
- s->block_header.size = ((uint32_t)b->in[b->in_pos] + 1) * 4;
+ /*
+ * Calculate the size of the Block Header and
+ * prepare to decode it.
+ */
+ s->block_header.size
+ = ((uint32_t)b->in[b->in_pos] + 1) * 4;
- s->temp.size = s->block_header.size;
- s->temp.pos = 0;
- s->sequence = SEQ_BLOCK_HEADER;
+ s->temp.size = s->block_header.size;
+ s->temp.pos = 0;
+ s->sequence = SEQ_BLOCK_HEADER;
- case SEQ_BLOCK_HEADER:
- if (!fill_temp(s, b))
- return XZ_OK;
+ case SEQ_BLOCK_HEADER:
+ if (!fill_temp(s, b))
+ return XZ_OK;
- ret = dec_block_header(s);
- if (ret != XZ_OK)
- return ret;
+ ret = dec_block_header(s);
+ if (ret != XZ_OK)
+ return ret;
- s->sequence = SEQ_BLOCK_UNCOMPRESS;
+ s->sequence = SEQ_BLOCK_UNCOMPRESS;
- case SEQ_BLOCK_UNCOMPRESS:
- s->in_start = b->in_pos;
- s->out_start = b->out_pos;
+ case SEQ_BLOCK_UNCOMPRESS:
+ ret = dec_block(s, b);
+ if (ret != XZ_STREAM_END)
+ return ret;
- ret = xz_dec_raw(s, b);
+ s->sequence = SEQ_BLOCK_PADDING;
+
+ case SEQ_BLOCK_PADDING:
+ /*
+ * Size of Compressed Data + Block Padding
+ * must be a multiple of four. We don't need
+ * s->block.compressed for anything else
+ * anymore, so we use it here to test the size
+ * of the Block Padding field.
+ */
+ while (s->block.compressed & 3) {
+ if (b->in_pos == b->in_size)
+ return XZ_OK;
+
+ if (b->in[b->in_pos++] != 0)
+ return XZ_DATA_ERROR;
- s->block.compressed += b->in_pos - s->in_start;
- s->block.uncompressed += b->out_pos - s->out_start;
+ ++s->block.compressed;
+ }
- if (s->block.compressed > s->block_header.compressed
- || s->block.uncompressed
- > s->block_header.uncompressed)
- return XZ_DATA_ERROR;
+ s->sequence = SEQ_BLOCK_CHECK;
- if (s->has_crc32)
- s->crc32 = xz_crc32(b->out + s->out_start,
- b->out_pos - s->out_start, s->crc32);
+ case SEQ_BLOCK_CHECK:
+ if (s->has_crc32) {
+ ret = crc32_validate(s, b);
+ if (ret != XZ_STREAM_END)
+ return ret;
+ }
- if (ret != XZ_STREAM_END)
- return ret;
+ s->sequence = SEQ_BLOCK_START;
+ break;
- /*
- * If sizes were stored in Block Header, they must match
- * the observed sizes now.
- */
- if (s->block_header.compressed != VLI_UNKNOWN
- && s->block_header.compressed
- != s->block.compressed)
- return XZ_DATA_ERROR;
+ case SEQ_INDEX:
+ ret = dec_index(s, b);
+ if (ret != XZ_STREAM_END)
+ return ret;
- if (s->block_header.uncompressed != VLI_UNKNOWN
- && s->block_header.uncompressed
- != s->block.uncompressed)
- return XZ_DATA_ERROR;
+ s->sequence = SEQ_INDEX_PADDING;
- /*
- * Update the hash and count, which are used for
- * Index validation.
- */
- s->block.hash.unpadded += s->block_header.size
- + s->block.compressed;
- if (s->has_crc32)
- s->block.hash.unpadded += 4;
+ case SEQ_INDEX_PADDING:
+ while ((s->index.size + (b->in_pos - s->in_start))
+ & 3) {
+ if (b->in_pos == b->in_size) {
+ index_update(s, b);
+ return XZ_OK;
+ }
- s->block.hash.uncompressed += s->block.uncompressed;
- s->block.hash.crc32 = xz_crc32(
- (const uint8_t *)&s->block.hash,
- sizeof(s->block.hash), s->block.hash.crc32);
+ if (b->in[b->in_pos++] != 0)
+ return XZ_DATA_ERROR;
+ }
- ++s->block.count;
- s->sequence = SEQ_BLOCK_PADDING;
+ /* Finish the CRC32 value and Index size. */
+ index_update(s, b);
- case SEQ_BLOCK_PADDING:
- /*
- * Size of Compressed Data + Block Padding must be a
- * multiple of four. We don't need s->d->block.compressed
- * for anything else anymore, so we use it here to test the
- * size of the Block Padding field.
- */
- while (s->block.compressed & 3) {
- if (b->in_pos == b->in_size)
- return XZ_OK;
-
- if (b->in[b->in_pos++] != 0)
+ /* Compare the hashes to validate the Index field. */
+ if (!memeq(&s->block.hash, &s->index.hash,
+ sizeof(s->block.hash)))
return XZ_DATA_ERROR;
- ++s->block.compressed;
- }
-
- s->sequence = SEQ_BLOCK_CHECK;
+ s->sequence = SEQ_INDEX_CRC32;
- case SEQ_BLOCK_CHECK:
- if (s->has_crc32) {
+ case SEQ_INDEX_CRC32:
ret = crc32_validate(s, b);
if (ret != XZ_STREAM_END)
return ret;
- }
-
- s->sequence = SEQ_BLOCK_START;
- break;
-
- case SEQ_INDEX_COUNT:
- case SEQ_INDEX_UNPADDED:
- case SEQ_INDEX_UNCOMPRESSED:
- do {
- ret = dec_vli(s, b->in, &b->in_pos, b->in_size);
- if (ret != XZ_STREAM_END) {
- index_update(s, b);
- return ret;
- }
-
- switch (s->sequence) {
- case SEQ_INDEX_COUNT:
- s->index.count = s->vli;
- /*
- * Validate that the Number of Records field
- * indicates the same number of Records as
- * there were Blocks in the Stream.
- */
- if (s->index.count != s->block.count)
- return XZ_DATA_ERROR;
-
- s->sequence = SEQ_INDEX_UNPADDED;
- break;
-
- case SEQ_INDEX_UNPADDED:
- s->index.hash.unpadded += s->vli;
- s->sequence = SEQ_INDEX_UNCOMPRESSED;
- break;
+ s->temp.size = STREAM_HEADER_SIZE;
+ s->sequence = SEQ_STREAM_FOOTER;
- case SEQ_INDEX_UNCOMPRESSED:
- s->index.hash.uncompressed += s->vli;
- s->index.hash.crc32 = xz_crc32(
- (const uint8_t *)&s->index.hash,
- sizeof(s->index.hash),
- s->index.hash.crc32);
- --s->index.count;
- s->sequence = SEQ_INDEX_UNPADDED;
- break;
-
- default:
- /* Silence compiler warnings */
- break;
- }
- } while (s->index.count > 0);
-
- s->sequence = SEQ_INDEX_PADDING;
-
- case SEQ_INDEX_PADDING:
- while ((s->index.size + (b->in_pos - s->in_start)) & 3) {
- if (b->in_pos == b->in_size) {
- index_update(s, b);
+ case SEQ_STREAM_FOOTER:
+ if (!fill_temp(s, b))
return XZ_OK;
- }
- if (b->in[b->in_pos++] != 0)
- return XZ_DATA_ERROR;
+ return dec_stream_footer(s);
}
-
- /* Finish the CRC32 value and Index size. */
- index_update(s, b);
-
- /* Compare the hashes to validate the Index field. */
- if (!memeq(&s->block.hash, &s->index.hash,
- sizeof(s->block.hash)))
- return XZ_DATA_ERROR;
-
- s->sequence = SEQ_INDEX_CRC32;
-
- case SEQ_INDEX_CRC32:
- ret = crc32_validate(s, b);
- if (ret != XZ_STREAM_END)
- return ret;
-
- s->temp.size = STREAM_HEADER_SIZE;
- s->sequence = SEQ_STREAM_FOOTER;
-
- case SEQ_STREAM_FOOTER:
- if (!fill_temp(s, b))
- return XZ_OK;
-
- return dec_stream_footer(s);
}
/* Never reached */