diff mbox series

[FFmpeg-devel,v17,4/5] libavformat: Remove MAX_PATH limit and use UTF-8 version of getenv()

Message ID 20220617093141.9826-4-nil-admirari@mailo.com
State New
Headers show
Series [FFmpeg-devel,v17,1/5] libavutil: Add wchartoutf8(), wchartoansi(), utf8toansi() and getenv_utf8() | expand

Checks

Context Check Description
andriy/make_x86 success Make finished
andriy/make_fate_x86 success Make fate finished

Commit Message

Nil Admirari June 17, 2022, 9:31 a.m. UTC
1. getenv() is replaced with getenv_utf8() across libavformat.
2. New versions of AviSynth+ are now called with UTF-8 filenames.
3. Old versions of AviSynth are still using ANSI strings,
   but MAX_PATH limit on filename is removed.
---
 libavformat/avisynth.c    | 39 +++++++++++++++++++++++++++------------
 libavformat/http.c        | 20 +++++++++++++-------
 libavformat/ipfsgateway.c | 35 +++++++++++++++++++++++------------
 libavformat/tls.c         | 11 +++++++++--
 4 files changed, 72 insertions(+), 33 deletions(-)

Comments

Martin Storsjö June 18, 2022, 10:24 p.m. UTC | #1
On Fri, 17 Jun 2022, Nil Admirari wrote:

> 1. getenv() is replaced with getenv_utf8() across libavformat.
> 2. New versions of AviSynth+ are now called with UTF-8 filenames.
> 3. Old versions of AviSynth are still using ANSI strings,
>   but MAX_PATH limit on filename is removed.
> ---
> libavformat/avisynth.c    | 39 +++++++++++++++++++++++++++------------
> libavformat/http.c        | 20 +++++++++++++-------
> libavformat/ipfsgateway.c | 35 +++++++++++++++++++++++------------
> libavformat/tls.c         | 11 +++++++++--
> 4 files changed, 72 insertions(+), 33 deletions(-)
>
> diff --git a/libavformat/http.c b/libavformat/http.c
> index c8f3f4b6a3..d90117e422 100644
> --- a/libavformat/http.c
> +++ b/libavformat/http.c
> @@ -29,6 +29,7 @@
> #include "libavutil/avassert.h"
> #include "libavutil/avstring.h"
> #include "libavutil/bprint.h"
> +#include "libavutil/getenv_utf8.h"
> #include "libavutil/opt.h"
> #include "libavutil/time.h"
> #include "libavutil/parseutils.h"

This actually causes some surprise breakage in MSVC builds. Here, 
getenv_utf8.h includes windows.h. If including windows.h and winsock2 
headers in the same file, the winsock2 headers must be included before.

I fixed it locally by moving this new include down, with a comment like 
this:

/* This header can include <windows.h>. That header has to be included after
  * winsock2 headers (included by network.h and os_support.h above). */
#include "libavutil/getenv_utf8.h"

(I had to do the same fixup in http.c and ipfsgateway.c.)

If that seems fine to you and others, I can push this patchset maybe 
tomorrow.

// Martin
Martin Storsjö June 18, 2022, 10:36 p.m. UTC | #2
On Sun, 19 Jun 2022, Martin Storsjö wrote:

