* [FFmpeg-devel] [PATCH] avformat/hls: fix data: URI handling in open_url
@ 2026-02-15 21:57 Bradley Walters via ffmpeg-devel
0 siblings, 0 replies; only message in thread
From: Bradley Walters via ffmpeg-devel @ 2026-02-15 21:57 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Bradley Walters
The existing code for data: URIs in open_url() called
avio_find_protocol_name(url + 5) which strips the 'data:' prefix
and passes the MIME type portion (e.g. 'application/octet-stream;...')
to protocol lookup. Since this is not a valid URL, it falls back to
the 'file' protocol, which then triggers the allowed_extensions
security check and blocks the URL.
This breaks HLS streams that embed AES-128 decryption keys as data:
URIs (e.g. data:application/octet-stream;base64,<key>).
Split the data handling into two cases:
- data+<proto>: for nested protocol combinations, parse the inner
protocol name as before
- data:<content>: bare data URIs, set proto_name directly to 'data'
since the data protocol handler will process the full URI
Signed-off-by: Bradley Walters <oss@walters.app>
---
My use case for this is to provide a patched manifest to ffmpeg
inlining the key when the URL would otherwise require Cloudflare.
libavformat/hls.c | 7 ++--
tests/Makefile | 1 +
tests/fate/hlsdec.mak | 23 +++++++++++
tests/ref/fate/hls-data-uri | 82 +++++++++++++++++++++++++++++++++++++
4 files changed, 110 insertions(+), 3 deletions(-)
create mode 100644 tests/fate/hlsdec.mak
create mode 100644 tests/ref/fate/hls-data-uri
diff --git a/libavformat/hls.c b/libavformat/hls.c
index 28c883097a..d91920feaa 100644
--- a/libavformat/hls.c
+++ b/libavformat/hls.c
@@ -660,9 +660,10 @@ static int open_url(AVFormatContext *s, AVIOContext **pb, const char *url,
if (av_strstart(url, "crypto", NULL)) {
if (url[6] == '+' || url[6] == ':')
proto_name = avio_find_protocol_name(url + 7);
- } else if (av_strstart(url, "data", NULL)) {
- if (url[4] == '+' || url[4] == ':')
- proto_name = avio_find_protocol_name(url + 5);
+ } else if (av_strstart(url, "data+", NULL)) {
+ proto_name = avio_find_protocol_name(url + 5);
+ } else if (av_strstart(url, "data:", NULL)) {
+ proto_name = "data";
}
if (!proto_name)
diff --git a/tests/Makefile b/tests/Makefile
index 4b3fa6a54a..64e7ee4a7a 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -199,6 +199,7 @@ include $(SRC_PATH)/tests/fate/gif.mak
include $(SRC_PATH)/tests/fate/h264.mak
include $(SRC_PATH)/tests/fate/hap.mak
include $(SRC_PATH)/tests/fate/hevc.mak
+include $(SRC_PATH)/tests/fate/hlsdec.mak
include $(SRC_PATH)/tests/fate/hlsenc.mak
include $(SRC_PATH)/tests/fate/hw.mak
include $(SRC_PATH)/tests/fate/iamf.mak
diff --git a/tests/fate/hlsdec.mak b/tests/fate/hlsdec.mak
new file mode 100644
index 0000000000..6151707bbf
--- /dev/null
+++ b/tests/fate/hlsdec.mak
@@ -0,0 +1,23 @@
+# Rewrite an HLS playlist to use a data: URI for the AES-128 key.
+# The key file contains the ASCII string "0000000000000000" (16 bytes of 0x30),
+# which base64-encodes to MDAwMDAwMDAwMDAwMDAwMA==.
+tests/data/hls_data_uri.m3u8: TAG = GEN
+tests/data/hls_data_uri.m3u8: ffmpeg$(PROGSSUF)$(EXESUF) | tests/data
+ $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< -nostdin \
+ -f lavfi -i "aevalsrc=cos(2*PI*t)*sin(2*PI*(440+4*t)*t):d=2" -f hls -hls_time 1 -map 0 \
+ -flags +bitexact -codec:a mp2fixed -hls_list_size 0 \
+ -hls_enc 1 -hls_enc_key 00000000000000000000000000000000 \
+ -hls_enc_iv 00000000000000000000000000000000 \
+ -hls_segment_filename $(TARGET_PATH)/tests/data/hls_data_uri_%d.ts \
+ $(TARGET_PATH)/tests/data/hls_data_uri.m3u8 2>/dev/null; \
+ sed -i 's|URI="[^"]*"|URI="data:application/octet-stream;base64,MDAwMDAwMDAwMDAwMDAwMA=="|' \
+ $(TARGET_PATH)/tests/data/hls_data_uri.m3u8
+
+FATE_HLSDEC-$(call FILTERDEMDECENCMUX, AEVALSRC ARESAMPLE, HLS MPEGTS, MP2 PCM_F64LE, MP2FIXED, HLS MPEGTS, LAVFI_INDEV CRYPTO_PROTOCOL DATA_PROTOCOL) += fate-hls-data-uri
+fate-hls-data-uri: tests/data/hls_data_uri.m3u8
+fate-hls-data-uri: CMD = framecrc -auto_conversion_filters -flags +bitexact -i $(TARGET_PATH)/tests/data/hls_data_uri.m3u8
+
+FATE_HLSDEC-yes := $(if $(call FRAMECRC), $(FATE_HLSDEC-yes))
+
+FATE_FFMPEG += $(FATE_HLSDEC-yes)
+fate-hlsdec: $(FATE_HLSDEC-yes)
diff --git a/tests/ref/fate/hls-data-uri b/tests/ref/fate/hls-data-uri
new file mode 100644
index 0000000000..a4b974ee71
--- /dev/null
+++ b/tests/ref/fate/hls-data-uri
@@ -0,0 +1,82 @@
+#tb 0: 1/44100
+#media_type 0: audio
+#codec_id 0: pcm_s16le
+#sample_rate 0: 44100
+#channel_layout_name 0: mono
+0, 0, 0, 1152, 2304, 0x907cb7fa
+0, 1152, 1152, 1152, 2304, 0xb8dc7525
+0, 2304, 2304, 1152, 2304, 0x3e7d6905
+0, 3456, 3456, 1152, 2304, 0xef47877b
+0, 4608, 4608, 1152, 2304, 0xfe916b7e
+0, 5760, 5760, 1152, 2304, 0xe3d08cde
+0, 6912, 6912, 1152, 2304, 0xff7f86cf
+0, 8064, 8064, 1152, 2304, 0x843e6f95
+0, 9216, 9216, 1152, 2304, 0x81577c26
+0, 10368, 10368, 1152, 2304, 0x04a085d5
+0, 11520, 11520, 1152, 2304, 0x1c5a76f5
+0, 12672, 12672, 1152, 2304, 0x4ee78623
+0, 13824, 13824, 1152, 2304, 0x8ec861dc
+0, 14976, 14976, 1152, 2304, 0x0ca179d8
+0, 16128, 16128, 1152, 2304, 0xc6da750f
+0, 17280, 17280, 1152, 2304, 0xf6bf79b5
+0, 18432, 18432, 1152, 2304, 0x97b88a43
+0, 19584, 19584, 1152, 2304, 0xf13c7b9c
+0, 20736, 20736, 1152, 2304, 0xdfba83af
+0, 21888, 21888, 1152, 2304, 0xc9467d4b
+0, 23040, 23040, 1152, 2304, 0xbbb58e2b
+0, 24192, 24192, 1152, 2304, 0x3a1078ea
+0, 25344, 25344, 1152, 2304, 0xe9587a5c
+0, 26496, 26496, 1152, 2304, 0xef5a8039
+0, 27648, 27648, 1152, 2304, 0x9d5f782f
+0, 28800, 28800, 1152, 2304, 0x1a548291
+0, 29952, 29952, 1152, 2304, 0x07517701
+0, 31104, 31104, 1152, 2304, 0x78127d6e
+0, 32256, 32256, 1152, 2304, 0x62e2788a
+0, 33408, 33408, 1152, 2304, 0x29397ad9
+0, 34560, 34560, 1152, 2304, 0x45da82d6
+0, 35712, 35712, 1152, 2304, 0x8ed66e51
+0, 36864, 36864, 1152, 2304, 0x660775cd
+0, 38016, 38016, 1152, 2304, 0x802c767a
+0, 39168, 39168, 1152, 2304, 0xcc055840
+0, 40320, 40320, 1152, 2304, 0x701b7eaf
+0, 41472, 41472, 1152, 2304, 0x8290749f
+0, 42624, 42624, 1152, 2304, 0x2c7b7d30
+0, 43776, 43776, 1152, 2304, 0xe4f17743
+0, 44928, 44928, 1152, 2304, 0x0e747d6e
+0, 46080, 46080, 1152, 2304, 0xbe7775a0
+0, 47232, 47232, 1152, 2304, 0xcf797673
+0, 48384, 48384, 1152, 2304, 0x29cb7800
+0, 49536, 49536, 1152, 2304, 0xfc947890
+0, 50688, 50688, 1152, 2304, 0x62757fc6
+0, 51840, 51840, 1152, 2304, 0x098876d0
+0, 52992, 52992, 1152, 2304, 0xa9567ee2
+0, 54144, 54144, 1152, 2304, 0xe3bb9173
+0, 55296, 55296, 1152, 2304, 0xcc2d6dee
+0, 56448, 56448, 1152, 2304, 0xe94591ab
+0, 57600, 57600, 1152, 2304, 0x5c7588de
+0, 58752, 58752, 1152, 2304, 0xfd83643c
+0, 59904, 59904, 1152, 2304, 0x528177f1
+0, 61056, 61056, 1152, 2304, 0x65d08474
+0, 62208, 62208, 1152, 2304, 0x738d765b
+0, 63360, 63360, 1152, 2304, 0xdd3d810e
+0, 64512, 64512, 1152, 2304, 0xef4f90d3
+0, 65664, 65664, 1152, 2304, 0x61e28d43
+0, 66816, 66816, 1152, 2304, 0x9a11796b
+0, 67968, 67968, 1152, 2304, 0x96c97dcd
+0, 69120, 69120, 1152, 2304, 0xa8fe8621
+0, 70272, 70272, 1152, 2304, 0x499b7d38
+0, 71424, 71424, 1152, 2304, 0xfcb078a9
+0, 72576, 72576, 1152, 2304, 0x40d78651
+0, 73728, 73728, 1152, 2304, 0xa4af7234
+0, 74880, 74880, 1152, 2304, 0x6831870a
+0, 76032, 76032, 1152, 2304, 0x030e7b9d
+0, 77184, 77184, 1152, 2304, 0x445a75b6
+0, 78336, 78336, 1152, 2304, 0x09857389
+0, 79488, 79488, 1152, 2304, 0x0d018866
+0, 80640, 80640, 1152, 2304, 0x2afe810a
+0, 81792, 81792, 1152, 2304, 0x0bcf7c43
+0, 82944, 82944, 1152, 2304, 0x13737c12
+0, 84096, 84096, 1152, 2304, 0x716c7bba
+0, 85248, 85248, 1152, 2304, 0xb801823b
+0, 86400, 86400, 1152, 2304, 0x0fd573ee
+0, 87552, 87552, 1152, 2304, 0x83f18952
--
2.53.0
_______________________________________________
ffmpeg-devel mailing list -- ffmpeg-devel@ffmpeg.org
To unsubscribe send an email to ffmpeg-devel-leave@ffmpeg.org
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2026-02-18 5:28 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-02-15 21:57 [FFmpeg-devel] [PATCH] avformat/hls: fix data: URI handling in open_url Bradley Walters via ffmpeg-devel
Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
This inbox may be cloned and mirrored by anyone:
git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git
# If you have public-inbox 1.1+ installed, you may
# initialize and index your mirror using the following commands:
public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \
ffmpegdev@gitmailbox.com
public-inbox-index ffmpegdev
Example config snippet for mirrors.
AGPL code for this site: git clone https://public-inbox.org/public-inbox.git