Vulnerability: libav before 12.1 is vulnerable to an invalid read of size 1 due to NULL pointer dereferencing in the nsv_read_chunk function in libavformat/nsvdec.c.
Vulnerability ID: CVE-2017-9051
CWE: CWE-476
Severity score: 6.4
Project: https://github.com/libav/libav
Published: 2017-05-18
File: libavformat/nsvdec.c
Commit message: nsvdec: don't ignore the return value of av_get_packet()

Fixes invalid reads with corrupted files.

CC: libav-stable@libav.org
Bug-Id: 1039
Commit author: Sean McGovern

Vulnerable version (before fix):
 static int nsv_read_chunk(AVFormatContext *s, int fill_header)     uint32_t vsize;     uint16_t asize;     uint16_t auxsize;      if (nsv->ahead[0].data || nsv->ahead[1].data)         return 0; //-1; /* hey! eat what you've in your plate first! */ static int nsv_read_chunk(AVFormatContext *s, int fill_header)     if (vsize && st[NSV_ST_VIDEO]) {         nst = st[NSV_ST_VIDEO]->priv_data;         pkt = &nsv->ahead[NSV_ST_VIDEO];         av_get_packet(pb, pkt, vsize);         pkt->stream_index = st[NSV_ST_VIDEO]->index;//NSV_ST_VIDEO;         pkt->dts = nst->frame_offset;         pkt->flags |= nsv->state == NSV_HAS_READ_NSVS ? AV_PKT_FLAG_KEY : 0; /* keyframe only likely on a sync frame */ static int nsv_read_chunk(AVFormatContext *s, int fill_header)                        bps, channels, samplerate);             }         }         av_get_packet(pb, pkt, asize);         pkt->stream_index = st[NSV_ST_AUDIO]->index;//NSV_ST_AUDIO;         pkt->flags |= nsv->state == NSV_HAS_READ_NSVS ? AV_PKT_FLAG_KEY : 0; /* keyframe only likely on a sync frame */         if( nsv->state == NSV_HAS_READ_NSVS && st[NSV_ST_VIDEO] ) {

Fixed version (after fix):
 static int nsv_read_chunk(AVFormatContext *s, int fill_header)     uint32_t vsize;     uint16_t asize;     uint16_t auxsize;     int ret;      if (nsv->ahead[0].data || nsv->ahead[1].data)         return 0; //-1; /* hey! eat what you've in your plate first! */ static int nsv_read_chunk(AVFormatContext *s, int fill_header)     if (vsize && st[NSV_ST_VIDEO]) {         nst = st[NSV_ST_VIDEO]->priv_data;         pkt = &nsv->ahead[NSV_ST_VIDEO];         if ((ret = av_get_packet(pb, pkt, vsize)) < 0)             return ret;         pkt->stream_index = st[NSV_ST_VIDEO]->index;//NSV_ST_VIDEO;         pkt->dts = nst->frame_offset;         pkt->flags |= nsv->state == NSV_HAS_READ_NSVS ? AV_PKT_FLAG_KEY : 0; /* keyframe only likely on a sync frame */ static int nsv_read_chunk(AVFormatContext *s, int fill_header)                        bps, channels, samplerate);             }         }         if ((ret = av_get_packet(pb, pkt, asize)) < 0)             return ret;         pkt->stream_index = st[NSV_ST_AUDIO]->index;//NSV_ST_AUDIO;         pkt->flags |= nsv->state == NSV_HAS_READ_NSVS ? AV_PKT_FLAG_KEY : 0; /* keyframe only likely on a sync frame */         if( nsv->state == NSV_HAS_READ_NSVS && st[NSV_ST_VIDEO] ) {

Patch:
patch: @@ -520,6 +520,7 @@ static int nsv_read_chunk(AVFormatContext *s, int fill_header)
     uint32_t vsize;
     uint16_t asize;
     uint16_t auxsize;
+    int ret;
 
     if (nsv->ahead[0].data || nsv->ahead[1].data)
         return 0; //-1; /* hey! eat what you've in your plate first! */
@@ -571,7 +572,8 @@ static int nsv_read_chunk(AVFormatContext *s, int fill_header)
     if (vsize && st[NSV_ST_VIDEO]) {
         nst = st[NSV_ST_VIDEO]->priv_data;
         pkt = &nsv->ahead[NSV_ST_VIDEO];
-        av_get_packet(pb, pkt, vsize);
+        if ((ret = av_get_packet(pb, pkt, vsize)) < 0)
+            return ret;
         pkt->stream_index = st[NSV_ST_VIDEO]->index;//NSV_ST_VIDEO;
         pkt->dts = nst->frame_offset;
         pkt->flags |= nsv->state == NSV_HAS_READ_NSVS ? AV_PKT_FLAG_KEY : 0; /* keyframe only likely on a sync frame */
@@ -615,7 +617,8 @@ static int nsv_read_chunk(AVFormatContext *s, int fill_header)
                        bps, channels, samplerate);
             }
         }
-        av_get_packet(pb, pkt, asize);
+        if ((ret = av_get_packet(pb, pkt, asize)) < 0)
+            return ret;
         pkt->stream_index = st[NSV_ST_AUDIO]->index;//NSV_ST_AUDIO;
         pkt->flags |= nsv->state == NSV_HAS_READ_NSVS ? AV_PKT_FLAG_KEY : 0; /* keyframe only likely on a sync frame */
         if( nsv->state == NSV_HAS_READ_NSVS && st[NSV_ST_VIDEO] ) {
path: libavformat/nsvdec.c