> On Fri, 17 Jun 2022, Nil Admirari wrote:
>
>> 1. getenv() is replaced with getenv_utf8() across libavformat.
>> 2. New versions of AviSynth+ are now called with UTF-8 filenames.
>> 3. Old versions of AviSynth are still using ANSI strings,
>>   but MAX_PATH limit on filename is removed.
>> ---
>> libavformat/avisynth.c    | 39 +++++++++++++++++++++++++++------------
>> libavformat/http.c        | 20 +++++++++++++-------
>> libavformat/ipfsgateway.c | 35 +++++++++++++++++++++++------------
>> libavformat/tls.c         | 11 +++++++++--
>> 4 files changed, 72 insertions(+), 33 deletions(-)
>> 
>> diff --git a/libavformat/http.c b/libavformat/http.c
>> index c8f3f4b6a3..d90117e422 100644
>> --- a/libavformat/http.c
>> +++ b/libavformat/http.c
>> @@ -29,6 +29,7 @@
>> #include "libavutil/avassert.h"
>> #include "libavutil/avstring.h"
>> #include "libavutil/bprint.h"
>> +#include "libavutil/getenv_utf8.h"
>> #include "libavutil/opt.h"
>> #include "libavutil/time.h"
>> #include "libavutil/parseutils.h"
>
> This actually causes some surprise breakage in MSVC builds. Here, 
> getenv_utf8.h includes windows.h. If including windows.h and winsock2 headers 
> in the same file, the winsock2 headers must be included before.
>
> I fixed it locally by moving this new include down, with a comment like this:
>
> /* This header can include <windows.h>. That header has to be included after
> * winsock2 headers (included by network.h and os_support.h above). */
> #include "libavutil/getenv_utf8.h"
>
> (I had to do the same fixup in http.c and ipfsgateway.c.)

Alternatively, as these env variables mostly are used for host names to a 
proxy or similar, there's probably not much need for handling anything 
outside of ASCII anyway, so we could also consider just leaving these as 
plain getenv().

// Martin
Martin Storsjö June 18, 2022, 10:40 p.m. UTC | #3
On Fri, 17 Jun 2022, Nil Admirari wrote:

> 1. getenv() is replaced with getenv_utf8() across libavformat.
> 2. New versions of AviSynth+ are now called with UTF-8 filenames.
> 3. Old versions of AviSynth are still using ANSI strings,
>   but MAX_PATH limit on filename is removed.
> ---
> libavformat/avisynth.c    | 39 +++++++++++++++++++++++++++------------
> libavformat/http.c        | 20 +++++++++++++-------
> libavformat/ipfsgateway.c | 35 +++++++++++++++++++++++------------
> libavformat/tls.c         | 11 +++++++++--
> 4 files changed, 72 insertions(+), 33 deletions(-)
>
> @@ -198,6 +199,7 @@ void ff_http_init_auth_state(URLContext *dest, const URLContext *src)
> static int http_open_cnx_internal(URLContext *h, AVDictionary **options)
> {
>     const char *path, *proxy_path, *lower_proto = "tcp", *local_path;
> +    char *env_http_proxy, *env_no_proxy;
>     char *hashmark;
>     char hostname[1024], hoststr[1024], proto[10];
>     char auth[1024], proxyauth[1024] = "";
> @@ -211,9 +213,13 @@ static int http_open_cnx_internal(URLContext *h, AVDictionary **options)
>                  path1, sizeof(path1), s->location);
>     ff_url_join(hoststr, sizeof(hoststr), NULL, NULL, hostname, port, NULL);
>
> -    proxy_path = s->http_proxy ? s->http_proxy : getenv("http_proxy");
> -    use_proxy  = !ff_http_match_no_proxy(getenv("no_proxy"), hostname) &&
> +    env_http_proxy = getenv_utf8("http_proxy");
> +    proxy_path = s->http_proxy ? s->http_proxy : env_http_proxy;
> +
> +    env_no_proxy = getenv_utf8("no_proxy");
> +    use_proxy  = !ff_http_match_no_proxy(env_no_proxy, hostname) &&
>                  proxy_path && av_strstart(proxy_path, "http://", NULL);
> +    av_freep(&env_no_proxy);
>
>     if (!strcmp(proto, "https")) {
>         lower_proto = "tls";
> @@ -224,7 +230,7 @@ static int http_open_cnx_internal(URLContext *h, AVDictionary **options)
>         if (s->http_proxy) {
>             err = av_dict_set(options, "http_proxy", s->http_proxy, 0);
>             if (err < 0)
> -                return err;
> +                goto end;
>         }
>     }
>     if (port < 0)
> @@ -259,12 +265,12 @@ static int http_open_cnx_internal(URLContext *h, AVDictionary **options)
>         err = ffurl_open_whitelist(&s->hd, buf, AVIO_FLAG_READ_WRITE,
>                                    &h->interrupt_callback, options,
>                                    h->protocol_whitelist, h->protocol_blacklist, h);
> -        if (err < 0)
> -            return err;
>     }
>
> -    return http_connect(h, path, local_path, hoststr,
> -                        auth, proxyauth);
> +end:
> +    av_freep(&env_http_proxy);
> +    return err < 0 ? err : http_connect(
> +        h, path, local_path, hoststr, auth, proxyauth);
> }

FWIW - I wasn't entirely sure we can conclude that we always pass through 
a case that initializes the err variable here, so just to be sure, I 
locally amended this patch to initialize the err variable to 0 too.

// Martin
Soft Works June 18, 2022, 10:48 p.m. UTC | #4
> -----Original Message-----
> From: ffmpeg-devel <ffmpeg-devel-bounces@ffmpeg.org> On Behalf Of
> Martin Storsjö
> Sent: Sunday, June 19, 2022 12:24 AM
> To: FFmpeg development discussions and patches <ffmpeg-
> devel@ffmpeg.org>
> Subject: Re: [FFmpeg-devel] [PATCH v17 4/5] libavformat: Remove
> MAX_PATH limit and use UTF-8 version of getenv()
> 
> On Fri, 17 Jun 2022, Nil Admirari wrote:
> 
> > 1. getenv() is replaced with getenv_utf8() across libavformat.
> > 2. New versions of AviSynth+ are now called with UTF-8 filenames.
> > 3. Old versions of AviSynth are still using ANSI strings,
> >   but MAX_PATH limit on filename is removed.
> > ---
> > libavformat/avisynth.c    | 39 +++++++++++++++++++++++++++---------
> ---
> > libavformat/http.c        | 20 +++++++++++++-------
> > libavformat/ipfsgateway.c | 35 +++++++++++++++++++++++------------
> > libavformat/tls.c         | 11 +++++++++--
> > 4 files changed, 72 insertions(+), 33 deletions(-)
> >
> > diff --git a/libavformat/http.c b/libavformat/http.c
> > index c8f3f4b6a3..d90117e422 100644
> > --- a/libavformat/http.c
> > +++ b/libavformat/http.c
> > @@ -29,6 +29,7 @@
> > #include "libavutil/avassert.h"
> > #include "libavutil/avstring.h"
> > #include "libavutil/bprint.h"
> > +#include "libavutil/getenv_utf8.h"
> > #include "libavutil/opt.h"
> > #include "libavutil/time.h"
> > #include "libavutil/parseutils.h"
> 
> This actually causes some surprise breakage in MSVC builds. Here,
> getenv_utf8.h includes windows.h. If including windows.h and winsock2
> headers in the same file, the winsock2 headers must be included
> before.
> 
> I fixed it locally by moving this new include down, with a comment
> like
> this:
> 
> /* This header can include <windows.h>. That header has to be
> included after
>   * winsock2 headers (included by network.h and os_support.h above).
> */

This is the recommended way:


#define WIN32_LEAN_AND_MEAN

#include <windows.h>
#include <winsock2.h>


<Quote>
The Winsock2.h header file internally includes core elements from the Windows.h header file, so there is not usually an #include line for the Windows.h header file in Winsock applications. If an #include line is needed for the Windows.h header file, this should be preceded with the #define WIN32_LEAN_AND_MEAN macro. For historical reasons, the Windows.h header defaults to including the Winsock.h header file for Windows Sockets 1.1. The declarations in the Winsock.h header file will conflict with the declarations in the Winsock2.h header file required by Windows Sockets 2. The WIN32_LEAN_AND_MEAN macro prevents the Winsock.h from being included by the Windows.h header.
</Quote>

References:

https://docs.microsoft.com/en-us/windows/win32/winsock/include-files-2
https://docs.microsoft.com/en-us/windows/win32/winsock/creating-a-basic-winsock-application

