gst/gststructure.c: Avoid overflows in fixation code when dealing with MAXINT values, which v4l2src seems to do.

Original commit message from CVS:
Patch by: Olivier Crete <tester at tester dot ca>
* gst/gststructure.c:
(gst_structure_fixate_field_nearest_fraction):
Avoid overflows in fixation code when dealing with MAXINT values, which
v4l2src seems to do.
Fixes #546328.
* tests/check/gst/gststructure.c: (GST_START_TEST):
Make a unit test to check the fix.
This commit is contained in:
Olivier Crete 2008-08-05 15:03:27 +00:00 committed by Wim Taymans
parent d041a7411a
commit 70a4cad10c
3 changed files with 49 additions and 22 deletions

View file

@ -1,3 +1,16 @@
2008-08-05 Wim Taymans <wim.taymans@collabora.co.uk>
Patch by: Olivier Crete <tester at tester dot ca>
* gst/gststructure.c:
(gst_structure_fixate_field_nearest_fraction):
Avoid overflows in fixation code when dealing with MAXINT values, which
v4l2src seems to do.
Fixes #546328.
* tests/check/gst/gststructure.c: (GST_START_TEST):
Make a unit test to check the fix.
2008-08-05 Wim Taymans <wim.taymans@collabora.co.uk> 2008-08-05 Wim Taymans <wim.taymans@collabora.co.uk>
* plugins/elements/gstcapsfilter.c: (copy_func), * plugins/elements/gstcapsfilter.c: (copy_func),

View file

@ -2232,16 +2232,13 @@ gst_structure_fixate_field_nearest_fraction (GstStructure * structure,
const GValue *list_value; const GValue *list_value;
int i, n; int i, n;
const GValue *best = NULL; const GValue *best = NULL;
GValue best_diff = { 0 }; gdouble target;
GValue cur_diff = { 0 }; gdouble cur_diff;
GValue target = { 0 }; gdouble best_diff = G_MAXDOUBLE;
gboolean res = FALSE;
g_value_init (&best_diff, GST_TYPE_FRACTION); target = (gdouble) target_numerator / (gdouble) target_denominator;
g_value_init (&cur_diff, GST_TYPE_FRACTION);
g_value_init (&target, GST_TYPE_FRACTION);
gst_value_set_fraction (&target, target_numerator, target_denominator); GST_DEBUG ("target %g, best %g", target, best_diff);
best = NULL; best = NULL;
@ -2249,28 +2246,32 @@ gst_structure_fixate_field_nearest_fraction (GstStructure * structure,
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
list_value = gst_value_list_get_value (value, i); list_value = gst_value_list_get_value (value, i);
if (G_VALUE_TYPE (list_value) == GST_TYPE_FRACTION) { if (G_VALUE_TYPE (list_value) == GST_TYPE_FRACTION) {
gint num, denom;
gdouble list_double;
if (gst_value_compare (list_value, &target) == GST_VALUE_LESS_THAN) num = gst_value_get_fraction_numerator (list_value);
gst_value_fraction_subtract (&cur_diff, &target, list_value); denom = gst_value_get_fraction_denominator (list_value);
else
gst_value_fraction_subtract (&cur_diff, list_value, &target);
if (!best list_double = ((gdouble) num / (gdouble) denom);
|| gst_value_compare (&cur_diff, cur_diff = target - list_double;
&best_diff) == GST_VALUE_LESS_THAN) {
GST_DEBUG ("curr diff %g, list %g", cur_diff, list_double);
if (cur_diff < 0)
cur_diff = -cur_diff;
if (!best || cur_diff < best_diff) {
GST_DEBUG ("new best %g", list_double);
best = list_value; best = list_value;
g_value_copy (&cur_diff, &best_diff); best_diff = cur_diff;
} }
} }
} }
if (best != NULL) { if (best != NULL) {
gst_structure_set_value (structure, field_name, best); gst_structure_set_value (structure, field_name, best);
res = TRUE; return TRUE;
} }
g_value_unset (&best_diff);
g_value_unset (&cur_diff);
g_value_unset (&target);
return res;
} }
return FALSE; return FALSE;
} }

View file

@ -294,7 +294,7 @@ GST_END_TEST;
GST_START_TEST (test_fixate_frac_list) GST_START_TEST (test_fixate_frac_list)
{ {
GstStructure *s; GstStructure *s, *s2;
GValue list = { 0 }; GValue list = { 0 };
GValue frac = { 0 }; GValue frac = { 0 };
gchar *str; gchar *str;
@ -319,6 +319,9 @@ GST_START_TEST (test_fixate_frac_list)
GST_DEBUG ("list %s", str); GST_DEBUG ("list %s", str);
g_free (str); g_free (str);
/* take copy */
s2 = gst_structure_copy (s);
/* fixate to the nearest fraction, this should give 15/1 */ /* fixate to the nearest fraction, this should give 15/1 */
fail_unless (gst_structure_fixate_field_nearest_fraction (s, "frac", 14, 1)); fail_unless (gst_structure_fixate_field_nearest_fraction (s, "frac", 14, 1));
@ -327,6 +330,16 @@ GST_START_TEST (test_fixate_frac_list)
fail_unless (denom == 1); fail_unless (denom == 1);
gst_structure_free (s); gst_structure_free (s);
s = s2;
/* fixate to the nearest fraction, this should give 30/1 */
fail_unless (gst_structure_fixate_field_nearest_fraction (s, "frac", G_MAXINT,
1));
fail_unless (gst_structure_get_fraction (s, "frac", &num, &denom));
fail_unless (num == 30);
fail_unless (denom == 1);
gst_structure_free (s);
} }
GST_END_TEST; GST_END_TEST;