From 13eb1002aefcf0e42280ddd5cf8fd3b87dcb8975 Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Thu, 1 Feb 2024 17:23:33 +0100 Subject: [PATCH] refactor(linux): Deal with invalid version numbers --- linux/ibus-keyman/src/keymanutil.c | 52 ++++++++++++------- linux/ibus-keyman/src/test/keymanutil_tests.c | 12 +++++ 2 files changed, 45 insertions(+), 19 deletions(-) diff --git a/linux/ibus-keyman/src/keymanutil.c b/linux/ibus-keyman/src/keymanutil.c index 2921be4030..26bfcf1d55 100644 --- a/linux/ibus-keyman/src/keymanutil.c +++ b/linux/ibus-keyman/src/keymanutil.c @@ -212,27 +212,41 @@ get_engine_for_language( return engine_desc; } -int -keyman_compare_version(const gchar *version1str, const gchar *version2str) { - size_t len1 = strlen(version1str); - size_t len2 = strlen(version2str); - for (size_t i = 0, j = 0; i < len1 || j < len2; i++, j++) { - int version1 = 0, version2 = 0; +int _get_version(const gchar **pver) { + g_assert(pver); + const gchar *ver = *pver; + int version = 0; - while (i < len1 && version1str[i] != '.') { - version1 = version1 * 10 + (version1str[i] - '0'); - i++; - } - while (j < len2 && version2str[j] != '.') { - version2 = version2 * 10 + (version2str[j] - '0'); - j++; - } - - if (version1 < version2) - return -1; - if (version1 > version2) - return +1; + while (*ver && *ver != '.') { + if (*ver >= '0' && *ver <= '9') { + version = version * 10 + (*ver - '0'); + ver++; + } else { + // stop comparison on first non-digit + while (*ver) + ver++; } + } + *pver = ver; + return version; +} + +int +keyman_compare_version(const gchar *ver1, const gchar *ver2) { + for (; *ver1 || *ver2; ) { + int version1 = _get_version(&ver1); + int version2 = _get_version(&ver2); + + if (version1 < version2) + return -1; + if (version1 > version2) + return +1; + + if (*ver1) + ver1++; + if (*ver2) + ver2++; + } return 0; } diff --git a/linux/ibus-keyman/src/test/keymanutil_tests.c b/linux/ibus-keyman/src/test/keymanutil_tests.c index 5779cff18b..17e89ed2a6 100644 --- a/linux/ibus-keyman/src/test/keymanutil_tests.c +++ b/linux/ibus-keyman/src/test/keymanutil_tests.c @@ -1043,6 +1043,16 @@ test_keyman_compare_version_equal_with_patch() { g_assert_cmpint(keyman_compare_version("1.0", "1.0.0"), ==, 0); } +void +test_keyman_compare_version_equal_nondigit() { + g_assert_cmpint(keyman_compare_version("1.1", "1.1-beta2"), ==, 0); +} + +void +test_keyman_compare_version_equal_doubledot() { + g_assert_cmpint(keyman_compare_version("1..2", "1.0.2"), ==, 0); +} + void test_keyman_compare_version_less() { g_assert_cmpint(keyman_compare_version("1.0", "1.1"), <, 0); @@ -1162,6 +1172,8 @@ int main(int argc, char* argv[]) { g_test_add_func("/keymanutil/keyman_compare_version/1.0==1.0", test_keyman_compare_version_equal); g_test_add_func("/keymanutil/keyman_compare_version/1.0==1.0.0", test_keyman_compare_version_equal_with_patch); + g_test_add_func("/keymanutil/keyman_compare_version/1.1==1.1-beta", test_keyman_compare_version_equal_nondigit); + g_test_add_func("/keymanutil/keyman_compare_version/1..2==1.0.2", test_keyman_compare_version_equal_doubledot); g_test_add_func("/keymanutil/keyman_compare_version/1.0<1.1", test_keyman_compare_version_less); g_test_add_func("/keymanutil/keyman_compare_version/1.0.1<1.1", test_keyman_compare_version_minor_less_with_patch); g_test_add_func("/keymanutil/keyman_compare_version/1.0<1.0.1", test_keyman_compare_version_patch_less);