Best regards,
softworkz
Martin Storsjö June 19, 2022, 7:49 a.m. UTC | #5
On Sat, 18 Jun 2022, Soft Works wrote:

>
>
>> -----Original Message-----
>> From: ffmpeg-devel <ffmpeg-devel-bounces@ffmpeg.org> On Behalf Of
>> Martin Storsjö
>> Sent: Sunday, June 19, 2022 12:24 AM
>> To: FFmpeg development discussions and patches <ffmpeg-
>> devel@ffmpeg.org>
>> Subject: Re: [FFmpeg-devel] [PATCH v17 4/5] libavformat: Remove
>> MAX_PATH limit and use UTF-8 version of getenv()
>>
>> On Fri, 17 Jun 2022, Nil Admirari wrote:
>>
>>> 1. getenv() is replaced with getenv_utf8() across libavformat.
>>> 2. New versions of AviSynth+ are now called with UTF-8 filenames.
>>> 3. Old versions of AviSynth are still using ANSI strings,
>>>   but MAX_PATH limit on filename is removed.
>>> ---
>>> libavformat/avisynth.c    | 39 +++++++++++++++++++++++++++---------
>> ---
>>> libavformat/http.c        | 20 +++++++++++++-------
>>> libavformat/ipfsgateway.c | 35 +++++++++++++++++++++++------------
>>> libavformat/tls.c         | 11 +++++++++--
>>> 4 files changed, 72 insertions(+), 33 deletions(-)
>>>
>>> diff --git a/libavformat/http.c b/libavformat/http.c
>>> index c8f3f4b6a3..d90117e422 100644
>>> --- a/libavformat/http.c
>>> +++ b/libavformat/http.c
>>> @@ -29,6 +29,7 @@
>>> #include "libavutil/avassert.h"
>>> #include "libavutil/avstring.h"
>>> #include "libavutil/bprint.h"
>>> +#include "libavutil/getenv_utf8.h"
>>> #include "libavutil/opt.h"
>>> #include "libavutil/time.h"
>>> #include "libavutil/parseutils.h"
>>
>> This actually causes some surprise breakage in MSVC builds. Here,
>> getenv_utf8.h includes windows.h. If including windows.h and winsock2
>> headers in the same file, the winsock2 headers must be included
>> before.
>>
>> I fixed it locally by moving this new include down, with a comment
>> like
>> this:
>>
>> /* This header can include <windows.h>. That header has to be
>> included after
>>   * winsock2 headers (included by network.h and os_support.h above).
>> */
>
> This is the recommended way:
>
>
> #define WIN32_LEAN_AND_MEAN
>
> #include <windows.h>
> #include <winsock2.h>

Thanks, adding #define WIN32_LEAN_AND_MEAN in wchar_filename.h fixes the 
issue.

// Martin
Soft Works June 19, 2022, 8 a.m. UTC | #6
> -----Original Message-----
> From: ffmpeg-devel <ffmpeg-devel-bounces@ffmpeg.org> On Behalf Of
> Martin Storsjö
> Sent: Sunday, June 19, 2022 9:49 AM
> To: FFmpeg development discussions and patches <ffmpeg-
> devel@ffmpeg.org>
> Subject: Re: [FFmpeg-devel] [PATCH v17 4/5] libavformat: Remove
> MAX_PATH limit and use UTF-8 version of getenv()
> 
> On Sat, 18 Jun 2022, Soft Works wrote:
> 
> >
> >
> >> -----Original Message-----
> >> From: ffmpeg-devel <ffmpeg-devel-bounces@ffmpeg.org> On Behalf Of
> >> Martin Storsjö
> >> Sent: Sunday, June 19, 2022 12:24 AM
> >> To: FFmpeg development discussions and patches <ffmpeg-
> >> devel@ffmpeg.org>
> >> Subject: Re: [FFmpeg-devel] [PATCH v17 4/5] libavformat: Remove
> >> MAX_PATH limit and use UTF-8 version of getenv()
> >>
> >> On Fri, 17 Jun 2022, Nil Admirari wrote:
> >>
> >>> 1. getenv() is replaced with getenv_utf8() across libavformat.
> >>> 2. New versions of AviSynth+ are now called with UTF-8 filenames.
> >>> 3. Old versions of AviSynth are still using ANSI strings,
> >>>   but MAX_PATH limit on filename is removed.
> >>> ---
> >>> libavformat/avisynth.c    | 39 +++++++++++++++++++++++++++-------
> --
> >> ---
> >>> libavformat/http.c        | 20 +++++++++++++-------
> >>> libavformat/ipfsgateway.c | 35 +++++++++++++++++++++++-----------
> -
> >>> libavformat/tls.c         | 11 +++++++++--
> >>> 4 files changed, 72 insertions(+), 33 deletions(-)
> >>>
> >>> diff --git a/libavformat/http.c b/libavformat/http.c
> >>> index c8f3f4b6a3..d90117e422 100644
> >>> --- a/libavformat/http.c
> >>> +++ b/libavformat/http.c
> >>> @@ -29,6 +29,7 @@
> >>> #include "libavutil/avassert.h"
> >>> #include "libavutil/avstring.h"
> >>> #include "libavutil/bprint.h"
> >>> +#include "libavutil/getenv_utf8.h"
> >>> #include "libavutil/opt.h"
> >>> #include "libavutil/time.h"
> >>> #include "libavutil/parseutils.h"
> >>
> >> This actually causes some surprise breakage in MSVC builds. Here,
> >> getenv_utf8.h includes windows.h. If including windows.h and
> winsock2
> >> headers in the same file, the winsock2 headers must be included
> >> before.
> >>
> >> I fixed it locally by moving this new include down, with a comment
> >> like
> >> this:
> >>
> >> /* This header can include <windows.h>. That header has to be
> >> included after
> >>   * winsock2 headers (included by network.h and os_support.h
> above).
> >> */
> >
> > This is the recommended way:
> >
> >
> > #define WIN32_LEAN_AND_MEAN
> >
> > #include <windows.h>
> > #include <winsock2.h>
> 
> Thanks, adding #define WIN32_LEAN_AND_MEAN in wchar_filename.h fixes
> the
> issue.

Besides that, it also sounds good  :-)
sw
Nil Admirari June 19, 2022, 11:44 a.m. UTC | #7
> Thanks, adding #define WIN32_LEAN_AND_MEAN in wchar_filename.h fixes the 
> issue.

Added WIN32_LEAN_AND_MEAN:
https://ffmpeg.org/pipermail/ffmpeg-devel/2022-June/297804.html
Nil Admirari June 19, 2022, 11:47 a.m. UTC | #8
> FWIW - I wasn't entirely sure we can conclude that we always pass through 
> a case that initializes the err variable here, so just to be sure, I 
> locally amended this patch to initialize the err variable to 0 too.

Fixed: https://ffmpeg.org/pipermail/ffmpeg-devel/2022-June/297806.html
diff mbox series

Patch

diff --git a/libavformat/avisynth.c b/libavformat/avisynth.c
index 8ba2bdead2..a97d12b6b6 100644
--- a/libavformat/avisynth.c
+++ b/libavformat/avisynth.c
@@ -34,6 +34,7 @@ 
 /* Platform-specific directives. */
 #ifdef _WIN32
   #include "compat/w32dlfcn.h"
+  #include "libavutil/wchar_filename.h"
   #undef EXTERN_C
   #define AVISYNTH_LIB "avisynth"
 #else
