From patchwork Thu Nov 29 18:18:17 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrey Semashev X-Patchwork-Id: 11233 Return-Path: X-Original-To: patchwork@ffaux-bg.ffmpeg.org Delivered-To: patchwork@ffaux-bg.ffmpeg.org Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by ffaux.localdomain (Postfix) with ESMTP id 9F36E44D195 for ; Thu, 29 Nov 2018 20:18:22 +0200 (EET) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 44A33689B90; Thu, 29 Nov 2018 20:18:23 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-lf1-f67.google.com (mail-lf1-f67.google.com [209.85.167.67]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 1066C6897BF for ; Thu, 29 Nov 2018 20:18:17 +0200 (EET) Received: by mail-lf1-f67.google.com with SMTP id a16so2183518lfg.3 for ; Thu, 29 Nov 2018 10:18:23 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=z3INW2pq9xp9XmQMSJdhpV0VA7bTvx1s3R/XvDcThBQ=; b=slhgctWcLdEP0Nk836BDGM2763VpdRwTM16AJSy/lO8jnIGJDu7c3LlFIH5KgYaELN IfyQ3oPByL2OXfi+hRnX2+ccivVGcX0Bzvv43xjjwb4yr2dGpwWgUrqOrxfgQdsazinV FIW6TBq95HkHqfReaRmOPZbdrdnWFbI+xM4M6QYWt0+ErYj9+yYRCIf6HATtR3n3d0ba 8kHZvzzer/loyk5wUA5pjD7mNnZl9kYQ9NdolkG8GQz1YBHrpiu1vW2EJ+/QO405rV64 9LEW0FFfO0+3Mlqdc/y3bUkHPtx4o4yb6mf1zO93Ra+ezef2Y5zICQ4HtJs2AWNE1VTs 9VjQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=z3INW2pq9xp9XmQMSJdhpV0VA7bTvx1s3R/XvDcThBQ=; b=AhTxBy93ZmPNDjr0b9DsEc2WwRTbVDFlMJt+cNp23pgupiSyljU3YPyp1fSMa7xVVO 0WrREsibzaPn5LwtWwU5877lXcea2PWSXK9p+u65+5EcdqiiikRgwLn0QoMMH83KS7J9 n7C+S0xxmAWy05cVLBjnOsX4Y1GfLco2e6GlJMv5PkaqXmlk2sbrlynrCbr4s9v/uXWp Q6A9n2cL3Vx0KnCTfImrHudC6lmZAAFR122C0aljfWvvOFB745a0zo3cC34AilMMqH8e JXL5kaWSk4YI7aJWn+bg2+JeWC0chpHDJ49IzSS1IRIg9B2W0XvFCoyGY/NNSp6v6MdW KIQw== X-Gm-Message-State: AA+aEWZTcHAfqOKxfSVA5u4fo2J3lpnfktEs0oBU9M4aa8Iynhe0sK+p UJJEJgU0cbCkBf3ArMjAqteaBtq2 X-Google-Smtp-Source: AFSGD/Xn2akzo0/QIWxK604lnDMikBmflvQGYpAZ4xQVMYPsupKHxrG5tA4RRsMJ7BIwVx7oO4lpFw== X-Received: by 2002:a19:cd50:: with SMTP id d77mr1675025lfg.125.1543515501875; Thu, 29 Nov 2018 10:18:21 -0800 (PST) Received: from localhost.localdomain (broadband-37-110-31-10.ip.moscow.rt.ru. [37.110.31.10]) by smtp.gmail.com with ESMTPSA id i75sm428010lfb.58.2018.11.29.10.18.20 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 29 Nov 2018 10:18:21 -0800 (PST) From: Andrey Semashev To: ffmpeg-devel@ffmpeg.org Date: Thu, 29 Nov 2018 21:18:17 +0300 Message-Id: <20181129181818.13295-1-andrey.semashev@gmail.com> X-Mailer: git-send-email 2.19.1 MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 1/2] lavf/file: Add proper support for authority in file URIs. X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Cc: Andrey Semashev Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" Previously, URIs with authority field were incorrectly interpreted as if the authority was part of the path. This commit adds more complete file URI parsing according to https://tools.ietf.org/html/rfc8089. In particular, the file backend now recognizes URIs with authority field and ensures that it is either empty or contains the special value "localhost". The file backend will return EINVAL if the user attempts to use it with a URI referring to a remote host. Also, enable file_delete() on Windows as it provides equivalents of unlink() and rmdir(). The compatibility glue is already provided by os_support.h. --- libavformat/file.c | 55 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 48 insertions(+), 7 deletions(-) diff --git a/libavformat/file.c b/libavformat/file.c index 1d321c4205..040197d50d 100644 --- a/libavformat/file.c +++ b/libavformat/file.c @@ -19,6 +19,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/log.h" +#include "libavutil/error.h" #include "libavutil/avstring.h" #include "libavutil/internal.h" #include "libavutil/opt.h" @@ -104,6 +106,31 @@ static const AVClass pipe_class = { .version = LIBAVUTIL_VERSION_INT, }; +static int file_get_path(const char* filename, const char** ppath) +{ + const char* path = filename; + // Check if the filename is a file URI. https://tools.ietf.org/html/rfc8089#section-2 + if (av_strncasecmp(path, "file:", sizeof("file:") - 1) == 0) { + path += sizeof("file:") - 1; + if (path[0] == '/' && path[1] == '/') { + // The URI may have an authority part. Check that the authority does not contain + // a remote host name. We cannot access filesystem on a different host. + path += 2; + if (path[0] != '/') { + if (strncmp(path, "localhost/", sizeof("localhost/") - 1) == 0) { + path += sizeof("localhost") - 1; + } else { + av_log(NULL, AV_LOG_ERROR, "File URIs referencing a remote host are not supported: %s\n", filename); + return AVERROR(EINVAL); + } + } + } + } + + *ppath = path; + return 0; +} + static int file_read(URLContext *h, unsigned char *buf, int size) { FileContext *c = h->priv_data; @@ -136,7 +163,9 @@ static int file_check(URLContext *h, int mask) { int ret = 0; const char *filename = h->filename; - av_strstart(filename, "file:", &filename); + ret = file_get_path(filename, &filename); + if (ret < 0) + return ret; { #if HAVE_ACCESS && defined(R_OK) @@ -167,10 +196,12 @@ static int file_check(URLContext *h, int mask) static int file_delete(URLContext *h) { -#if HAVE_UNISTD_H +#if HAVE_UNISTD_H || defined(_WIN32) int ret; const char *filename = h->filename; - av_strstart(filename, "file:", &filename); + ret = file_get_path(filename, &filename); + if (ret < 0) + return ret; ret = rmdir(filename); if (ret < 0 && errno == ENOTDIR) @@ -188,8 +219,12 @@ static int file_move(URLContext *h_src, URLContext *h_dst) { const char *filename_src = h_src->filename; const char *filename_dst = h_dst->filename; - av_strstart(filename_src, "file:", &filename_src); - av_strstart(filename_dst, "file:", &filename_dst); + int ret = file_get_path(filename_src, &filename_src); + if (ret < 0) + return ret; + ret = file_get_path(filename_dst, &filename_dst); + if (ret < 0) + return ret; if (rename(filename_src, filename_dst) < 0) return AVERROR(errno); @@ -206,7 +241,9 @@ static int file_open(URLContext *h, const char *filename, int flags) int fd; struct stat st; - av_strstart(filename, "file:", &filename); + int ret = file_get_path(filename, &filename); + if (ret < 0) + return ret; if (flags & AVIO_FLAG_WRITE && flags & AVIO_FLAG_READ) { access = O_CREAT | O_RDWR; @@ -264,8 +301,12 @@ static int file_open_dir(URLContext *h) { #if HAVE_LSTAT FileContext *c = h->priv_data; + const char* dirname = h->filename; + int ret = file_get_path(dirname, &dirname); + if (ret < 0) + return ret; - c->dir = opendir(h->filename); + c->dir = opendir(dirname); if (!c->dir) return AVERROR(errno);