diff --git a/ChangeLog b/ChangeLog index 5fcde55e6e..a79daab233 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2005-06-23 Thomas Vander Stichele + + * check/gst/gstvalue.c: (START_TEST), (gst_value_suite): + * gst/gstvalue.c: (gst_value_deserialize_int_helper): + remove gst_strtoll completely, since it didn't actually do + anything more than what g_ascii_strtoull already does. + check for range errors when deserializing + do a cast for the unsigned cases; but further fixing needs + a decision on what the interpretation of "(int)" and + deserialization should be for values that fall outside the + type's boundaries (ie, refuse, or interpret as casting) + 2005-06-23 Wim Taymans * check/Makefile.am: diff --git a/check/gst/gstvalue.c b/check/gst/gstvalue.c index f8dad4c69a..29bbc889a4 100644 --- a/check/gst/gstvalue.c +++ b/check/gst/gstvalue.c @@ -64,7 +64,6 @@ START_TEST (test_deserialize_gint) { GValue value = { 0 }; const char *strings[] = { - "-", "123456", "-123456", "0xFFFF", @@ -78,12 +77,13 @@ START_TEST (test_deserialize_gint) "0xFF000000", /* a positive long long serializing to -1 */ "0xFFFFFFFF", + "0xFFFFFFFF", /* a negative long long serializing to -1 */ "0xFFFFFFFFFFFFFFFF", + "0xFFFFFFFFFFFFFFFF", "0xEFFFFFFF", }; gint results[] = { - 0, 123456, -123456, 0xFFFF, @@ -93,7 +93,10 @@ START_TEST (test_deserialize_gint) 0x80000000, 0xFF000000, -1, + 0xFFFFFFFF, -1, + /* cast needs to be explicit because of unsigned -> signed */ + (gint) 0xFFFFFFFFFFFFFFFFLL, 0xEFFFFFFF, }; int i; @@ -115,10 +118,15 @@ START_TEST (test_deserialize_gint_failures) { GValue value = { 0 }; const char *strings[] = { + "-", /* not a complete number */ + "- TEST", /* not a complete number */ "0x0000000100000000", /* lowest long long that cannot fit in 32 bits */ "0xF000000000000000", "0xFFFFFFF000000000", "0xFFFFFFFF00000000", + "0x10000000000000000", /* first number too long to fit into a long long */ + /* invent a new processor first before trying to make this one pass */ + "0x10000000000000000000000000000000000000000000", }; int i; @@ -132,6 +140,91 @@ START_TEST (test_deserialize_gint_failures) END_TEST; +START_TEST (test_deserialize_guint) +{ + GValue value = { 0 }; + const char *strings[] = { + "123456", + "-123456", + "0xFFFF", + "0x0000FFFF", + /* a positive long long, serializing to highest possible positive sint */ + "0x7FFFFFFF", + /* a positive long long, serializing to lowest possible negative sint */ + "0x80000000", + "2147483648", + /* a negative long long, serializing to lowest possible negative sint */ + "0xFFFFFFFF80000000", + /* a value typically used for rgb masks */ + "0xFF000000", + /* a positive long long serializing to highest possible positive uint */ + "0xFFFFFFFF", + "0xFFFFFFFF", + /* a negative long long serializing to highest possible positive uint */ + "0xFFFFFFFFFFFFFFFF", + "0xEFFFFFFF", + }; + guint results[] = { + 123456, + -123456, + 0xFFFF, + 0xFFFF, + 0x7FFFFFFF, + 0x80000000, + (guint) 2147483648LL, + 0x80000000, + 0xFF000000, + 0xFFFFFFFF, + G_MAXUINT, + (guint) 0xFFFFFFFFFFFFFFFFLL, + 0xEFFFFFFF, + }; + int i; + + g_value_init (&value, G_TYPE_UINT); + + for (i = 0; i < G_N_ELEMENTS (strings); ++i) { + fail_unless (gst_value_deserialize (&value, strings[i]), + "could not deserialize %s (%d)", strings[i], i); + fail_unless (g_value_get_uint (&value) == results[i], + "resulting value is %d, not %d, for string %s (%d)", + g_value_get_uint (&value), results[i], strings[i], i); + } +} + +END_TEST; + +START_TEST (test_deserialize_guint_failures) +{ + GValue value = { 0 }; + const char *strings[] = { + "-", /* not a complete number */ + "- TEST", /* not a complete number */ +#if 0 +/* FIXME: these values should not be deserializable, since they overflow + * the target format */ + "0x0000000100000000", /* lowest long long that cannot fit in 32 bits */ + "0xF000000000000000", + "0xFFFFFFF000000000", + "0xFFFFFFFF00000000", + "0x10000000000000000", /* first number too long to fit into a long long */ + /* invent a new processor first before trying to make this one pass */ + "0x10000000000000000000000000000000000000000000", +#endif + }; + int i; + + g_value_init (&value, G_TYPE_UINT); + + for (i = 0; i < G_N_ELEMENTS (strings); ++i) { + fail_if (gst_value_deserialize (&value, strings[i]), + "deserialized %s (%d), while it should have failed", strings[i], i); + } +} + +END_TEST; + + START_TEST (test_string) { gchar *try[] = { @@ -221,6 +314,8 @@ gst_value_suite (void) tcase_add_test (tc_chain, test_deserialize_buffer); tcase_add_test (tc_chain, test_deserialize_gint); tcase_add_test (tc_chain, test_deserialize_gint_failures); + tcase_add_test (tc_chain, test_deserialize_guint); + tcase_add_test (tc_chain, test_deserialize_guint_failures); tcase_add_test (tc_chain, test_deserialize_gint64); tcase_add_test (tc_chain, test_string); tcase_add_test (tc_chain, test_deserialize_string); diff --git a/gst/gstvalue.c b/gst/gstvalue.c index 34c0c84604..3451df134c 100644 --- a/gst/gstvalue.c +++ b/gst/gstvalue.c @@ -980,46 +980,29 @@ gst_value_deserialize_boolean (GValue * dest, const char *s) return ret; } -/******* - * int * - *******/ - -static long long -gst_strtoll (const char *s, char **end, int base) -{ - long long i; - - if (s[0] == '-') { - i = -(long long) g_ascii_strtoull (s + 1, end, base); - } else { - i = g_ascii_strtoull (s, end, base); - } - - return i; -} - -#define CREATE_SERIALIZATION_START(_type,_macro) \ -static gint \ -gst_value_compare_ ## _type (const GValue * value1, const GValue * value2) \ -{ \ - g ## _type val1 = g_value_get_ ## _type (value1); \ - g ## _type val2 = g_value_get_ ## _type (value2); \ - if (val1 > val2) \ - return GST_VALUE_GREATER_THAN; \ - if (val1 < val2) \ - return GST_VALUE_LESS_THAN; \ - return GST_VALUE_EQUAL; \ -} \ -\ -static char * \ -gst_value_serialize_ ## _type (const GValue * value) \ -{ \ - GValue val = { 0, }; \ - g_value_init (&val, G_TYPE_STRING); \ - if (!g_value_transform (value, &val)) \ - g_assert_not_reached (); \ - /* NO_COPY_MADNESS!!! */ \ - return (char *) g_value_get_string (&val); \ +#define CREATE_SERIALIZATION_START(_type,_macro) \ +static gint \ +gst_value_compare_ ## _type \ +(const GValue * value1, const GValue * value2) \ +{ \ + g ## _type val1 = g_value_get_ ## _type (value1); \ + g ## _type val2 = g_value_get_ ## _type (value2); \ + if (val1 > val2) \ + return GST_VALUE_GREATER_THAN; \ + if (val1 < val2) \ + return GST_VALUE_LESS_THAN; \ + return GST_VALUE_EQUAL; \ +} \ + \ +static char * \ +gst_value_serialize_ ## _type (const GValue * value) \ +{ \ + GValue val = { 0, }; \ + g_value_init (&val, G_TYPE_STRING); \ + if (!g_value_transform (value, &val)) \ + g_assert_not_reached (); \ + /* NO_COPY_MADNESS!!! */ \ + return (char *) g_value_get_string (&val); \ } /* deserialize the given s into to as a long long. @@ -1027,14 +1010,20 @@ gst_value_serialize_ ## _type (const GValue * value) \ * bytes. */ static gboolean -gst_value_deserialize_int_helper (long long *to, const char *s, long long min, - long long max, int size) +gst_value_deserialize_int_helper (long long *to, const char *s, + long long min, long long max, int size) { gboolean ret = FALSE; char *end; long long mask = -1; - *to = gst_strtoll (s, &end, 0); + errno = 0; + *to = g_ascii_strtoull (s, &end, 0); + /* a range error is a definitive no-no */ + if (errno == ERANGE) { + return FALSE; + } + if (*end == 0) { ret = TRUE; } else { @@ -1101,11 +1090,18 @@ CREATE_SERIALIZATION_START(_type,_macro) \ static gboolean \ gst_value_deserialize_ ## _type (GValue * dest, const char *s) \ { \ - unsigned long long x; \ + guint64 x; \ char *end; \ gboolean ret = FALSE; \ \ + errno = 0; \ x = g_ascii_strtoull (s, &end, 0); \ + /* a range error is a definitive no-no */ \ + if (errno == ERANGE) { \ + return FALSE; \ + } \ + /* the cast ensures the range check later on makes sense */ \ + x = (g ## _type) x; \ if (*end == 0) { \ ret = TRUE; \ } else { \ diff --git a/tests/check/gst/gstvalue.c b/tests/check/gst/gstvalue.c index f8dad4c69a..29bbc889a4 100644 --- a/tests/check/gst/gstvalue.c +++ b/tests/check/gst/gstvalue.c @@ -64,7 +64,6 @@ START_TEST (test_deserialize_gint) { GValue value = { 0 }; const char *strings[] = { - "-", "123456", "-123456", "0xFFFF", @@ -78,12 +77,13 @@ START_TEST (test_deserialize_gint) "0xFF000000", /* a positive long long serializing to -1 */ "0xFFFFFFFF", + "0xFFFFFFFF", /* a negative long long serializing to -1 */ "0xFFFFFFFFFFFFFFFF", + "0xFFFFFFFFFFFFFFFF", "0xEFFFFFFF", }; gint results[] = { - 0, 123456, -123456, 0xFFFF, @@ -93,7 +93,10 @@ START_TEST (test_deserialize_gint) 0x80000000, 0xFF000000, -1, + 0xFFFFFFFF, -1, + /* cast needs to be explicit because of unsigned -> signed */ + (gint) 0xFFFFFFFFFFFFFFFFLL, 0xEFFFFFFF, }; int i; @@ -115,10 +118,15 @@ START_TEST (test_deserialize_gint_failures) { GValue value = { 0 }; const char *strings[] = { + "-", /* not a complete number */ + "- TEST", /* not a complete number */ "0x0000000100000000", /* lowest long long that cannot fit in 32 bits */ "0xF000000000000000", "0xFFFFFFF000000000", "0xFFFFFFFF00000000", + "0x10000000000000000", /* first number too long to fit into a long long */ + /* invent a new processor first before trying to make this one pass */ + "0x10000000000000000000000000000000000000000000", }; int i; @@ -132,6 +140,91 @@ START_TEST (test_deserialize_gint_failures) END_TEST; +START_TEST (test_deserialize_guint) +{ + GValue value = { 0 }; + const char *strings[] = { + "123456", + "-123456", + "0xFFFF", + "0x0000FFFF", + /* a positive long long, serializing to highest possible positive sint */ + "0x7FFFFFFF", + /* a positive long long, serializing to lowest possible negative sint */ + "0x80000000", + "2147483648", + /* a negative long long, serializing to lowest possible negative sint */ + "0xFFFFFFFF80000000", + /* a value typically used for rgb masks */ + "0xFF000000", + /* a positive long long serializing to highest possible positive uint */ + "0xFFFFFFFF", + "0xFFFFFFFF", + /* a negative long long serializing to highest possible positive uint */ + "0xFFFFFFFFFFFFFFFF", + "0xEFFFFFFF", + }; + guint results[] = { + 123456, + -123456, + 0xFFFF, + 0xFFFF, + 0x7FFFFFFF, + 0x80000000, + (guint) 2147483648LL, + 0x80000000, + 0xFF000000, + 0xFFFFFFFF, + G_MAXUINT, + (guint) 0xFFFFFFFFFFFFFFFFLL, + 0xEFFFFFFF, + }; + int i; + + g_value_init (&value, G_TYPE_UINT); + + for (i = 0; i < G_N_ELEMENTS (strings); ++i) { + fail_unless (gst_value_deserialize (&value, strings[i]), + "could not deserialize %s (%d)", strings[i], i); + fail_unless (g_value_get_uint (&value) == results[i], + "resulting value is %d, not %d, for string %s (%d)", + g_value_get_uint (&value), results[i], strings[i], i); + } +} + +END_TEST; + +START_TEST (test_deserialize_guint_failures) +{ + GValue value = { 0 }; + const char *strings[] = { + "-", /* not a complete number */ + "- TEST", /* not a complete number */ +#if 0 +/* FIXME: these values should not be deserializable, since they overflow + * the target format */ + "0x0000000100000000", /* lowest long long that cannot fit in 32 bits */ + "0xF000000000000000", + "0xFFFFFFF000000000", + "0xFFFFFFFF00000000", + "0x10000000000000000", /* first number too long to fit into a long long */ + /* invent a new processor first before trying to make this one pass */ + "0x10000000000000000000000000000000000000000000", +#endif + }; + int i; + + g_value_init (&value, G_TYPE_UINT); + + for (i = 0; i < G_N_ELEMENTS (strings); ++i) { + fail_if (gst_value_deserialize (&value, strings[i]), + "deserialized %s (%d), while it should have failed", strings[i], i); + } +} + +END_TEST; + + START_TEST (test_string) { gchar *try[] = { @@ -221,6 +314,8 @@ gst_value_suite (void) tcase_add_test (tc_chain, test_deserialize_buffer); tcase_add_test (tc_chain, test_deserialize_gint); tcase_add_test (tc_chain, test_deserialize_gint_failures); + tcase_add_test (tc_chain, test_deserialize_guint); + tcase_add_test (tc_chain, test_deserialize_guint_failures); tcase_add_test (tc_chain, test_deserialize_gint64); tcase_add_test (tc_chain, test_string); tcase_add_test (tc_chain, test_deserialize_string);