diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2008-06-27 15:48:45 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2008-06-27 15:48:45 +0000 |
commit | 2bbdda09dfaf5f2c788ce38aba80a1e562c954c8 (patch) | |
tree | bbb21e80c548f0366de676df9e216cabd2d86303 /archival | |
parent | ac2b50ebeaa23d75920fba71cf7a2683690c17da (diff) | |
download | busybox-w32-2bbdda09dfaf5f2c788ce38aba80a1e562c954c8.tar.gz busybox-w32-2bbdda09dfaf5f2c788ce38aba80a1e562c954c8.tar.bz2 busybox-w32-2bbdda09dfaf5f2c788ce38aba80a1e562c954c8.zip |
unlzma: fix memory leak (Pascal Bellard)
Diffstat (limited to 'archival')
-rw-r--r-- | archival/libunarchive/decompress_unlzma.c | 43 |
1 files changed, 23 insertions, 20 deletions
diff --git a/archival/libunarchive/decompress_unlzma.c b/archival/libunarchive/decompress_unlzma.c index 79df70179..2cfcd9b7d 100644 --- a/archival/libunarchive/decompress_unlzma.c +++ b/archival/libunarchive/decompress_unlzma.c | |||
@@ -45,7 +45,7 @@ typedef struct { | |||
45 | 45 | ||
46 | 46 | ||
47 | /* Called twice: once at startup and once in rc_normalize() */ | 47 | /* Called twice: once at startup and once in rc_normalize() */ |
48 | static void rc_read(rc_t * rc) | 48 | static void rc_read(rc_t *rc) |
49 | { | 49 | { |
50 | int buffer_size = safe_read(rc->fd, RC_BUFFER, RC_BUFFER_SIZE); | 50 | int buffer_size = safe_read(rc->fd, RC_BUFFER, RC_BUFFER_SIZE); |
51 | if (buffer_size <= 0) | 51 | if (buffer_size <= 0) |
@@ -58,9 +58,9 @@ static void rc_read(rc_t * rc) | |||
58 | static rc_t* rc_init(int fd) /*, int buffer_size) */ | 58 | static rc_t* rc_init(int fd) /*, int buffer_size) */ |
59 | { | 59 | { |
60 | int i; | 60 | int i; |
61 | rc_t* rc; | 61 | rc_t *rc; |
62 | 62 | ||
63 | rc = xmalloc(sizeof(rc_t) + RC_BUFFER_SIZE); | 63 | rc = xmalloc(sizeof(*rc) + RC_BUFFER_SIZE); |
64 | 64 | ||
65 | rc->fd = fd; | 65 | rc->fd = fd; |
66 | /* rc->buffer_size = buffer_size; */ | 66 | /* rc->buffer_size = buffer_size; */ |
@@ -78,21 +78,20 @@ static rc_t* rc_init(int fd) /*, int buffer_size) */ | |||
78 | } | 78 | } |
79 | 79 | ||
80 | /* Called once */ | 80 | /* Called once */ |
81 | static ALWAYS_INLINE void rc_free(rc_t * rc) | 81 | static ALWAYS_INLINE void rc_free(rc_t *rc) |
82 | { | 82 | { |
83 | if (ENABLE_FEATURE_CLEAN_UP) | 83 | free(rc); |
84 | free(rc); | ||
85 | } | 84 | } |
86 | 85 | ||
87 | /* Called twice, but one callsite is in speed_inline'd rc_is_bit_0_helper() */ | 86 | /* Called twice, but one callsite is in speed_inline'd rc_is_bit_0_helper() */ |
88 | static void rc_do_normalize(rc_t * rc) | 87 | static void rc_do_normalize(rc_t *rc) |
89 | { | 88 | { |
90 | if (rc->ptr >= rc->buffer_end) | 89 | if (rc->ptr >= rc->buffer_end) |
91 | rc_read(rc); | 90 | rc_read(rc); |
92 | rc->range <<= 8; | 91 | rc->range <<= 8; |
93 | rc->code = (rc->code << 8) | *rc->ptr++; | 92 | rc->code = (rc->code << 8) | *rc->ptr++; |
94 | } | 93 | } |
95 | static ALWAYS_INLINE void rc_normalize(rc_t * rc) | 94 | static ALWAYS_INLINE void rc_normalize(rc_t *rc) |
96 | { | 95 | { |
97 | if (rc->range < (1 << RC_TOP_BITS)) { | 96 | if (rc->range < (1 << RC_TOP_BITS)) { |
98 | rc_do_normalize(rc); | 97 | rc_do_normalize(rc); |
@@ -105,25 +104,25 @@ static ALWAYS_INLINE void rc_normalize(rc_t * rc) | |||
105 | * Thus rc_is_bit_0 is always inlined, and rc_is_bit_0_helper is inlined | 104 | * Thus rc_is_bit_0 is always inlined, and rc_is_bit_0_helper is inlined |
106 | * only if we compile for speed. | 105 | * only if we compile for speed. |
107 | */ | 106 | */ |
108 | static speed_inline uint32_t rc_is_bit_0_helper(rc_t * rc, uint16_t * p) | 107 | static speed_inline uint32_t rc_is_bit_0_helper(rc_t *rc, uint16_t *p) |
109 | { | 108 | { |
110 | rc_normalize(rc); | 109 | rc_normalize(rc); |
111 | rc->bound = *p * (rc->range >> RC_MODEL_TOTAL_BITS); | 110 | rc->bound = *p * (rc->range >> RC_MODEL_TOTAL_BITS); |
112 | return rc->bound; | 111 | return rc->bound; |
113 | } | 112 | } |
114 | static ALWAYS_INLINE int rc_is_bit_0(rc_t * rc, uint16_t * p) | 113 | static ALWAYS_INLINE int rc_is_bit_0(rc_t *rc, uint16_t *p) |
115 | { | 114 | { |
116 | uint32_t t = rc_is_bit_0_helper(rc, p); | 115 | uint32_t t = rc_is_bit_0_helper(rc, p); |
117 | return rc->code < t; | 116 | return rc->code < t; |
118 | } | 117 | } |
119 | 118 | ||
120 | /* Called ~10 times, but very small, thus inlined */ | 119 | /* Called ~10 times, but very small, thus inlined */ |
121 | static speed_inline void rc_update_bit_0(rc_t * rc, uint16_t * p) | 120 | static speed_inline void rc_update_bit_0(rc_t *rc, uint16_t *p) |
122 | { | 121 | { |
123 | rc->range = rc->bound; | 122 | rc->range = rc->bound; |
124 | *p += ((1 << RC_MODEL_TOTAL_BITS) - *p) >> RC_MOVE_BITS; | 123 | *p += ((1 << RC_MODEL_TOTAL_BITS) - *p) >> RC_MOVE_BITS; |
125 | } | 124 | } |
126 | static speed_inline void rc_update_bit_1(rc_t * rc, uint16_t * p) | 125 | static speed_inline void rc_update_bit_1(rc_t *rc, uint16_t *p) |
127 | { | 126 | { |
128 | rc->range -= rc->bound; | 127 | rc->range -= rc->bound; |
129 | rc->code -= rc->bound; | 128 | rc->code -= rc->bound; |
@@ -131,7 +130,7 @@ static speed_inline void rc_update_bit_1(rc_t * rc, uint16_t * p) | |||
131 | } | 130 | } |
132 | 131 | ||
133 | /* Called 4 times in unlzma loop */ | 132 | /* Called 4 times in unlzma loop */ |
134 | static int rc_get_bit(rc_t * rc, uint16_t * p, int *symbol) | 133 | static int rc_get_bit(rc_t *rc, uint16_t *p, int *symbol) |
135 | { | 134 | { |
136 | if (rc_is_bit_0(rc, p)) { | 135 | if (rc_is_bit_0(rc, p)) { |
137 | rc_update_bit_0(rc, p); | 136 | rc_update_bit_0(rc, p); |
@@ -145,7 +144,7 @@ static int rc_get_bit(rc_t * rc, uint16_t * p, int *symbol) | |||
145 | } | 144 | } |
146 | 145 | ||
147 | /* Called once */ | 146 | /* Called once */ |
148 | static ALWAYS_INLINE int rc_direct_bit(rc_t * rc) | 147 | static ALWAYS_INLINE int rc_direct_bit(rc_t *rc) |
149 | { | 148 | { |
150 | rc_normalize(rc); | 149 | rc_normalize(rc); |
151 | rc->range >>= 1; | 150 | rc->range >>= 1; |
@@ -158,7 +157,7 @@ static ALWAYS_INLINE int rc_direct_bit(rc_t * rc) | |||
158 | 157 | ||
159 | /* Called twice */ | 158 | /* Called twice */ |
160 | static speed_inline void | 159 | static speed_inline void |
161 | rc_bit_tree_decode(rc_t * rc, uint16_t * p, int num_levels, int *symbol) | 160 | rc_bit_tree_decode(rc_t *rc, uint16_t *p, int num_levels, int *symbol) |
162 | { | 161 | { |
163 | int i = num_levels; | 162 | int i = num_levels; |
164 | 163 | ||
@@ -489,12 +488,16 @@ unpack_lzma_stream(int src_fd, int dst_fd) | |||
489 | } | 488 | } |
490 | } | 489 | } |
491 | 490 | ||
492 | if (full_write(dst_fd, buffer, buffer_pos) != (ssize_t)buffer_pos) { | 491 | { |
492 | SKIP_DESKTOP(int total_written = 0; /* success */) | ||
493 | USE_DESKTOP(total_written += buffer_pos;) | ||
494 | if (full_write(dst_fd, buffer, buffer_pos) != (ssize_t)buffer_pos) { | ||
493 | bad: | 495 | bad: |
496 | total_written = -1; /* failure */ | ||
497 | } | ||
494 | rc_free(rc); | 498 | rc_free(rc); |
495 | return -1; | 499 | free(p); |
500 | free(buffer); | ||
501 | return total_written; | ||
496 | } | 502 | } |
497 | rc_free(rc); | ||
498 | USE_DESKTOP(total_written += buffer_pos;) | ||
499 | return USE_DESKTOP(total_written) + 0; | ||
500 | } | 503 | } |