summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEwald Snel <esnel@users.sourceforge.net>2002-12-31 20:15:51 +0000
committerEwald Snel <esnel@users.sourceforge.net>2002-12-31 20:15:51 +0000
commit045fb8e68b54798d706bfcc6e739b26667ca5e85 (patch)
treee7d25f03c23b96334d792cdfaf1f643d1583b7ef /src
parent88fa2176e1cf0d862dca82d44673bc8f266c5bde (diff)
downloadxine-lib-045fb8e68b54798d706bfcc6e739b26667ca5e85.tar.gz
xine-lib-045fb8e68b54798d706bfcc6e739b26667ca5e85.tar.bz2
Protect against input buffer overflow
CVS patchset: 3737 CVS date: 2002/12/31 20:15:51
Diffstat (limited to 'src')
-rw-r--r--src/libxinevdec/svq1.c44
1 files changed, 30 insertions, 14 deletions
diff --git a/src/libxinevdec/svq1.c b/src/libxinevdec/svq1.c
index c6eddab67..d52e156e8 100644
--- a/src/libxinevdec/svq1.c
+++ b/src/libxinevdec/svq1.c
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
- * $Id: svq1.c,v 1.19 2002/12/21 12:56:49 miguelfreitas Exp $
+ * $Id: svq1.c,v 1.20 2002/12/31 20:15:51 esnel Exp $
*/
#include <stdio.h>
@@ -50,7 +50,8 @@
/* memory bit stream */
typedef struct bit_buffer_s {
uint8_t *buffer;
- uint32_t bitpos;
+ unsigned int bitpos;
+ unsigned int length;
} bit_buffer_t;
/* variable length (bit) code */
@@ -579,11 +580,23 @@ static vlc_code_t inter_mean_table_5[292] = {
static uint32_t get_bits (bit_buffer_t *bitbuf, int count) {
uint32_t result;
- /* load 32 bits of data (byte-aligned) */
- result = BE_32 (&bitbuf->buffer[bitbuf->bitpos >> 3]);
+ /* avoid buffer overflow */
+ if ((bitbuf->bitpos + 24) >= bitbuf->length) {
+ int i;
- /* compensate for sub-byte offset */
- result <<= (bitbuf->bitpos & 0x7);
+ /* load upto 24 bits of data on sub-byte offset */
+ result = 0;
+
+ for (i=(bitbuf->bitpos & ~0x7); i < bitbuf->length; i+=8) {
+ result |= bitbuf->buffer[i >> 3] << (24 + (bitbuf->bitpos - i));
+ }
+ } else {
+ /* load 32 bits of data (byte-aligned) */
+ result = BE_32 (&bitbuf->buffer[bitbuf->bitpos >> 3]);
+
+ /* compensate for sub-byte offset */
+ result <<= (bitbuf->bitpos & 0x7);
+ }
/* flush num bits */
bitbuf->bitpos += count;
@@ -1135,7 +1148,7 @@ static int decode_frame_header (bit_buffer_t *bitbuf, svq1_t *svq1) {
return 0;
}
-static int svq1_decode_frame (svq1_t *svq1, uint8_t *buffer) {
+static int svq1_decode_frame (svq1_t *svq1, uint8_t *buffer, int length) {
bit_buffer_t bitbuf;
uint8_t *current, *previous;
int result, i, x, y, width, height;
@@ -1144,6 +1157,7 @@ static int svq1_decode_frame (svq1_t *svq1, uint8_t *buffer) {
/* initialize bit buffer */
bitbuf.buffer = buffer;
bitbuf.bitpos = 0;
+ bitbuf.length = 8*length;
/* decode frame header */
svq1->frame_code = get_bits (&bitbuf, 22);
@@ -1162,7 +1176,7 @@ static int svq1_decode_frame (svq1_t *svq1, uint8_t *buffer) {
result = decode_frame_header (&bitbuf, svq1);
- if (result != 0)
+ if (result != 0 || bitbuf.bitpos > bitbuf.length)
return result;
/* check frame size (changed?) */
@@ -1222,7 +1236,7 @@ static int svq1_decode_frame (svq1_t *svq1, uint8_t *buffer) {
for (x=0; x < width; x+=16) {
result = decode_svq1_block (&bitbuf, &current[x], width, 1);
- if (result != 0)
+ if (result != 0 || bitbuf.bitpos > bitbuf.length)
return result;
}
@@ -1237,7 +1251,7 @@ static int svq1_decode_frame (svq1_t *svq1, uint8_t *buffer) {
result = decode_delta_block (&bitbuf, &current[x], previous,
width, svq1->motion, x, y);
- if (result != 0)
+ if (result != 0 || bitbuf.bitpos > bitbuf.length)
return result;
}
@@ -1306,14 +1320,16 @@ static void svq1dec_decode_data (video_decoder_t *this_gen, buf_element_t *buf)
vo_frame_t *img;
int result;
- result = svq1_decode_frame (this->svq1, this->buf);
+ result = svq1_decode_frame (this->svq1, this->buf, this->size);
if (this->svq1->width > 0 && this->svq1->height > 0) {
img = this->stream->video_out->get_frame (this->stream->video_out,
- this->svq1->width,
- this->svq1->height,
- XINE_VO_ASPECT_DONT_TOUCH, XINE_IMGFMT_YV12, VO_BOTH_FIELDS);
+ this->svq1->width,
+ this->svq1->height,
+ XINE_VO_ASPECT_DONT_TOUCH,
+ XINE_IMGFMT_YV12,
+ VO_BOTH_FIELDS);
img->duration = this->video_step;
img->pts = buf->pts;