@@ -56,6 +57,7 @@  typedef struct AviSynthLibrary {
 #define AVSC_DECLARE_FUNC(name) name ## _func name
     AVSC_DECLARE_FUNC(avs_bit_blt);
     AVSC_DECLARE_FUNC(avs_clip_get_error);
+    AVSC_DECLARE_FUNC(avs_check_version);
     AVSC_DECLARE_FUNC(avs_create_script_environment);
     AVSC_DECLARE_FUNC(avs_delete_script_environment);
     AVSC_DECLARE_FUNC(avs_get_audio);
@@ -137,6 +139,7 @@  static av_cold int avisynth_load_library(void)
 
     LOAD_AVS_FUNC(avs_bit_blt, 0);
     LOAD_AVS_FUNC(avs_clip_get_error, 0);
+    LOAD_AVS_FUNC(avs_check_version, 0);
     LOAD_AVS_FUNC(avs_create_script_environment, 0);
     LOAD_AVS_FUNC(avs_delete_script_environment, 0);
     LOAD_AVS_FUNC(avs_get_audio, 0);
@@ -807,26 +810,38 @@  static int avisynth_create_stream(AVFormatContext *s)
 static int avisynth_open_file(AVFormatContext *s)
 {
     AviSynthContext *avs = s->priv_data;
-    AVS_Value arg, val;
+    AVS_Value val;
     int ret;
-#ifdef _WIN32
-    char filename_ansi[MAX_PATH * 4];
-    wchar_t filename_wc[MAX_PATH * 4];
-#endif
 
     if (ret = avisynth_context_create(s))
         return ret;
 
+    if (!avs_library.avs_check_version(avs->env, 7)) {
+        AVS_Value args[] = {
+            avs_new_value_string(s->url),
+            avs_new_value_bool(1) // filename is in UTF-8
+        };
+        val = avs_library.avs_invoke(avs->env, "Import",
+                                     avs_new_value_array(args, 2), 0);
+    } else {
+        AVS_Value arg;
 #ifdef _WIN32
-    /* Convert UTF-8 to ANSI code page */
-    MultiByteToWideChar(CP_UTF8, 0, s->url, -1, filename_wc, MAX_PATH * 4);
-    WideCharToMultiByte(CP_THREAD_ACP, 0, filename_wc, -1, filename_ansi,
-                        MAX_PATH * 4, NULL, NULL);
-    arg = avs_new_value_string(filename_ansi);
+        char *filename_ansi;
+        /* Convert UTF-8 to ANSI code page */
+        if (utf8toansi(s->url, &filename_ansi)) {
+            ret = AVERROR_UNKNOWN;
+            goto fail;
+        }
+        arg = avs_new_value_string(filename_ansi);
 #else
-    arg = avs_new_value_string(s->url);
+        arg = avs_new_value_string(s->url);
 #endif
-    val = avs_library.avs_invoke(avs->env, "Import", arg, 0);
+        val = avs_library.avs_invoke(avs->env, "Import", arg, 0);
+#ifdef _WIN32
+        av_free(filename_ansi);
+#endif
+    }
+
     if (avs_is_error(val)) {
         av_log(s, AV_LOG_ERROR, "%s\n", avs_as_error(val));
         ret = AVERROR_UNKNOWN;
diff --git a/libavformat/http.c b/libavformat/http.c
index c8f3f4b6a3..d90117e422 100644
--- a/libavformat/http.c
+++ b/libavformat/http.c
@@ -29,6 +29,7 @@ 
 #include "libavutil/avassert.h"
 #include "libavutil/avstring.h"
 #include "libavutil/bprint.h"
+#include "libavutil/getenv_utf8.h"
 #include "libavutil/opt.h"
 #include "libavutil/time.h"
 #include "libavutil/parseutils.h"
@@ -198,6 +199,7 @@  void ff_http_init_auth_state(URLContext *dest, const URLContext *src)
 static int http_open_cnx_internal(URLContext *h, AVDictionary **options)
 {
     const char *path, *proxy_path, *lower_proto = "tcp", *local_path;
+    char *env_http_proxy, *env_no_proxy;
     char *hashmark;
     char hostname[1024], hoststr[1024], proto[10];
     char auth[1024], proxyauth[1024] = "";
@@ -211,9 +213,13 @@  static int http_open_cnx_internal(URLContext *h, AVDictionary **options)
                  path1, sizeof(path1), s->location);
     ff_url_join(hoststr, sizeof(hoststr), NULL, NULL, hostname, port, NULL);
 
-    proxy_path = s->http_proxy ? s->http_proxy : getenv("http_proxy");
-    use_proxy  = !ff_http_match_no_proxy(getenv("no_proxy"), hostname) &&
+    env_http_proxy = getenv_utf8("http_proxy");
+    proxy_path = s->http_proxy ? s->http_proxy : env_http_proxy;
+
+    env_no_proxy = getenv_utf8("no_proxy");
+    use_proxy  = !ff_http_match_no_proxy(env_no_proxy, hostname) &&
                  proxy_path && av_strstart(proxy_path, "http://", NULL);
+    av_freep(&env_no_proxy);
 
     if (!strcmp(proto, "https")) {
         lower_proto = "tls";
@@ -224,7 +230,7 @@  static int http_open_cnx_internal(URLContext *h, AVDictionary **options)
         if (s->http_proxy) {
             err = av_dict_set(options, "http_proxy", s->http_proxy, 0);
             if (err < 0)
-                return err;
+                goto end;
         }
     }
     if (port < 0)
@@ -259,12 +265,12 @@  static int http_open_cnx_internal(URLContext *h, AVDictionary **options)
         err = ffurl_open_whitelist(&s->hd, buf, AVIO_FLAG_READ_WRITE,
                                    &h->interrupt_callback, options,
                                    h->protocol_whitelist, h->protocol_blacklist, h);
-        if (err < 0)
-            return err;
     }
 
-    return http_connect(h, path, local_path, hoststr,
-                        auth, proxyauth);
+end:
+    av_freep(&env_http_proxy);
+    return err < 0 ? err : http_connect(
+        h, path, local_path, hoststr, auth, proxyauth);
 }
 
 static int http_should_reconnect(HTTPContext *s, int err)
diff --git a/libavformat/ipfsgateway.c b/libavformat/ipfsgateway.c
index 83d52293b4..a8323403f0 100644
--- a/libavformat/ipfsgateway.c
+++ b/libavformat/ipfsgateway.c
@@ -20,6 +20,7 @@ 
  */
 
 #include "libavutil/avstring.h"
+#include "libavutil/getenv_utf8.h"
 #include "libavutil/opt.h"
 #include <sys/stat.h>
 #include "os_support.h"
@@ -55,12 +56,15 @@  static int populate_ipfs_gateway(URLContext *h)
     int stat_ret = 0;
     int ret = AVERROR(EINVAL);
     FILE *gateway_file = NULL;
+    char *env_ipfs_gateway, *env_ipfs_path;
 
     // Test $IPFS_GATEWAY.
-    if (getenv("IPFS_GATEWAY") != NULL) {
-        if (snprintf(c->gateway_buffer, sizeof(c->gateway_buffer), "%s",
-                     getenv("IPFS_GATEWAY"))
-            >= sizeof(c->gateway_buffer)) {
+    env_ipfs_gateway = getenv_utf8("IPFS_GATEWAY");
+    if (env_ipfs_gateway != NULL) {
+        int printed = snprintf(c->gateway_buffer, sizeof(c->gateway_buffer),
+                               "%s", env_ipfs_gateway);
+        av_freep(&env_ipfs_gateway);
+        if (printed >= sizeof(c->gateway_buffer)) {
             av_log(h, AV_LOG_WARNING,
                    "The IPFS_GATEWAY environment variable "
                    "exceeds the maximum length. "
@@ -77,20 +81,25 @@  static int populate_ipfs_gateway(URLContext *h)
 
     // We need to know the IPFS folder to - eventually - read the contents of
     // the "gateway" file which would tell us the gateway to use.
-    if (getenv("IPFS_PATH") == NULL) {
+    env_ipfs_path = getenv_utf8("IPFS_PATH");
+    if (env_ipfs_path == NULL) {
+        char *env_home = getenv_utf8("HOME");
+
         av_log(h, AV_LOG_DEBUG, "$IPFS_PATH is empty.\n");
 
         // Try via the home folder.
-        if (getenv("HOME") == NULL) {
+        if (env_home == NULL) {
             av_log(h, AV_LOG_WARNING, "$HOME appears to be empty.\n");
             ret = AVERROR(EINVAL);
             goto err;
         }
 
         // Verify the composed path fits.
-        if (snprintf(ipfs_full_data_folder, sizeof(ipfs_full_data_folder),
-                     "%s/.ipfs/", getenv("HOME"))
-            >= sizeof(ipfs_full_data_folder)) {
+        int printed = snprintf(
+            ipfs_full_data_folder, sizeof(ipfs_full_data_folder),
+            "%s/.ipfs/", env_home);
+        av_freep(&env_home);
+        if (printed >= sizeof(ipfs_full_data_folder)) {
             av_log(h, AV_LOG_WARNING,
                    "The IPFS data path exceeds the "
                    "max path length (%zu)\n",
@@ -113,9 +122,11 @@  static int populate_ipfs_gateway(URLContext *h)
             goto err;
         }
     } else {
-        if (snprintf(ipfs_full_data_folder, sizeof(ipfs_full_data_folder), "%s",
-                     getenv("IPFS_PATH"))
-            >= sizeof(ipfs_full_data_folder)) {
+        int printed = snprintf(
+            ipfs_full_data_folder, sizeof(ipfs_full_data_folder),
+            "%s", env_ipfs_path);
+        av_freep(&env_ipfs_path);
+        if (printed >= sizeof(ipfs_full_data_folder)) {
             av_log(h, AV_LOG_WARNING,
                    "The IPFS_PATH environment variable "
                    "exceeds the maximum length. "
diff --git a/libavformat/tls.c b/libavformat/tls.c
index 302c0f8d59..ea68f18d3a 100644
--- a/libavformat/tls.c
+++ b/libavformat/tls.c
@@ -26,6 +26,7 @@ 
 #include "url.h"
 #include "tls.h"
 #include "libavutil/avstring.h"
+#include "libavutil/getenv_utf8.h"
 #include "libavutil/opt.h"
 #include "libavutil/parseutils.h"
 
@@ -60,6 +61,7 @@  int ff_tls_open_underlying(TLSShared *c, URLContext *parent, const char *uri, AV
     char buf[200], opts[50] = "";
     struct addrinfo hints = { 0 }, *ai = NULL;
     const char *proxy_path;
+    char *env_http_proxy, *env_no_proxy;
     int use_proxy;
 
     set_options(c, uri);
@@ -89,9 +91,13 @@  int ff_tls_open_underlying(TLSShared *c, URLContext *parent, const char *uri, AV
     if (!c->host && !(c->host = av_strdup(c->underlying_host)))
         return AVERROR(ENOMEM);
 
-    proxy_path = c->http_proxy ? c->http_proxy : getenv("http_proxy");
-    use_proxy = !ff_http_match_no_proxy(getenv("no_proxy"), c->underlying_host) &&
+    env_http_proxy = getenv_utf8("http_proxy");
+    proxy_path = c->http_proxy ? c->http_proxy : env_http_proxy;
+
+    env_no_proxy = getenv_utf8("no_proxy");
+    use_proxy = !ff_http_match_no_proxy(env_no_proxy, c->underlying_host) &&
                 proxy_path && av_strstart(proxy_path, "http://", NULL);
+    av_freep(&env_no_proxy);
 
     if (use_proxy) {
         char proxy_host[200], proxy_auth[200], dest[200];
@@ -104,6 +110,7 @@  int ff_tls_open_underlying(TLSShared *c, URLContext *parent, const char *uri, AV
                     proxy_port, "/%s", dest);
     }
 
+    av_freep(&env_http_proxy);
     return ffurl_open_whitelist(&c->tcp, buf, AVIO_FLAG_READ_WRITE,
                                 &parent->interrupt_callback, options,
                                 parent->protocol_whitelist, parent->protocol_blacklist, parent);