libnm: move _nm_utils_ascii_str_to_int64() from src/ to libnm-core/

(cherry picked from commit c5d23737fd)
This commit is contained in:
Thomas Haller 2015-02-22 11:54:03 +01:00
parent a4d11bae29
commit ba285e319e
11 changed files with 219 additions and 209 deletions

View file

@ -136,4 +136,6 @@ GByteArray *nm_utils_rsa_key_encrypt (const guint8 *data,
int nm_utils_bond_mode_string_to_int (const char *mode);
const char *nm_utils_bond_mode_int_to_string (int mode);
gint64 _nm_utils_ascii_str_to_int64 (const char *str, guint base, gint64 min, gint64 max, gint64 fallback);
#endif

View file

@ -22,6 +22,7 @@
#include "config.h"
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <netinet/ether.h>
#include <arpa/inet.h>
@ -3278,3 +3279,81 @@ nm_utils_bond_mode_string_to_int (const char *mode)
}
return -1;
}
/**********************************************************************************************/
/* _nm_utils_ascii_str_to_int64:
*
* A wrapper for g_ascii_strtoll, that checks whether the whole string
* can be successfully converted to a number and is within a given
* range. On any error, @fallback will be returned and %errno will be set
* to a non-zero value. On success, %errno will be set to zero, check %errno
* for errors. Any trailing or leading (ascii) white space is ignored and the
* functions is locale independent.
*
* The function is guaranteed to return a value between @min and @max
* (inclusive) or @fallback. Also, the parsing is rather strict, it does
* not allow for any unrecognized characters, except leading and trailing
* white space.
**/
gint64
_nm_utils_ascii_str_to_int64 (const char *str, guint base, gint64 min, gint64 max, gint64 fallback)
{
gint64 v;
size_t len;
char buf[64], *s, *str_free = NULL;
if (str) {
while (g_ascii_isspace (str[0]))
str++;
}
if (!str || !str[0]) {
errno = EINVAL;
return fallback;
}
len = strlen (str);
if (g_ascii_isspace (str[--len])) {
/* backward search the first non-ws character.
* We already know that str[0] is non-ws. */
while (g_ascii_isspace (str[--len]))
;
/* str[len] is now the last non-ws character... */
len++;
if (len >= sizeof (buf))
s = str_free = g_malloc (len + 1);
else
s = buf;
memcpy (s, str, len);
s[len] = 0;
/*
g_assert (len > 0 && len < strlen (str) && len == strlen (s));
g_assert (!g_ascii_isspace (str[len-1]) && g_ascii_isspace (str[len]));
g_assert (strncmp (str, s, len) == 0);
*/
str = s;
}
errno = 0;
v = g_ascii_strtoll (str, &s, base);
if (errno != 0)
v = fallback;
else if (s[0] != 0) {
errno = EINVAL;
v = fallback;
} else if (v > max || v < min) {
errno = ERANGE;
v = fallback;
}
if (G_UNLIKELY (str_free))
g_free (str_free);
return v;
}

View file

