diff --git a/ModemManager.spec b/ModemManager.spec index 3861a13..a0ae9ef 100644 --- a/ModemManager.spec +++ b/ModemManager.spec @@ -4,7 +4,7 @@ Summary: Mobile broadband modem management service Name: ModemManager Version: 0.6.0.0 -Release: 1%{snapshot}%{?dist} +Release: 2%{snapshot}%{?dist} # # Source from git://anongit.freedesktop.org/ModemManager/ModemManager # tarball built with: @@ -30,6 +30,9 @@ BuildRequires: libxslt Patch0: buildsys-hates-openpty.patch +Patch1: rh862341-1-UCS2-conversions.patch +Patch2: rh862341-2-parse_operator.patch + %description The ModemManager service provides a consistent API to operate many different modems, including mobile broadband (3G) devices. @@ -37,6 +40,8 @@ modems, including mobile broadband (3G) devices. %prep %setup -q %patch0 -p1 -b .pty +%patch1 -p1 -b .UCS2-conversion +%patch2 -p1 -b .parse-operator %build @@ -90,6 +95,9 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor >&/dev/null || : %{_datadir}/dbus-1/interfaces/*.xml %changelog +* Tue Nov 27 2012 Jiří Klimeš - 0.6.0.0-2 +- core: fix a crash in g_utf8_validate() (rh #862341) + * Tue Sep 4 2012 Dan Williams - 0.6.0.0-1 - Update to 0.6.0 - core: fix SMS notifications on many Qualcomm devices diff --git a/rh862341-1-UCS2-conversions.patch b/rh862341-1-UCS2-conversions.patch new file mode 100644 index 0000000..c2d196e --- /dev/null +++ b/rh862341-1-UCS2-conversions.patch @@ -0,0 +1,160 @@ +commit e07c2162d66ab1a2e938db48744fc00afd29c272 +Author: Dan Williams +Date: Tue Sep 11 16:36:16 2012 -0500 + + core: better handling of non-UCS2 conversions that should be UCS2 (bgo #683817) + + Some modems return the +COPS operator name in hex-encoded current + character set (as set with +CSCS). Others return the operator name + in ASCII when set to UCS2, while yet others return the ASCII name + with trash at the end (*cough* Huawei *cough*). Handle that better + by not crashing. + +diff --git a/src/mm-charsets.c b/src/mm-charsets.c +index 68bf2d1..65fc33c 100644 +--- a/src/mm-charsets.c ++++ b/src/mm-charsets.c +@@ -710,8 +710,7 @@ gsm_pack (const guint8 *src, + * the hex representation of the charset-encoded string, so we need to cope with + * that case. */ + gchar * +-mm_charset_take_and_convert_to_utf8 (gchar *str, +- MMModemCharset charset) ++mm_charset_take_and_convert_to_utf8 (gchar *str, MMModemCharset charset) + { + gchar *utf8 = NULL; + +@@ -752,6 +751,7 @@ mm_charset_take_and_convert_to_utf8 (gchar *str, + case MM_MODEM_CHARSET_UCS2: { + gsize len; + gboolean possibly_hex = TRUE; ++ gsize bread = 0, bwritten = 0; + + /* If the string comes in hex-UCS-2, len needs to be a multiple of 4 */ + len = strlen (str); +@@ -765,19 +765,37 @@ mm_charset_take_and_convert_to_utf8 (gchar *str, + possibly_hex = isxdigit (*p++); + } + +- /* If we get UCS-2, we expect the HEX representation of the string */ ++ /* If hex, then we expect hex-encoded UCS-2 */ + if (possibly_hex) { + utf8 = mm_modem_charset_hex_to_utf8 (str, charset); +- if (!utf8) { +- /* If we couldn't convert the string as HEX-UCS-2, try to see if +- * the string is valid UTF-8 itself. */ +- utf8 = str; +- } else ++ if (utf8) { + g_free (str); +- } else +- /* If we already know it's not hex, try to use the string as it is */ +- utf8 = str; ++ break; ++ } ++ } ++ ++ /* If not hex, then it might be raw UCS-2 (very unlikely) or ASCII/UTF-8 ++ * (much more likely). Try to convert to UTF-8 and if that fails, use ++ * the partial conversion length to re-convert the part of the string ++ * that is UTF-8, if any. ++ */ ++ utf8 = g_convert (str, strlen (str), ++ "UTF-8//TRANSLIT", "UTF-8//TRANSLIT", ++ &bread, &bwritten, NULL); + ++ /* Valid conversion, or we didn't get enough valid UTF-8 */ ++ if (utf8 || (bwritten <= 2)) { ++ g_free (str); ++ break; ++ } ++ ++ /* Last try; chop off the original string at the conversion failure ++ * location and get what we can. ++ */ ++ str[bread] = '\0'; ++ utf8 = g_convert (str, strlen (str), ++ "UTF-8//TRANSLIT", "UTF-8//TRANSLIT", ++ NULL, NULL, NULL); + break; + } + +@@ -791,7 +809,7 @@ mm_charset_take_and_convert_to_utf8 (gchar *str, + + /* Validate UTF-8 always before returning. This result will be exposed in DBus + * very likely... */ +- if (!g_utf8_validate (utf8, -1, NULL)) { ++ if (utf8 && !g_utf8_validate (utf8, -1, NULL)) { + /* Better return NULL than an invalid UTF-8 string */ + g_free (utf8); + utf8 = NULL; +diff --git a/src/mm-charsets.h b/src/mm-charsets.h +index 855387a..96435cc 100644 +--- a/src/mm-charsets.h ++++ b/src/mm-charsets.h +@@ -72,7 +72,6 @@ guint8 *gsm_pack (const guint8 *src, + guint8 start_offset, /* in bits */ + guint32 *out_packed_len); + +-gchar *mm_charset_take_and_convert_to_utf8 (gchar *str, +- MMModemCharset charset); ++gchar *mm_charset_take_and_convert_to_utf8 (gchar *str, MMModemCharset charset); + + #endif /* MM_CHARSETS_H */ +diff --git a/src/tests/test-charsets.c b/src/tests/test-charsets.c +index f954d93..ced38a6 100644 +--- a/src/tests/test-charsets.c ++++ b/src/tests/test-charsets.c +@@ -326,6 +326,41 @@ test_pack_gsm7_7_chars_offset (void *f, gpointer d) + g_free (packed); + } + ++static void ++test_take_convert_ucs2_hex_utf8 (void *f, gpointer d) ++{ ++ gchar *src, *converted; ++ ++ /* Ensure hex-encoded UCS-2 works */ ++ src = g_strdup ("0054002d004d006f00620069006c0065"); ++ converted = mm_charset_take_and_convert_to_utf8 (src, MM_MODEM_CHARSET_UCS2); ++ g_assert_cmpstr (converted, ==, "T-Mobile"); ++ g_free (converted); ++} ++ ++static void ++test_take_convert_ucs2_bad_ascii (void *f, gpointer d) ++{ ++ gchar *src, *converted; ++ ++ /* Test that something mostly ASCII returns most of the original string */ ++ src = g_strdup ("Orange\241"); ++ converted = mm_charset_take_and_convert_to_utf8 (src, MM_MODEM_CHARSET_UCS2); ++ g_assert_cmpstr (converted, ==, "Orange"); ++ g_free (converted); ++} ++ ++static void ++test_take_convert_ucs2_bad_ascii2 (void *f, gpointer d) ++{ ++ gchar *src, *converted; ++ ++ /* Ensure something completely screwed up doesn't crash */ ++ src = g_strdup ("\241\255\254\250\244\234"); ++ converted = mm_charset_take_and_convert_to_utf8 (src, MM_MODEM_CHARSET_UCS2); ++ g_assert (converted == NULL); ++} ++ + + #if GLIB_CHECK_VERSION(2,25,12) + typedef GTestFixtureFunc TCFunc; +@@ -360,6 +395,10 @@ int main (int argc, char **argv) + + g_test_suite_add (suite, TESTCASE (test_pack_gsm7_7_chars_offset, NULL)); + ++ g_test_suite_add (suite, TESTCASE (test_take_convert_ucs2_hex_utf8, NULL)); ++ g_test_suite_add (suite, TESTCASE (test_take_convert_ucs2_bad_ascii, NULL)); ++ g_test_suite_add (suite, TESTCASE (test_take_convert_ucs2_bad_ascii2, NULL)); ++ + result = g_test_run (); + + return result; diff --git a/rh862341-2-parse_operator.patch b/rh862341-2-parse_operator.patch new file mode 100644 index 0000000..b98c2e6 --- /dev/null +++ b/rh862341-2-parse_operator.patch @@ -0,0 +1,38 @@ +commit 219424a6e2d017491a05ecbed661bccde3f991ef +Author: Aleksander Morgado +Date: Wed Sep 12 07:34:37 2012 +0200 + + gsm: skip additional UTF-8 validity check when parsing operator + + This is a fix related to the previous e07c2162d. + + mm_charset_take_and_convert_to_utf8() already does a UTF-8 validity check + internally before returning the string, so it's pointless to do a new one + on the returned string. + + Plus, mm_charset_take_and_convert_to_utf8() may really return NULL, which + would end up in segfaulting as g_utf8_validate() expects always a non-NULL + string. + +diff --git a/src/mm-generic-gsm.c b/src/mm-generic-gsm.c +index 83e4083..60f2ea1 100644 +--- a/src/mm-generic-gsm.c ++++ b/src/mm-generic-gsm.c +@@ -3066,13 +3066,14 @@ parse_operator (const char *reply, MMModemCharset cur_charset) + * string of the bytes of the operator name as encoded by the current + * character set. + */ +- if (cur_charset == MM_MODEM_CHARSET_UCS2) ++ if (cur_charset == MM_MODEM_CHARSET_UCS2) { ++ /* In this case we're already checking UTF-8 validity */ + operator = mm_charset_take_and_convert_to_utf8 (operator, MM_MODEM_CHARSET_UCS2); +- ++ } + /* Ensure the operator name is valid UTF-8 so that we can send it + * through D-Bus and such. + */ +- if (!g_utf8_validate (operator, -1, NULL)) { ++ else if (!g_utf8_validate (operator, -1, NULL)) { + g_free (operator); + operator = NULL; + }