summaryrefslogtreecommitdiff
path: root/multimedia
diff options
context:
space:
mode:
authorleot <leot@pkgsrc.org>2018-01-29 21:54:22 +0000
committerleot <leot@pkgsrc.org>2018-01-29 21:54:22 +0000
commitfbe3a8c08433fe9ecb10d82a6128be571ded616c (patch)
treec1066a1d30e2dd0e2771c3dee8b18dccea19f53a /multimedia
parenta7fd58faa1183791266cd44dc094c728dcae6ea1 (diff)
downloadpkgsrc-fbe3a8c08433fe9ecb10d82a6128be571ded616c.tar.gz
mpv: Add patch-player_lua_ytdl__hook.lua to address CVE-2018-6360
Sync player/lua/ytdl_hook.lua with upstream commit 2a0f9fc1588d8bda51a6340197c54285f3f62755 minus hunks that need `on_load_fail' hook introduced after mpv-0.27. Bump PKGREVISION.
Diffstat (limited to 'multimedia')
-rw-r--r--multimedia/mpv/Makefile4
-rw-r--r--multimedia/mpv/distinfo3
-rw-r--r--multimedia/mpv/patches/patch-player_lua_ytdl__hook.lua265
3 files changed, 269 insertions, 3 deletions
diff --git a/multimedia/mpv/Makefile b/multimedia/mpv/Makefile
index a3bc4b64f89..38baf052703 100644
--- a/multimedia/mpv/Makefile
+++ b/multimedia/mpv/Makefile
@@ -1,7 +1,7 @@
-# $NetBSD: Makefile,v 1.62 2018/01/28 20:10:57 wiz Exp $
+# $NetBSD: Makefile,v 1.63 2018/01/29 21:54:22 leot Exp $
DISTNAME= mpv-0.27.0
-PKGREVISION= 1
+PKGREVISION= 2
CATEGORIES= multimedia
MASTER_SITES= ${MASTER_SITE_GITHUB:=mpv-player/}
GITHUB_TAG= v${PKGVERSION_NOREV}
diff --git a/multimedia/mpv/distinfo b/multimedia/mpv/distinfo
index c13152b7f5b..bb9e3c70d5d 100644
--- a/multimedia/mpv/distinfo
+++ b/multimedia/mpv/distinfo
@@ -1,8 +1,9 @@
-$NetBSD: distinfo,v 1.37 2017/09/13 10:35:58 leot Exp $
+$NetBSD: distinfo,v 1.38 2018/01/29 21:54:22 leot Exp $
SHA1 (mpv-0.27.0.tar.gz) = d4bddb88cf7a112a295a130a091181acbe25605b
RMD160 (mpv-0.27.0.tar.gz) = d2edbdfdc6fdf3a0c210536ac3966e99113c83ad
SHA512 (mpv-0.27.0.tar.gz) = 22738f907d84d362095773972f685e3b03ab4c8172a22ddede290fc221a83ab9135b96f8b18191dabe842b2963f68983929cf065097287fc1a054a7d5f1d0ae4
Size (mpv-0.27.0.tar.gz) = 2956816 bytes
SHA1 (patch-audio_out_ao__oss.c) = d7f3a75ab43efe396ce536fb54e6207a7ded3510
+SHA1 (patch-player_lua_ytdl__hook.lua) = 450a6f2640c76b5db0c0cd585674ccd689712f78
SHA1 (patch-player_main.c) = 842432e448526a9d170e7efd2b01276e36072e16
diff --git a/multimedia/mpv/patches/patch-player_lua_ytdl__hook.lua b/multimedia/mpv/patches/patch-player_lua_ytdl__hook.lua
new file mode 100644
index 00000000000..c5aba3bd0a1
--- /dev/null
+++ b/multimedia/mpv/patches/patch-player_lua_ytdl__hook.lua
@@ -0,0 +1,265 @@
+$NetBSD: patch-player_lua_ytdl__hook.lua,v 1.1 2018/01/29 21:54:22 leot Exp $
+
+Sync ytdl_hook.lua script with commit 2a0f9fc1588d8bda51a6340197c54285f3f62755
+in order to fix CVE-2018-6360.
+
+Please note that this completely omits hunks that need `on_load_fail' hook that
+was implemented post-0.27.
+
+--- player/lua/ytdl_hook.lua.orig 2018-01-28 10:58:02.151884824 +0000
++++ player/lua/ytdl_hook.lua
+@@ -15,6 +16,18 @@ local ytdl = {
+
+ local chapter_list = {}
+
++function Set (t)
++ local set = {}
++ for _, v in pairs(t) do set[v] = true end
++ return set
++end
++
++local safe_protos = Set {
++ "http", "https", "ftp", "ftps",
++ "rtmp", "rtmps", "rtmpe", "rtmpt", "rtmpts", "rtmpte",
++ "data"
++}
++
+ local function exec(args)
+ local ret = utils.subprocess({args = args})
+ return ret.status, ret.stdout, ret
+@@ -71,6 +84,15 @@ local function edl_escape(url)
+ return "%" .. string.len(url) .. "%" .. url
+ end
+
++local function url_is_safe(url)
++ local proto = type(url) == "string" and url:match("^(.+)://") or nil
++ local safe = proto and safe_protos[proto]
++ if not safe then
++ msg.error(("Ignoring potentially unsafe url: '%s'"):format(url))
++ end
++ return safe
++end
++
+ local function time_to_secs(time_string)
+ local ret
+
+@@ -182,6 +204,9 @@ local function edl_track_joined(fragment
+
+ for i = offset, #fragments do
+ local fragment = fragments[i]
++ if not url_is_safe(join_url(base, fragment)) then
++ return nil
++ end
+ table.insert(parts, edl_escape(join_url(base, fragment)))
+ if fragment.duration then
+ parts[#parts] =
+@@ -191,16 +216,63 @@ local function edl_track_joined(fragment
+ return edl .. table.concat(parts, ";") .. ";"
+ end
+
++local function has_native_dash_demuxer()
++ local demuxers = mp.get_property_native("demuxer-lavf-list")
++ for _,v in ipairs(demuxers) do
++ if v == "dash" then
++ return true
++ end
++ end
++ return false
++end
++
++local function valid_manifest(json)
++ local reqfmt = json["requested_formats"] and json["requested_formats"][1] or {}
++ if not reqfmt["manifest_url"] and not json["manifest_url"] then
++ return false
++ end
++ local proto = reqfmt["protocol"] or json["protocol"] or ""
++ return (has_native_dash_demuxer() and proto == "http_dash_segments") or
++ proto:find("^m3u8")
++end
++
+ local function add_single_video(json)
+ local streamurl = ""
++ local max_bitrate = 0
++ local reqfmts = json["requested_formats"]
++
++ -- prefer manifest_url if present
++ if valid_manifest(json) then
++ local mpd_url = reqfmts and reqfmts[1]["manifest_url"] or
++ json["manifest_url"]
++ if not mpd_url then
++ msg.error("No manifest URL found in JSON data.")
++ return
++ elseif not url_is_safe(mpd_url) then
++ return
++ end
++
++ streamurl = mpd_url
++
++ if reqfmts then
++ for _, track in pairs(reqfmts) do
++ max_bitrate = track.tbr > max_bitrate and
++ track.tbr or max_bitrate
++ end
++ elseif json.tbr then
++ max_bitrate = json.tbr > max_bitrate and json.tbr or max_bitrate
++ end
+
+ -- DASH/split tracks
+- if not (json["requested_formats"] == nil) then
+- for _, track in pairs(json.requested_formats) do
++ elseif reqfmts then
++ for _, track in pairs(reqfmts) do
+ local edl_track = nil
+ edl_track = edl_track_joined(track.fragments,
+ track.protocol, json.is_live,
+ track.fragment_base_url)
++ if not edl_track and not url_is_safe(track.url) then
++ return
++ end
+ if track.acodec and track.acodec ~= "none" then
+ -- audio track
+ mp.commandv("audio-add",
+@@ -217,6 +289,9 @@ local function add_single_video(json)
+ edl_track = edl_track_joined(json.fragments, json.protocol,
+ json.is_live, json.fragment_base_url)
+
++ if not edl_track and not url_is_safe(json.url) then
++ return
++ end
+ -- normal video or single track
+ streamurl = edl_track or json.url
+ set_http_headers(json.http_headers)
+@@ -231,6 +306,13 @@ local function add_single_video(json)
+
+ mp.set_property("file-local-options/force-media-title", json.title)
+
++ -- set hls-bitrate for dash track selection
++ if max_bitrate > 0 and
++ not option_was_set("hls-bitrate") and
++ not option_was_set_locally("hls-bitrate") then
++ mp.set_property_native('file-local-options/hls-bitrate', max_bitrate*1000)
++ end
++
+ -- add subtitles
+ if not (json.requested_subtitles == nil) then
+ for lang, sub_info in pairs(json.requested_subtitles) do
+@@ -309,7 +391,8 @@ mp.add_hook("on_load", 10, function ()
+
+ -- check for youtube-dl in mpv's config dir
+ if not (ytdl.searched) then
+- local ytdl_mcd = mp.find_config_file("youtube-dl")
++ local exesuf = (package.config:sub(1,1) == '\\') and '.exe' or ''
++ local ytdl_mcd = mp.find_config_file("youtube-dl" .. exesuf)
+ if not (ytdl_mcd == nil) then
+ msg.verbose("found youtube-dl at: " .. ytdl_mcd)
+ ytdl.path = ytdl_mcd
+@@ -365,9 +448,15 @@ mp.add_hook("on_load", 10, function ()
+ local es, json, result = exec(command)
+
+ if (es < 0) or (json == nil) or (json == "") then
+- if not result.killed_by_us then
+- msg.warn("youtube-dl failed, trying to play URL directly ...")
++ local err = "youtube-dl failed: "
++ if result.error and result.error == "init" then
++ err = err .. "not found or not enough permissions"
++ elseif not result.killed_by_us then
++ err = err .. "unexpected error ocurred"
++ else
++ err = string.format("%s returned '%d'", err, es)
+ end
++ msg.error(err)
+ return
+ end
+
+@@ -396,18 +485,26 @@ mp.add_hook("on_load", 10, function ()
+ return
+ end
+
++ local self_redirecting_url =
++ json.entries[1]["_type"] ~= "url_transparent" and
++ json.entries[1]["webpage_url"] and
++ json.entries[1]["webpage_url"] == json["webpage_url"]
++
+
+ -- some funky guessing to detect multi-arc videos
+- if (not (json.entries[1]["_type"] == "url_transparent")) and
+- (not (json.entries[1]["webpage_url"] == nil)
+- and (json.entries[1]["webpage_url"] == json["webpage_url"]))
+- and not (json.entries[1].url == nil) then
++ if self_redirecting_url and #json.entries > 1
++ and json.entries[1].protocol == "m3u8_native"
++ and json.entries[1].url then
+ msg.verbose("multi-arc video detected, building EDL")
+
+ local playlist = edl_track_joined(json.entries)
+
+ msg.debug("EDL: " .. playlist)
+
++ if not playlist then
++ return
++ end
++
+ -- can't change the http headers for each entry, so use the 1st
+ if json.entries[1] then
+ set_http_headers(json.entries[1].http_headers)
+@@ -446,39 +543,43 @@ mp.add_hook("on_load", 10, function ()
+ end
+ end
+
+- elseif (not (json.entries[1]["_type"] == "url_transparent")) and
+- (not (json.entries[1]["webpage_url"] == nil)
+- and (json.entries[1]["webpage_url"] == json["webpage_url"]))
+- and (#json.entries == 1) then
+-
++ elseif self_redirecting_url and #json.entries == 1 then
+ msg.verbose("Playlist with single entry detected.")
+ add_single_video(json.entries[1])
+ else
+-
+- local playlist = "#EXTM3U\n"
++ local playlist = {"#EXTM3U"}
+ for i, entry in pairs(json.entries) do
+ local site = entry.url
+ local title = entry.title
+
+ if not (title == nil) then
+ title = string.gsub(title, '%s+', ' ')
+- playlist = playlist .. "#EXTINF:0," .. title .. "\n"
++ table.insert(playlist, "#EXTINF:0," .. title)
+ end
+
+- -- some extractors will still return the full info for
+- -- all clips in the playlist and the URL will point
+- -- directly to the file in that case, which we don't
+- -- want so get the webpage URL instead, which is what
+- -- we want
+- if not (json.entries[1]["_type"] == "url_transparent")
+- and not (entry["webpage_url"] == nil) then
++ --[[ some extractors will still return the full info for
++ all clips in the playlist and the URL will point
++ directly to the file in that case, which we don't
++ want so get the webpage URL instead, which is what
++ we want, but only if we aren't going to trigger an
++ infinite loop
++ --]]
++ if entry["webpage_url"] and not self_redirecting_url then
+ site = entry["webpage_url"]
+ end
+
+- playlist = playlist .. "ytdl://" .. site .. "\n"
++ -- links with only youtube id as returned by --flat-playlist
++ if not site:find("://") then
++ table.insert(playlist, "ytdl://" .. site)
++ elseif url_is_safe(site) then
++ table.insert(playlist, site)
++ end
++
+ end
+
+- mp.set_property("stream-open-filename", "memory://" .. playlist)
++ if #playlist > 0 then
++ mp.set_property("stream-open-filename", "memory://" .. table.concat(playlist, "\n"))
++ end
+ end
+
+ else -- probably a video