@ -4040,6 +4040,137 @@ test_nm_utils_uuid_generate_from_string (void)
/******************************************************************************/
static void
test_nm_utils_ascii_str_to_int64_check (const char *str, guint base, gint64 min,
gint64 max, gint64 fallback, int exp_errno,
gint64 exp_val)
{
gint64 v;
errno = 1;
v = _nm_utils_ascii_str_to_int64 (str, base, min, max, fallback);
g_assert_cmpint (errno, ==, exp_errno);
g_assert_cmpint (v, ==, exp_val);
}
static void
test_nm_utils_ascii_str_to_int64_do (const char *str, guint base, gint64 min,
gint64 max, gint64 fallback, int exp_errno,
gint64 exp_val)
{
const char *sign = "";
const char *val;
static const char *whitespaces[] = {
"",
" ",
"\r\n\t",
" \r\n\t ",
" \r\n\t \t\r\n\t",
NULL,
};
static const char *nulls[] = {
"",
"0",
"00",
"0000",
"0000000000000000",
"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
NULL,
};
const char **ws_pre, **ws_post, **null;
guint i;
if (str == NULL || exp_errno != 0) {
test_nm_utils_ascii_str_to_int64_check (str, base, min, max, fallback, exp_errno, exp_val);
return;
}
if (strncmp (str, "-", 1) == 0)
sign = "-";
val = str + strlen (sign);
for (ws_pre = whitespaces; *ws_pre; ws_pre++) {
for (ws_post = whitespaces; *ws_post; ws_post++) {
for (null = nulls; *null; null++) {
for (i = 0; ; i++) {
char *s;
const char *str_base = "";
if (base == 16) {
if (i == 1)
str_base = "0x";
else if (i > 1)
break;
} else if (base == 8) {
if (i == 1)
str_base = "0";
else if (i > 1)
break;
} else if (base == 0) {
if (i > 0)
break;
/* with base==0, a leading zero would be interpreted as octal. Only test without *null */
if ((*null)[0])
break;
} else {
if (i > 0)
break;
}
s = g_strdup_printf ("%s%s%s%s%s%s", *ws_pre, sign, str_base, *null, val, *ws_post);
test_nm_utils_ascii_str_to_int64_check (s, base, min, max, fallback, exp_errno, exp_val);
g_free (s);
}
}
}
}
}
static void
test_nm_utils_ascii_str_to_int64 (void)
{
test_nm_utils_ascii_str_to_int64_do (NULL, 10, 0, 10000, -1, EINVAL, -1);
test_nm_utils_ascii_str_to_int64_do ("", 10, 0, 10000, -1, EINVAL, -1);
test_nm_utils_ascii_str_to_int64_do ("1x", 10, 0, 10000, -1, EINVAL, -1);
test_nm_utils_ascii_str_to_int64_do ("4711", 10, 0, 10000, -1, 0, 4711);
test_nm_utils_ascii_str_to_int64_do ("10000", 10, 0, 10000, -1, 0, 10000);
test_nm_utils_ascii_str_to_int64_do ("10001", 10, 0, 10000, -1, ERANGE, -1);
test_nm_utils_ascii_str_to_int64_do ("FF", 16, 0, 10000, -1, 0, 255);
test_nm_utils_ascii_str_to_int64_do ("FF", 10, 0, 10000, -2, EINVAL, -2);
test_nm_utils_ascii_str_to_int64_do ("9223372036854775807", 10, 0, G_MAXINT64, -2, 0, G_MAXINT64);
test_nm_utils_ascii_str_to_int64_do ("7FFFFFFFFFFFFFFF", 16, 0, G_MAXINT64, -2, 0, G_MAXINT64);
test_nm_utils_ascii_str_to_int64_do ("9223372036854775808", 10, 0, G_MAXINT64, -2, ERANGE, -2);
test_nm_utils_ascii_str_to_int64_do ("-9223372036854775808", 10, G_MININT64, 0, -2, 0, G_MININT64);
test_nm_utils_ascii_str_to_int64_do ("-9223372036854775808", 10, G_MININT64+1, 0, -2, ERANGE, -2);
test_nm_utils_ascii_str_to_int64_do ("-9223372036854775809", 10, G_MININT64, 0, -2, ERANGE, -2);
test_nm_utils_ascii_str_to_int64_do ("1.0", 10, 1, 1, -1, EINVAL, -1);
test_nm_utils_ascii_str_to_int64_do ("1x0", 16, -10, 10, -100, EINVAL, -100);
test_nm_utils_ascii_str_to_int64_do ("0", 16, -10, 10, -100, 0, 0);
test_nm_utils_ascii_str_to_int64_do ("10001111", 2, -1000, 1000, -100000, 0, 0x8F);
test_nm_utils_ascii_str_to_int64_do ("-10001111", 2, -1000, 1000, -100000, 0, -0x8F);
test_nm_utils_ascii_str_to_int64_do ("1111111", 2, G_MININT64, G_MAXINT64, -1, 0, 0x7F);
test_nm_utils_ascii_str_to_int64_do ("111111111111111", 2, G_MININT64, G_MAXINT64, -1, 0, 0x7FFF);
test_nm_utils_ascii_str_to_int64_do ("11111111111111111111111111111111111111111111111", 2, G_MININT64, G_MAXINT64, -1, 0, 0x7FFFFFFFFFFF);
test_nm_utils_ascii_str_to_int64_do ("111111111111111111111111111111111111111111111111111111111111111", 2, G_MININT64, G_MAXINT64, -1, 0, 0x7FFFFFFFFFFFFFFF);
test_nm_utils_ascii_str_to_int64_do ("100000000000000000000000000000000000000000000000000000000000000", 2, G_MININT64, G_MAXINT64, -1, 0, 0x4000000000000000);
test_nm_utils_ascii_str_to_int64_do ("1000000000000000000000000000000000000000000000000000000000000000", 2, G_MININT64, G_MAXINT64, -1, ERANGE, -1);
test_nm_utils_ascii_str_to_int64_do ("-100000000000000000000000000000000000000000000000000000000000000", 2, G_MININT64, G_MAXINT64, -1, 0, -0x4000000000000000);
test_nm_utils_ascii_str_to_int64_do ("111111111111111111111111111111111111111111111111111111111111111", 2, G_MININT64, G_MAXINT64, -1, 0, 0x7FFFFFFFFFFFFFFF);
test_nm_utils_ascii_str_to_int64_do ("-100000000000000000000000000000000000000000000000000000000000000", 2, G_MININT64, G_MAXINT64, -1, 0, -0x4000000000000000);
test_nm_utils_ascii_str_to_int64_do ("0x70", 10, G_MININT64, G_MAXINT64, -1, EINVAL, -1);
test_nm_utils_ascii_str_to_int64_do ("4711", 0, G_MININT64, G_MAXINT64, -1, 0, 4711);
test_nm_utils_ascii_str_to_int64_do ("04711", 0, G_MININT64, G_MAXINT64, -1, 0, 04711);
test_nm_utils_ascii_str_to_int64_do ("0x4711", 0, G_MININT64, G_MAXINT64, -1, 0, 0x4711);
test_nm_utils_ascii_str_to_int64_do ("080", 0, G_MININT64, G_MAXINT64, -1, EINVAL, -1);
test_nm_utils_ascii_str_to_int64_do ("070", 0, G_MININT64, G_MAXINT64, -1, 0, 7*8);
test_nm_utils_ascii_str_to_int64_do ("0x70", 0, G_MININT64, G_MAXINT64, -1, 0, 0x70);
}
/******************************************************************************/
NMTST_DEFINE ();
int main (int argc, char **argv)
@ -4138,6 +4269,8 @@ int main (int argc, char **argv)
g_test_add_func ("/core/general/hexstr2bin", test_hexstr2bin);
g_test_add_func ("/core/general/test_nm_utils_uuid_generate_from_string", test_nm_utils_uuid_generate_from_string);
g_test_add_func ("/core/general/_nm_utils_ascii_str_to_int64", test_nm_utils_ascii_str_to_int64);
return g_test_run ();
}

