WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] [xen-unstable] Decompressors: check for write errors in

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] Decompressors: check for write errors in unlzma.c
From: Xen patchbot-unstable <patchbot@xxxxxxx>
Date: Fri, 11 Nov 2011 21:11:15 +0000
Delivery-date: Fri, 11 Nov 2011 13:13:15 -0800
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User Lasse Collin <lasse.collin@xxxxxxxxxxx>
# Date 1321018410 -3600
# Node ID 2ffeeb28e9be98c932905f7fd2bf80bfc089622c
# Parent  fe9a59ff84750086b731c5be84417f8d302d84db
Decompressors: check for write errors in unlzma.c

From: Lasse Collin <lasse.collin@xxxxxxxxxxx>

The return value of wr->flush() is not checked in write_byte().  This
means that the decompressor won't stop even if the caller doesn't want
more data.  This can happen e.g.  with corrupt LZMA-compressed initramfs.
Returning the error quickly allows the user to see the error message
quicker.

There is a similar missing check for wr.flush() near the end of unlzma().

Signed-off-by: Lasse Collin <lasse.collin@xxxxxxxxxxx>
Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx>
Acked-by: Keir Fraser <keir@xxxxxxx>
Committed-by: Jan Beulich <jbeulich@xxxxxxxx>
---


diff -r fe9a59ff8475 -r 2ffeeb28e9be xen/common/unlzma.c
--- a/xen/common/unlzma.c       Fri Nov 11 14:32:57 2011 +0100
+++ b/xen/common/unlzma.c       Fri Nov 11 14:33:30 2011 +0100
@@ -307,32 +307,38 @@
 
 }
 
-static inline void INIT write_byte(struct writer *wr, uint8_t byte)
+static inline int INIT write_byte(struct writer *wr, uint8_t byte)
 {
        wr->buffer[wr->buffer_pos++] = wr->previous_byte = byte;
        if (wr->flush && wr->buffer_pos == wr->header->dict_size) {
                wr->buffer_pos = 0;
                wr->global_pos += wr->header->dict_size;
-               wr->flush((char *)wr->buffer, wr->header->dict_size);
+               if (wr->flush((char *)wr->buffer, wr->header->dict_size)
+                               != wr->header->dict_size)
+                       return -1;
        }
+       return 0;
 }
 
 
-static inline void INIT copy_byte(struct writer *wr, uint32_t offs)
+static inline int INIT copy_byte(struct writer *wr, uint32_t offs)
 {
-       write_byte(wr, peek_old_byte(wr, offs));
+       return write_byte(wr, peek_old_byte(wr, offs));
 }
 
-static inline void INIT copy_bytes(struct writer *wr,
+static inline int INIT copy_bytes(struct writer *wr,
                                         uint32_t rep0, int len)
 {
        do {
-               copy_byte(wr, rep0);
+               if (copy_byte(wr, rep0))
+                       return -1;
                len--;
        } while (len != 0 && wr->buffer_pos < wr->header->dst_size);
+
+       return len;
 }
 
-static inline void INIT process_bit0(struct writer *wr, struct rc *rc,
+static inline int INIT process_bit0(struct writer *wr, struct rc *rc,
                                     struct cstate *cst, uint16_t *p,
                                     int pos_state, uint16_t *prob,
                                     int lc, uint32_t literal_pos_mask) {
@@ -366,16 +372,17 @@
                uint16_t *prob_lit = prob + mi;
                rc_get_bit(rc, prob_lit, &mi);
        }
-       write_byte(wr, mi);
        if (cst->state < 4)
                cst->state = 0;
        else if (cst->state < 10)
                cst->state -= 3;
        else
                cst->state -= 6;
+
+       return write_byte(wr, mi);
 }
 
-static inline void INIT process_bit1(struct writer *wr, struct rc *rc,
+static inline int INIT process_bit1(struct writer *wr, struct rc *rc,
                                            struct cstate *cst, uint16_t *p,
                                            int pos_state, uint16_t *prob) {
   int offset;
@@ -406,8 +413,7 @@
 
                                cst->state = cst->state < LZMA_NUM_LIT_STATES ?
                                        9 : 11;
-                               copy_byte(wr, cst->rep0);
-                               return;
+                               return copy_byte(wr, cst->rep0);
                        } else {
                                rc_update_bit_1(rc, prob);
                        }
@@ -509,12 +515,12 @@
                } else
                        cst->rep0 = pos_slot;
                if (++(cst->rep0) == 0)
-                       return;
+                       return 0;
        }
 
        len += LZMA_MATCH_MIN_LEN;
 
-       copy_bytes(wr, cst->rep0, len);
+       return copy_bytes(wr, cst->rep0, len);
 }
 
 
@@ -617,11 +623,17 @@
                int pos_state = get_pos(&wr) & pos_state_mask;
                uint16_t *prob = p + LZMA_IS_MATCH +
                        (cst.state << LZMA_NUM_POS_BITS_MAX) + pos_state;
-               if (rc_is_bit_0(&rc, prob))
-                       process_bit0(&wr, &rc, &cst, p, pos_state, prob,
-                                    lc, literal_pos_mask);
-               else {
-                       process_bit1(&wr, &rc, &cst, p, pos_state, prob);
+               if (rc_is_bit_0(&rc, prob)) {
+                       if (process_bit0(&wr, &rc, &cst, p, pos_state, prob,
+                                       lc, literal_pos_mask)) {
+                               error("LZMA data is corrupt");
+                               goto exit_3;
+                       }
+               } else {
+                       if (process_bit1(&wr, &rc, &cst, p, pos_state, prob)) {
+                               error("LZMA data is corrupt");
+                               goto exit_3;
+                       }
                        if (cst.rep0 == 0)
                                break;
                }
@@ -631,9 +643,8 @@
 
        if (posp)
                *posp = rc.ptr-rc.buffer;
-       if (wr.flush)
-               wr.flush(wr.buffer, wr.buffer_pos);
-       ret = 0;
+       if (!wr.flush || wr.flush(wr.buffer, wr.buffer_pos) == wr.buffer_pos)
+               ret = 0;
 exit_3:
        large_free(p);
 exit_2:

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] Decompressors: check for write errors in unlzma.c, Xen patchbot-unstable <=