/src/gstreamer/ci/fuzzing/gst-subparse.c
Line | Count | Source |
1 | | /* |
2 | | * Copyright 2026 Google Inc. |
3 | | * author: Arthur SC Chan <arthur.chan@adalogics.com> |
4 | | * |
5 | | * Licensed under the Apache License, Version 2.0 (the "License"); |
6 | | * you may not use this file except in compliance with the License. |
7 | | * You may obtain a copy of the License at |
8 | | * |
9 | | * http://www.apache.org/licenses/LICENSE-2.0 |
10 | | * |
11 | | * Unless required by applicable law or agreed to in writing, software |
12 | | * distributed under the License is distributed on an "AS IS" BASIS, |
13 | | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
14 | | * See the License for the specific language governing permissions and |
15 | | * limitations under the License. |
16 | | * |
17 | | */ |
18 | | |
19 | | #ifdef HAVE_CONFIG_H |
20 | | #include "config.h" |
21 | | #endif |
22 | | |
23 | | #include <locale.h> |
24 | | #include <stdlib.h> |
25 | | #include <string.h> |
26 | | #include <glib.h> |
27 | | #include <gst/gst.h> |
28 | | |
29 | | /* Subtitle parsing fuzzing target |
30 | | * |
31 | | * This application can be compiled with libFuzzer to fuzz |
32 | | * subtitle parsing in gst-plugins-base/gst/subparse/ |
33 | | * |
34 | | * The goal is to cover subtitle parsing code for: |
35 | | * - SubRip (SRT) - Most common subtitle format with timestamps |
36 | | * - WebVTT - Web Video Text Tracks with cue settings |
37 | | * - SSA/ASS - Advanced SubStation Alpha with styling |
38 | | * - MicroDVD - Frame-based format with {frame}{frame} syntax |
39 | | * - SAMI - Microsoft HTML-based subtitle format |
40 | | * - SubViewer - Another time-based format |
41 | | * - MPSub - MPlayer subtitle format |
42 | | * - TMPlayer - Frame/time based format |
43 | | * - MPL2 - Frame-based variant |
44 | | * - DKS - Frame-based format |
45 | | * - QuickTime Text - Apple subtitle format |
46 | | * - LRC - Lyrics format with embedded timestamps |
47 | | * |
48 | | * All parsers handle complex text/binary formats with potential for: |
49 | | * - Memory corruption (buffer overflows) |
50 | | * - Regular expression DoS (ReDoS) attacks |
51 | | * - Integer overflows in timestamp parsing |
52 | | * - HTML/XML injection in tag handling |
53 | | * - Logic errors in format detection |
54 | | * - Encoding conversion vulnerabilities |
55 | | **/ |
56 | | |
57 | | static void |
58 | | custom_logger (const gchar * log_domain, GLogLevelFlags log_level, |
59 | | const gchar * message, gpointer unused_data) |
60 | 2 | { |
61 | 2 | if (log_level & G_LOG_LEVEL_CRITICAL) { |
62 | 0 | g_printerr ("CRITICAL ERROR : %s\n", message); |
63 | 0 | abort (); |
64 | 2 | } else if (log_level & G_LOG_LEVEL_WARNING) { |
65 | 1 | g_printerr ("WARNING : %s\n", message); |
66 | 1 | } |
67 | 2 | } |
68 | | |
69 | | static void |
70 | | test_subtitle_parsing_direct_pad_chain (const guint8 * data, size_t size) |
71 | 6.18k | { |
72 | 6.18k | GstElement *subparse, *fakesink; |
73 | 6.18k | GstPad *sinkpad, *srcpad, *fakesink_pad; |
74 | 6.18k | GstBuffer *buffer; |
75 | 6.18k | GstCaps *caps; |
76 | 6.18k | GstSegment segment; |
77 | | |
78 | | /* Create subparse element */ |
79 | 6.18k | subparse = gst_element_factory_make ("subparse", NULL); |
80 | 6.18k | g_assert (subparse != NULL); |
81 | | |
82 | | /* Create fakesink to receive output */ |
83 | 6.18k | fakesink = gst_element_factory_make ("fakesink", NULL); |
84 | 6.18k | g_assert (fakesink != NULL); |
85 | | |
86 | | /* Get pads */ |
87 | 6.18k | sinkpad = gst_element_get_static_pad (subparse, "sink"); |
88 | 6.18k | srcpad = gst_element_get_static_pad (subparse, "src"); |
89 | 6.18k | fakesink_pad = gst_element_get_static_pad (fakesink, "sink"); |
90 | | |
91 | 6.18k | g_assert (sinkpad); |
92 | 6.18k | g_assert (srcpad); |
93 | 6.18k | g_assert (fakesink_pad); |
94 | | |
95 | | /* Link subparse to fakesink */ |
96 | 6.18k | g_assert (gst_pad_link (srcpad, fakesink_pad) == GST_PAD_LINK_OK); |
97 | | |
98 | | /* Set elements to PLAYING state (sink to source order) */ |
99 | 6.18k | gst_element_set_state (fakesink, GST_STATE_PLAYING); |
100 | 6.18k | gst_element_set_state (subparse, GST_STATE_PLAYING); |
101 | | |
102 | | /* Send stream-start event */ |
103 | 6.18k | gst_pad_send_event (sinkpad, gst_event_new_stream_start ("fuzz-stream")); |
104 | | |
105 | | /* Send segment event */ |
106 | 6.18k | gst_segment_init (&segment, GST_FORMAT_TIME); |
107 | 6.18k | gst_pad_send_event (sinkpad, gst_event_new_segment (&segment)); |
108 | | |
109 | | /* Create buffer with fuzzer data */ |
110 | 6.18k | buffer = |
111 | 6.18k | gst_buffer_new_wrapped_full (GST_MEMORY_FLAG_READONLY, (gpointer) data, |
112 | 6.18k | size, 0, size, NULL, NULL); |
113 | 6.18k | if (buffer) { |
114 | | /* Chain buffer directly to pad - errors are expected with bad data */ |
115 | 6.18k | gst_pad_chain (sinkpad, buffer); |
116 | | |
117 | | /* Send EOS event */ |
118 | 6.18k | gst_pad_send_event (sinkpad, gst_event_new_eos ()); |
119 | 6.18k | } |
120 | | |
121 | | /* Cleanup (source to sink order) */ |
122 | 6.18k | gst_element_set_state (subparse, GST_STATE_NULL); |
123 | 6.18k | gst_element_set_state (fakesink, GST_STATE_NULL); |
124 | 6.18k | gst_object_unref (sinkpad); |
125 | 6.18k | gst_object_unref (srcpad); |
126 | 6.18k | gst_object_unref (fakesink_pad); |
127 | 6.18k | gst_object_unref (subparse); |
128 | 6.18k | gst_object_unref (fakesink); |
129 | 6.18k | } |
130 | | |
131 | | int |
132 | | LLVMFuzzerTestOneInput (const guint8 * data, size_t size) |
133 | 6.18k | { |
134 | 6.18k | static gboolean initialized = FALSE; |
135 | | |
136 | 6.18k | if (!initialized) { |
137 | 1 | g_log_set_always_fatal (G_LOG_LEVEL_CRITICAL); |
138 | 1 | g_log_set_default_handler (custom_logger, NULL); |
139 | | |
140 | 1 | gst_init (NULL, NULL); |
141 | | |
142 | 1 | initialized = TRUE; |
143 | 1 | } |
144 | | |
145 | 6.18k | if (size == 0) |
146 | 0 | return 0; |
147 | | |
148 | | /* Test direct pad chain approach */ |
149 | 6.18k | test_subtitle_parsing_direct_pad_chain (data, size); |
150 | | |
151 | 6.18k | return 0; |
152 | 6.18k | } |