mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-03 05:59:10 +00:00
mpdparser: validate representation set identifier
It must have no whitespace, and must comply with RFC 1738 when used to build a URL. https://bugzilla.gnome.org/show_bug.cgi?id=750852
This commit is contained in:
parent
704d49b9c7
commit
b8df6cc316
2 changed files with 105 additions and 5 deletions
|
@ -33,6 +33,9 @@
|
||||||
#define GST_CAT_DEFAULT gst_dash_demux_debug
|
#define GST_CAT_DEFAULT gst_dash_demux_debug
|
||||||
|
|
||||||
/* Property parsing */
|
/* Property parsing */
|
||||||
|
static gboolean gst_mpdparser_get_xml_prop_validated_string (xmlNode * a_node,
|
||||||
|
const gchar * property_name, gchar ** property_value,
|
||||||
|
gboolean (*validator) (const char *));
|
||||||
static gboolean gst_mpdparser_get_xml_prop_string (xmlNode * a_node,
|
static gboolean gst_mpdparser_get_xml_prop_string (xmlNode * a_node,
|
||||||
const gchar * property_name, gchar ** property_value);
|
const gchar * property_name, gchar ** property_value);
|
||||||
static gboolean gst_mpdparser_get_xml_ns_prop_string (xmlNode * a_node,
|
static gboolean gst_mpdparser_get_xml_ns_prop_string (xmlNode * a_node,
|
||||||
|
@ -253,14 +256,20 @@ static const struct GstMpdParserUtcTimingMethod
|
||||||
|
|
||||||
/* functions to parse node namespaces, content and properties */
|
/* functions to parse node namespaces, content and properties */
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_mpdparser_get_xml_prop_string (xmlNode * a_node,
|
gst_mpdparser_get_xml_prop_validated_string (xmlNode * a_node,
|
||||||
const gchar * property_name, gchar ** property_value)
|
const gchar * property_name, gchar ** property_value,
|
||||||
|
gboolean (*validate) (const char *))
|
||||||
{
|
{
|
||||||
xmlChar *prop_string;
|
xmlChar *prop_string;
|
||||||
gboolean exists = FALSE;
|
gboolean exists = FALSE;
|
||||||
|
|
||||||
prop_string = xmlGetProp (a_node, (const xmlChar *) property_name);
|
prop_string = xmlGetProp (a_node, (const xmlChar *) property_name);
|
||||||
if (prop_string) {
|
if (prop_string) {
|
||||||
|
if (validate && !(*validate) ((const char *) prop_string)) {
|
||||||
|
GST_WARNING ("Validation failure: %s", prop_string);
|
||||||
|
xmlFree (prop_string);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
*property_value = (gchar *) prop_string;
|
*property_value = (gchar *) prop_string;
|
||||||
exists = TRUE;
|
exists = TRUE;
|
||||||
GST_LOG (" - %s: %s", property_name, prop_string);
|
GST_LOG (" - %s: %s", property_name, prop_string);
|
||||||
|
@ -288,6 +297,28 @@ gst_mpdparser_get_xml_ns_prop_string (xmlNode * a_node,
|
||||||
return exists;
|
return exists;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_mpdparser_get_xml_prop_string (xmlNode * a_node,
|
||||||
|
const gchar * property_name, gchar ** property_value)
|
||||||
|
{
|
||||||
|
return gst_mpdparser_get_xml_prop_validated_string (a_node, property_name,
|
||||||
|
property_value, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_mpdparser_validate_no_whitespace (const char *s)
|
||||||
|
{
|
||||||
|
return !strpbrk (s, "\r\n\t ");
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_mpdparser_get_xml_prop_string_no_whitespace (xmlNode * a_node,
|
||||||
|
const gchar * property_name, gchar ** property_value)
|
||||||
|
{
|
||||||
|
return gst_mpdparser_get_xml_prop_validated_string (a_node, property_name,
|
||||||
|
property_value, gst_mpdparser_validate_no_whitespace);
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_mpdparser_get_xml_prop_string_vector_type (xmlNode * a_node,
|
gst_mpdparser_get_xml_prop_string_vector_type (xmlNode * a_node,
|
||||||
const gchar * property_name, gchar *** property_value)
|
const gchar * property_name, gchar *** property_value)
|
||||||
|
@ -1571,7 +1602,8 @@ gst_mpdparser_parse_representation_node (GList ** list, xmlNode * a_node,
|
||||||
*list = g_list_append (*list, new_representation);
|
*list = g_list_append (*list, new_representation);
|
||||||
|
|
||||||
GST_LOG ("attributes of Representation node:");
|
GST_LOG ("attributes of Representation node:");
|
||||||
gst_mpdparser_get_xml_prop_string (a_node, "id", &new_representation->id);
|
gst_mpdparser_get_xml_prop_string_no_whitespace (a_node, "id",
|
||||||
|
&new_representation->id);
|
||||||
gst_mpdparser_get_xml_prop_unsigned_integer (a_node, "bandwidth", 0,
|
gst_mpdparser_get_xml_prop_unsigned_integer (a_node, "bandwidth", 0,
|
||||||
&new_representation->bandwidth);
|
&new_representation->bandwidth);
|
||||||
gst_mpdparser_get_xml_prop_unsigned_integer (a_node, "qualityRanking", 0,
|
gst_mpdparser_get_xml_prop_unsigned_integer (a_node, "qualityRanking", 0,
|
||||||
|
@ -2868,6 +2900,26 @@ promote_format_to_uint64 (const gchar * format)
|
||||||
return promoted_format;
|
return promoted_format;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_mpdparser_validate_rfc1738_url (const char *s)
|
||||||
|
{
|
||||||
|
while (*s) {
|
||||||
|
if (!strchr
|
||||||
|
(";:@&=aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ0123456789$-_.+!*'(),%",
|
||||||
|
*s))
|
||||||
|
return FALSE;
|
||||||
|
if (*s == '%') {
|
||||||
|
/* g_ascii_isdigit returns FALSE for NUL, and || is a short circuiting
|
||||||
|
operator, so this is safe for strings ending before two hex digits */
|
||||||
|
if (!g_ascii_isxdigit (s[1]) || !g_ascii_isxdigit (s[2]))
|
||||||
|
return FALSE;
|
||||||
|
s += 2;
|
||||||
|
}
|
||||||
|
s++;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
static gchar *
|
static gchar *
|
||||||
gst_mpdparser_build_URL_from_template (const gchar * url_template,
|
gst_mpdparser_build_URL_from_template (const gchar * url_template,
|
||||||
const gchar * id, guint number, guint bandwidth, guint64 time)
|
const gchar * id, guint number, guint bandwidth, guint64 time)
|
||||||
|
@ -2891,6 +2943,11 @@ gst_mpdparser_build_URL_from_template (const gchar * url_template,
|
||||||
format = default_format;
|
format = default_format;
|
||||||
|
|
||||||
if (!g_strcmp0 (token, "RepresentationID")) {
|
if (!g_strcmp0 (token, "RepresentationID")) {
|
||||||
|
if (!gst_mpdparser_validate_rfc1738_url (id)) {
|
||||||
|
GST_WARNING ("String '%s' has characters invalid in an RFC 1738 URL",
|
||||||
|
id);
|
||||||
|
goto invalid_format;
|
||||||
|
}
|
||||||
tokens[i] = g_strdup_printf ("%s", id);
|
tokens[i] = g_strdup_printf ("%s", id);
|
||||||
g_free (token);
|
g_free (token);
|
||||||
last_token_par = TRUE;
|
last_token_par = TRUE;
|
||||||
|
|
|
@ -2016,7 +2016,7 @@ GST_START_TEST (dash_mpdparser_period_adaptationSet_representation)
|
||||||
" profiles=\"urn:mpeg:dash:profile:isoff-main:2011\">"
|
" profiles=\"urn:mpeg:dash:profile:isoff-main:2011\">"
|
||||||
" <Period>"
|
" <Period>"
|
||||||
" <AdaptationSet>"
|
" <AdaptationSet>"
|
||||||
" <Representation id=\"Test Id\""
|
" <Representation id=\"Test_Id\""
|
||||||
" bandwidth=\"100\""
|
" bandwidth=\"100\""
|
||||||
" qualityRanking=\"200\""
|
" qualityRanking=\"200\""
|
||||||
" dependencyId=\"one two three\""
|
" dependencyId=\"one two three\""
|
||||||
|
@ -2033,7 +2033,7 @@ GST_START_TEST (dash_mpdparser_period_adaptationSet_representation)
|
||||||
adaptationSet = (GstAdaptationSetNode *) periodNode->AdaptationSets->data;
|
adaptationSet = (GstAdaptationSetNode *) periodNode->AdaptationSets->data;
|
||||||
representation = (GstRepresentationNode *)
|
representation = (GstRepresentationNode *)
|
||||||
adaptationSet->Representations->data;
|
adaptationSet->Representations->data;
|
||||||
assert_equals_string (representation->id, "Test Id");
|
assert_equals_string (representation->id, "Test_Id");
|
||||||
assert_equals_uint64 (representation->bandwidth, 100);
|
assert_equals_uint64 (representation->bandwidth, 100);
|
||||||
assert_equals_uint64 (representation->qualityRanking, 200);
|
assert_equals_uint64 (representation->qualityRanking, 200);
|
||||||
assert_equals_string (representation->dependencyId[0], "one");
|
assert_equals_string (representation->dependencyId[0], "one");
|
||||||
|
@ -4447,6 +4447,44 @@ GST_START_TEST
|
||||||
|
|
||||||
GST_END_TEST;
|
GST_END_TEST;
|
||||||
|
|
||||||
|
GST_START_TEST (dash_mpdparser_whitespace_strings)
|
||||||
|
{
|
||||||
|
fail_unless (gst_mpdparser_validate_no_whitespace ("") == TRUE);
|
||||||
|
fail_unless (gst_mpdparser_validate_no_whitespace ("/") == TRUE);
|
||||||
|
fail_unless (gst_mpdparser_validate_no_whitespace (" ") == FALSE);
|
||||||
|
fail_unless (gst_mpdparser_validate_no_whitespace ("aaaaaaaa ") == FALSE);
|
||||||
|
fail_unless (gst_mpdparser_validate_no_whitespace ("a\ta") == FALSE);
|
||||||
|
fail_unless (gst_mpdparser_validate_no_whitespace ("a\ra") == FALSE);
|
||||||
|
fail_unless (gst_mpdparser_validate_no_whitespace ("a\na") == FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_END_TEST;
|
||||||
|
|
||||||
|
GST_START_TEST (dash_mpdparser_rfc1738_strings)
|
||||||
|
{
|
||||||
|
fail_unless (gst_mpdparser_validate_rfc1738_url ("/") == FALSE);
|
||||||
|
fail_unless (gst_mpdparser_validate_rfc1738_url (" ") == FALSE);
|
||||||
|
fail_unless (gst_mpdparser_validate_rfc1738_url ("aaaaaaaa ") == FALSE);
|
||||||
|
|
||||||
|
fail_unless (gst_mpdparser_validate_rfc1738_url ("") == TRUE);
|
||||||
|
fail_unless (gst_mpdparser_validate_rfc1738_url ("a") == TRUE);
|
||||||
|
fail_unless (gst_mpdparser_validate_rfc1738_url
|
||||||
|
(";:@&=aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ0123456789$-_.+!*'(),%AA")
|
||||||
|
== TRUE);
|
||||||
|
fail_unless (gst_mpdparser_validate_rfc1738_url
|
||||||
|
(";:@&=aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ0123456789$-_.+!*'(),% ")
|
||||||
|
== FALSE);
|
||||||
|
fail_unless (gst_mpdparser_validate_rfc1738_url ("%AA") == TRUE);
|
||||||
|
fail_unless (gst_mpdparser_validate_rfc1738_url ("%A") == FALSE);
|
||||||
|
fail_unless (gst_mpdparser_validate_rfc1738_url ("%") == FALSE);
|
||||||
|
fail_unless (gst_mpdparser_validate_rfc1738_url ("%XA") == FALSE);
|
||||||
|
fail_unless (gst_mpdparser_validate_rfc1738_url ("%AX") == FALSE);
|
||||||
|
fail_unless (gst_mpdparser_validate_rfc1738_url ("%XX") == FALSE);
|
||||||
|
fail_unless (gst_mpdparser_validate_rfc1738_url ("\001") == FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_END_TEST;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* create a test suite containing all dash testcases
|
* create a test suite containing all dash testcases
|
||||||
*/
|
*/
|
||||||
|
@ -4457,6 +4495,7 @@ dash_suite (void)
|
||||||
TCase *tc_simpleMPD = tcase_create ("simpleMPD");
|
TCase *tc_simpleMPD = tcase_create ("simpleMPD");
|
||||||
TCase *tc_complexMPD = tcase_create ("complexMPD");
|
TCase *tc_complexMPD = tcase_create ("complexMPD");
|
||||||
TCase *tc_negativeTests = tcase_create ("negativeTests");
|
TCase *tc_negativeTests = tcase_create ("negativeTests");
|
||||||
|
TCase *tc_stringTests = tcase_create ("stringTests");
|
||||||
|
|
||||||
GST_DEBUG_CATEGORY_INIT (gst_dash_demux_debug, "gst_dash_demux_debug", 0,
|
GST_DEBUG_CATEGORY_INIT (gst_dash_demux_debug, "gst_dash_demux_debug", 0,
|
||||||
"mpeg dash tests");
|
"mpeg dash tests");
|
||||||
|
@ -4605,9 +4644,13 @@ dash_suite (void)
|
||||||
tcase_add_test (tc_negativeTests,
|
tcase_add_test (tc_negativeTests,
|
||||||
dash_mpdparser_wrong_period_duration_inferred_from_next_mediaPresentationDuration);
|
dash_mpdparser_wrong_period_duration_inferred_from_next_mediaPresentationDuration);
|
||||||
|
|
||||||
|
tcase_add_test (tc_stringTests, dash_mpdparser_whitespace_strings);
|
||||||
|
tcase_add_test (tc_stringTests, dash_mpdparser_rfc1738_strings);
|
||||||
|
|
||||||
suite_add_tcase (s, tc_simpleMPD);
|
suite_add_tcase (s, tc_simpleMPD);
|
||||||
suite_add_tcase (s, tc_complexMPD);
|
suite_add_tcase (s, tc_complexMPD);
|
||||||
suite_add_tcase (s, tc_negativeTests);
|
suite_add_tcase (s, tc_negativeTests);
|
||||||
|
suite_add_tcase (s, tc_stringTests);
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue