version comparisons: stop using locale-dependent isdigit()
The docs are not entirely clear what glyphs qualify as digits. The function is supposed to be locale-dependent, but I couldn't get it to return true on any non-ascii digits I tried. But it's better to be safe than sorry, let's use our trivial replacement instead.
This commit is contained in:
@@ -77,19 +77,18 @@ sd_char* endswith_no_case(const sd_char *s, const sd_char *postfix) {
|
||||
return (sd_char*) s + sl - pl;
|
||||
}
|
||||
|
||||
#ifdef SD_BOOT
|
||||
static sd_bool isdigit(sd_char a) {
|
||||
static sd_bool is_digit(sd_char a) {
|
||||
/* Locale-independent version of isdigit(). */
|
||||
return a >= '0' && a <= '9';
|
||||
}
|
||||
#endif
|
||||
|
||||
static sd_bool is_alpha(sd_char a) {
|
||||
/* Locale independent version of isalpha(). */
|
||||
/* Locale-independent version of isalpha(). */
|
||||
return (a >= 'a' && a <= 'z') || (a >= 'A' && a <= 'Z');
|
||||
}
|
||||
|
||||
static sd_bool is_valid_version_char(sd_char a) {
|
||||
return isdigit(a) || is_alpha(a) || IN_SET(a, '~', '-', '^', '.');
|
||||
return is_digit(a) || is_alpha(a) || IN_SET(a, '~', '-', '^', '.');
|
||||
}
|
||||
|
||||
sd_int strverscmp_improved(const sd_char *a, const sd_char *b) {
|
||||
@@ -187,7 +186,7 @@ sd_int strverscmp_improved(const sd_char *a, const sd_char *b) {
|
||||
b++;
|
||||
}
|
||||
|
||||
if (isdigit(*a) || isdigit(*b)) {
|
||||
if (is_digit(*a) || is_digit(*b)) {
|
||||
/* Skip leading '0', to make 00123 equivalent to 123. */
|
||||
while (*a == '0')
|
||||
a++;
|
||||
@@ -196,9 +195,9 @@ sd_int strverscmp_improved(const sd_char *a, const sd_char *b) {
|
||||
|
||||
/* Find the leading numeric segments. One may be an empty string. So,
|
||||
* numeric segments are always newer than alpha segments. */
|
||||
for (aa = a; isdigit(*aa); aa++)
|
||||
for (aa = a; is_digit(*aa); aa++)
|
||||
;
|
||||
for (bb = b; isdigit(*bb); bb++)
|
||||
for (bb = b; is_digit(*bb); bb++)
|
||||
;
|
||||
|
||||
/* To compare numeric segments without parsing their values, first compare the
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "locale-util.h"
|
||||
#include "macro.h"
|
||||
@@ -914,6 +916,13 @@ TEST(strverscmp_improved) {
|
||||
|
||||
/* invalid characters */
|
||||
assert_se(strverscmp_improved("123_aa2-67.89", "123aa+2-67.89") == 0);
|
||||
|
||||
/* non-ASCII digits */
|
||||
(void) setlocale(LC_NUMERIC, "ar_YE.utf8");
|
||||
assert_se(strverscmp_improved("1٠١٢٣٤٥٦٧٨٩", "1") == 0);
|
||||
|
||||
(void) setlocale(LC_NUMERIC, "th_TH.utf8");
|
||||
assert_se(strverscmp_improved("1๐๑๒๓๔๕๖๗๘๙", "1") == 0);
|
||||
}
|
||||
|
||||
#define RPMVERCMP(a, b, c) \
|
||||
|
||||
Reference in New Issue
Block a user