View file

@ -1803,81 +1803,6 @@ nm_utils_cmp_connection_by_autoconnect_priority (NMConnection **a, NMConnection
return 0;
}
/* _nm_utils_ascii_str_to_int64:
*
* A wrapper for g_ascii_strtoll, that checks whether the whole string
* can be successfully converted to a number and is within a given
* range. On any error, @fallback will be returned and %errno will be set
* to a non-zero value. On success, %errno will be set to zero, check %errno
* for errors. Any trailing or leading (ascii) white space is ignored and the
* functions is locale independent.
*
* The function is guaranteed to return a value between @min and @max
* (inclusive) or @fallback. Also, the parsing is rather strict, it does
* not allow for any unrecognized characters, except leading and trailing
* white space.
**/
gint64
_nm_utils_ascii_str_to_int64 (const char *str, guint base, gint64 min, gint64 max, gint64 fallback)
{
gint64 v;
size_t len;
char buf[64], *s, *str_free = NULL;
if (str) {
while (g_ascii_isspace (str[0]))
str++;
}
if (!str || !str[0]) {
errno = EINVAL;
return fallback;
}
len = strlen (str);
if (g_ascii_isspace (str[--len])) {
/* backward search the first non-ws character.
* We already know that str[0] is non-ws. */
while (g_ascii_isspace (str[--len]))
;
/* str[len] is now the last non-ws character... */
len++;
if (len >= sizeof (buf))
s = str_free = g_malloc (len + 1);
else
s = buf;
memcpy (s, str, len);
s[len] = 0;
/*
g_assert (len > 0 && len < strlen (str) && len == strlen (s));
g_assert (!g_ascii_isspace (str[len-1]) && g_ascii_isspace (str[len]));
g_assert (strncmp (str, s, len) == 0);
*/
str = s;
}
errno = 0;
v = g_ascii_strtoll (str, &s, base);
if (errno != 0)
v = fallback;
else if (s[0] != 0) {
errno = EINVAL;
v = fallback;
} else if (v > max || v < min) {
errno = ERANGE;
v = fallback;
}
if (G_UNLIKELY (str_free))
g_free (str_free);
return v;
}
/**
* nm_utils_uuid_generate_from_strings:
* @string1: a variadic list of strings. Must be NULL terminated.

View file

@ -163,8 +163,6 @@ int nm_utils_cmp_connection_by_autoconnect_priority (NMConnection **a, NMConnect
void nm_utils_log_connection_diff (NMConnection *connection, NMConnection *diff_base, guint32 level, guint64 domain, const char *name, const char *prefix);
gint64 _nm_utils_ascii_str_to_int64 (const char *str, guint base, gint64 min, gint64 max, gint64 fallback);
#define NM_UTILS_UUID_NS "b425e9fb-7598-44b4-9e3b-5a2e3aaa4905"
char *nm_utils_uuid_generate_from_strings (const char *string1, ...) G_GNUC_NULL_TERMINATED;

View file

@ -31,6 +31,7 @@
#include <unistd.h>
#include "nm-dhcp-listener.h"
#include "nm-core-internal.h"
#include "nm-logging.h"
#include "nm-dbus-manager.h"
#include "nm-dbus-glib-types.h"

View file

@ -26,7 +26,7 @@
#include "nm-config.h"
#include "nm-device.h"
#include "gsystem-local-alloc.h"
#include "NetworkManagerUtils.h"
#include "nm-core-internal.h"
typedef struct {
char *config_main_file;

View file

@ -55,6 +55,7 @@
#endif
#include "gsystem-local-alloc.h"
#include "nm-core-internal.h"
#include "NetworkManagerUtils.h"
#include "nm-linux-platform.h"
#include "NetworkManagerUtils.h"

View file

@ -35,6 +35,7 @@
#include "NetworkManagerUtils.h"
#include "nm-logging.h"
#include "nm-enum-types.h"
#include "nm-core-internal.h"
#define debug(...) nm_log_dbg (LOGD_PLATFORM, __VA_ARGS__)

View file

@ -36,7 +36,7 @@
#include "shvar.h"
#include "NetworkManagerUtils.h"
#include "nm-core-internal.h"
#include "nm-logging.h"
#define PARSE_WARNING(msg...) nm_log_warn (LOGD_SETTINGS, " " msg)

View file

@ -30,135 +30,6 @@
#include "nm-test-utils.h"
static void
test_nm_utils_ascii_str_to_int64_check (const char *str, guint base, gint64 min,
gint64 max, gint64 fallback, int exp_errno,
gint64 exp_val)
{
gint64 v;
errno = 1;
v = _nm_utils_ascii_str_to_int64 (str, base, min, max, fallback);
g_assert_cmpint (errno, ==, exp_errno);
g_assert_cmpint (v, ==, exp_val);
}
static void
test_nm_utils_ascii_str_to_int64_do (const char *str, guint base, gint64 min,
gint64 max, gint64 fallback, int exp_errno,
gint64 exp_val)
{
const char *sign = "";
const char *val;
static const char *whitespaces[] = {
"",
" ",
"\r\n\t",
" \r\n\t ",
" \r\n\t \t\r\n\t",
NULL,
};
static const char *nulls[] = {
"",
"0",
"00",
"0000",
"0000000000000000",
"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
NULL,
};
const char **ws_pre, **ws_post, **null;
guint i;
if (str == NULL || exp_errno != 0) {
test_nm_utils_ascii_str_to_int64_check (str, base, min, max, fallback, exp_errno, exp_val);
return;
}
if (strncmp (str, "-", 1) == 0)
sign = "-";
val = str + strlen (sign);
for (ws_pre = whitespaces; *ws_pre; ws_pre++) {
for (ws_post = whitespaces; *ws_post; ws_post++) {
for (null = nulls; *null; null++) {
for (i = 0; ; i++) {
char *s;
const char *str_base = "";
if (base == 16) {
if (i == 1)
str_base = "0x";
else if (i > 1)
break;
} else if (base == 8) {
if (i == 1)
str_base = "0";
else if (i > 1)
break;
} else if (base == 0) {
if (i > 0)
break;
/* with base==0, a leading zero would be interpreted as octal. Only test without *null */
if ((*null)[0])
break;
} else {
if (i > 0)
break;
}
s = g_strdup_printf ("%s%s%s%s%s%s", *ws_pre, sign, str_base, *null, val, *ws_post);
test_nm_utils_ascii_str_to_int64_check (s, base, min, max, fallback, exp_errno, exp_val);
g_free (s);
}
}
}
}
}
static void
test_nm_utils_ascii_str_to_int64 (void)
{
test_nm_utils_ascii_str_to_int64_do (NULL, 10, 0, 10000, -1, EINVAL, -1);
test_nm_utils_ascii_str_to_int64_do ("", 10, 0, 10000, -1, EINVAL, -1);
test_nm_utils_ascii_str_to_int64_do ("1x", 10, 0, 10000, -1, EINVAL, -1);
test_nm_utils_ascii_str_to_int64_do ("4711", 10, 0, 10000, -1, 0, 4711);
test_nm_utils_ascii_str_to_int64_do ("10000", 10, 0, 10000, -1, 0, 10000);
test_nm_utils_ascii_str_to_int64_do ("10001", 10, 0, 10000, -1, ERANGE, -1);
test_nm_utils_ascii_str_to_int64_do ("FF", 16, 0, 10000, -1, 0, 255);
test_nm_utils_ascii_str_to_int64_do ("FF", 10, 0, 10000, -2, EINVAL, -2);
test_nm_utils_ascii_str_to_int64_do ("9223372036854775807", 10, 0, G_MAXINT64, -2, 0, G_MAXINT64);
test_nm_utils_ascii_str_to_int64_do ("7FFFFFFFFFFFFFFF", 16, 0, G_MAXINT64, -2, 0, G_MAXINT64);
test_nm_utils_ascii_str_to_int64_do ("9223372036854775808", 10, 0, G_MAXINT64, -2, ERANGE, -2);
test_nm_utils_ascii_str_to_int64_do ("-9223372036854775808", 10, G_MININT64, 0, -2, 0, G_MININT64);
test_nm_utils_ascii_str_to_int64_do ("-9223372036854775808", 10, G_MININT64+1, 0, -2, ERANGE, -2);
test_nm_utils_ascii_str_to_int64_do ("-9223372036854775809", 10, G_MININT64, 0, -2, ERANGE, -2);
test_nm_utils_ascii_str_to_int64_do ("1.0", 10, 1, 1, -1, EINVAL, -1);
test_nm_utils_ascii_str_to_int64_do ("1x0", 16, -10, 10, -100, EINVAL, -100);
test_nm_utils_ascii_str_to_int64_do ("0", 16, -10, 10, -100, 0, 0);
test_nm_utils_ascii_str_to_int64_do ("10001111", 2, -1000, 1000, -100000, 0, 0x8F);
test_nm_utils_ascii_str_to_int64_do ("-10001111", 2, -1000, 1000, -100000, 0, -0x8F);
test_nm_utils_ascii_str_to_int64_do ("1111111", 2, G_MININT64, G_MAXINT64, -1, 0, 0x7F);
test_nm_utils_ascii_str_to_int64_do ("111111111111111", 2, G_MININT64, G_MAXINT64, -1, 0, 0x7FFF);
test_nm_utils_ascii_str_to_int64_do ("11111111111111111111111111111111111111111111111", 2, G_MININT64, G_MAXINT64, -1, 0, 0x7FFFFFFFFFFF);
test_nm_utils_ascii_str_to_int64_do ("111111111111111111111111111111111111111111111111111111111111111", 2, G_MININT64, G_MAXINT64, -1, 0, 0x7FFFFFFFFFFFFFFF);
test_nm_utils_ascii_str_to_int64_do ("100000000000000000000000000000000000000000000000000000000000000", 2, G_MININT64, G_MAXINT64, -1, 0, 0x4000000000000000);
test_nm_utils_ascii_str_to_int64_do ("1000000000000000000000000000000000000000000000000000000000000000", 2, G_MININT64, G_MAXINT64, -1, ERANGE, -1);
test_nm_utils_ascii_str_to_int64_do ("-100000000000000000000000000000000000000000000000000000000000000", 2, G_MININT64, G_MAXINT64, -1, 0, -0x4000000000000000);
test_nm_utils_ascii_str_to_int64_do ("111111111111111111111111111111111111111111111111111111111111111", 2, G_MININT64, G_MAXINT64, -1, 0, 0x7FFFFFFFFFFFFFFF);
test_nm_utils_ascii_str_to_int64_do ("-100000000000000000000000000000000000000000000000000000000000000", 2, G_MININT64, G_MAXINT64, -1, 0, -0x4000000000000000);
test_nm_utils_ascii_str_to_int64_do ("0x70", 10, G_MININT64, G_MAXINT64, -1, EINVAL, -1);
test_nm_utils_ascii_str_to_int64_do ("4711", 0, G_MININT64, G_MAXINT64, -1, 0, 4711);
test_nm_utils_ascii_str_to_int64_do ("04711", 0, G_MININT64, G_MAXINT64, -1, 0, 04711);
test_nm_utils_ascii_str_to_int64_do ("0x4711", 0, G_MININT64, G_MAXINT64, -1, 0, 0x4711);
test_nm_utils_ascii_str_to_int64_do ("080", 0, G_MININT64, G_MAXINT64, -1, EINVAL, -1);
test_nm_utils_ascii_str_to_int64_do ("070", 0, G_MININT64, G_MAXINT64, -1, 0, 7*8);
test_nm_utils_ascii_str_to_int64_do ("0x70", 0, G_MININT64, G_MAXINT64, -1, 0, 0x70);
}
/* Reference implementation for nm_utils_ip6_address_clear_host_address.
* Taken originally from set_address_masked(), src/rdisc/nm-lndp-rdisc.c
**/
@ -893,7 +764,6 @@ main (int argc, char **argv)
{
nmtst_init_with_logging (&argc, &argv, NULL, "ALL");
g_test_add_func ("/general/_nm_utils_ascii_str_to_int64", test_nm_utils_ascii_str_to_int64);
g_test_add_func ("/general/nm_utils_ip6_address_clear_host_address", test_nm_utils_ip6_address_clear_host_address);
g_test_add_func ("/general/nm_utils_log_connection_diff", test_nm_utils_log_connection_diff);