Commit 673cd7b5 authored by Luc Saillard's avatar Luc Saillard Committed by Jean-Baptiste Kempf

Always append a null character when reading HLS playlist

The httplive module doesn't always append a null character after reading the
playlist. Many str* function is used on the playlist buffer (strstr, printf,
...). We must ensure that the buffer is null terminated, else we will read
random data.

We also have two functions readM3u8() and read_M3u8() that does the same
job. Rewrite it into read_M3U8_from_url() and read_M3U8_from_stream().
Signed-off-by: default avatarJean-Baptiste Kempf <jb@videolan.org>
parent 3defabc0
...@@ -40,6 +40,7 @@ ...@@ -40,6 +40,7 @@
#include <vlc_arrays.h> #include <vlc_arrays.h>
#include <vlc_stream.h> #include <vlc_stream.h>
#include <vlc_url.h> #include <vlc_url.h>
#include <vlc_memory.h>
/***************************************************************************** /*****************************************************************************
* Module descriptor * Module descriptor
...@@ -135,8 +136,8 @@ static int Read (stream_t *, void *p_read, unsigned int i_read); ...@@ -135,8 +136,8 @@ static int Read (stream_t *, void *p_read, unsigned int i_read);
static int Peek (stream_t *, const uint8_t **pp_peek, unsigned int i_peek); static int Peek (stream_t *, const uint8_t **pp_peek, unsigned int i_peek);
static int Control(stream_t *, int i_query, va_list); static int Control(stream_t *, int i_query, va_list);
static ssize_t read_M3U8(stream_t *s, vlc_url_t *url, uint8_t **buffer); static ssize_t read_M3U8_from_stream(stream_t *s, uint8_t **buffer);
static ssize_t ReadM3U8(stream_t *s, uint8_t **buffer); static ssize_t read_M3U8_from_url(stream_t *s, vlc_url_t *url, uint8_t **buffer);
static char *ReadLine(uint8_t *buffer, uint8_t **pos, size_t len); static char *ReadLine(uint8_t *buffer, uint8_t **pos, size_t len);
static int hls_Download(stream_t *s, segment_t *segment); static int hls_Download(stream_t *s, segment_t *segment);
...@@ -848,7 +849,7 @@ static int parse_M3U8(stream_t *s, vlc_array_t *streams, uint8_t *buffer, const ...@@ -848,7 +849,7 @@ static int parse_M3U8(stream_t *s, vlc_array_t *streams, uint8_t *buffer, const
/* Download playlist file from server */ /* Download playlist file from server */
uint8_t *buf = NULL; uint8_t *buf = NULL;
ssize_t len = read_M3U8(s, &hls->url, &buf); ssize_t len = read_M3U8_from_url(s, &hls->url, &buf);
if (len < 0) if (len < 0)
err = VLC_EGENERIC; err = VLC_EGENERIC;
else else
...@@ -965,7 +966,7 @@ static int get_HTTPLiveMetaPlaylist(stream_t *s, vlc_array_t **streams) ...@@ -965,7 +966,7 @@ static int get_HTTPLiveMetaPlaylist(stream_t *s, vlc_array_t **streams)
/* Download new playlist file from server */ /* Download new playlist file from server */
uint8_t *buffer = NULL; uint8_t *buffer = NULL;
ssize_t len = read_M3U8(s, &p_sys->m3u8, &buffer); ssize_t len = read_M3U8_from_url(s, &p_sys->m3u8, &buffer);
if (len < 0) if (len < 0)
return VLC_EGENERIC; return VLC_EGENERIC;
...@@ -1411,79 +1412,64 @@ static int hls_Download(stream_t *s, segment_t *segment) ...@@ -1411,79 +1412,64 @@ static int hls_Download(stream_t *s, segment_t *segment)
} }
/* Read M3U8 file */ /* Read M3U8 file */
static ssize_t read_M3U8(stream_t *s, vlc_url_t *url, uint8_t **buffer) static ssize_t read_M3U8_from_stream(stream_t *s, uint8_t **buffer)
{ {
assert(*buffer == NULL); int64_t total_bytes = 0;
int64_t total_allocated = 0;
/* Construct URL */ uint8_t *p = NULL;
char *psz_url = ConstructUrl(url);
if (psz_url == NULL)
return VLC_ENOMEM;
stream_t *p_m3u8 = stream_UrlNew(s, psz_url); while (1)
free(psz_url); {
if (p_m3u8 == NULL) char buf[4096];
return VLC_EGENERIC; int64_t bytes;
int64_t size = stream_Size(p_m3u8); bytes = stream_Read(s, buf, sizeof(buf));
if (size == 0) size = 8192; /* no Content-Length */ if (bytes == 0)
break; /* EOF ? */
else if (bytes < 0)
return bytes;
*buffer = calloc(1, size); if ( (total_bytes + bytes + 1) > total_allocated )
if (*buffer == NULL)
{ {
stream_Delete(p_m3u8); if (total_allocated)
total_allocated *= 2;
else
total_allocated = __MIN(bytes+1, sizeof(buf));
p = realloc_or_free(p, total_allocated);
if (p == NULL)
return VLC_ENOMEM; return VLC_ENOMEM;
} }
int64_t len = 0, curlen = 0; memcpy(p+total_bytes, buf, bytes);
do { total_bytes += bytes;
int read = ((size - curlen) >= INT_MAX) ? INT_MAX : (size - curlen);
len = stream_Read(p_m3u8, *buffer + curlen, read);
if (len <= 0)
break;
curlen += len;
if (curlen >= size)
{
uint8_t *tmp = realloc(*buffer, size + 8192);
if (tmp == NULL)
break;
size += 8192;
*buffer = tmp;
} }
} while (vlc_object_alive(s));
stream_Delete(p_m3u8);
(*buffer)[curlen-1] = '\0'; if (total_allocated == 0)
return size; return VLC_EGENERIC;
p[total_bytes] = '\0';
*buffer = p;
return total_bytes;
} }
static ssize_t ReadM3U8(stream_t *s, uint8_t **buffer) static ssize_t read_M3U8_from_url(stream_t *s, vlc_url_t *url, uint8_t **buffer)
{ {
assert(*buffer == NULL); assert(*buffer == NULL);
int64_t size = stream_Size(s->p_source); /* Construct URL */
if (size == 0) size = 1024; /* no Content-Length */ char *psz_url = ConstructUrl(url);
if (psz_url == NULL)
*buffer = calloc(1, size);
if (*buffer == NULL)
return VLC_ENOMEM; return VLC_ENOMEM;
int64_t len = 0, curlen = 0; stream_t *p_m3u8 = stream_UrlNew(s, psz_url);
do { free(psz_url);
int read = ((size - curlen) >= INT_MAX) ? INT_MAX : (size - curlen); if (p_m3u8 == NULL)
len = stream_Read(s->p_source, *buffer + curlen, read); return VLC_EGENERIC;
if (len <= 0)
break; ssize_t size = read_M3U8_from_stream(p_m3u8, buffer);
curlen += len; stream_Delete(p_m3u8);
if (curlen >= size)
{
uint8_t *tmp = realloc(*buffer, size + 1024);
if (tmp == NULL)
break;
size += 1024;
*buffer = tmp;
}
} while (vlc_object_alive(s));
return size; return size;
} }
...@@ -1566,7 +1552,7 @@ static int Open(vlc_object_t *p_this) ...@@ -1566,7 +1552,7 @@ static int Open(vlc_object_t *p_this)
/* Parse HLS m3u8 content. */ /* Parse HLS m3u8 content. */
uint8_t *buffer = NULL; uint8_t *buffer = NULL;
ssize_t len = ReadM3U8(s, &buffer); ssize_t len = read_M3U8_from_stream(s->p_source, &buffer);
if (len < 0) if (len < 0)
goto fail; goto fail;
if (parse_M3U8(s, p_sys->hls_stream, buffer, len) != VLC_SUCCESS) if (parse_M3U8(s, p_sys->hls_stream, buffer, len) != VLC_SUCCESS)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment