mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-26 14:03:49 +03:00
util: new stricter unsigned int parsing
strtoul() is required to parse negative numbers as their twos-complement positive counterpart. But sometimes we want to reject negative numbers. Add new functions to do this. The 'p' suffix is a mnemonic for 'positive' (technically it also parses 0, but 'non-negative' doesn't lend itself to a nice one-letter suffix). * src/util/virstring.h (virStrToLong_uip, virStrToLong_ulp) (virStrToLong_ullp): New prototypes. * src/util/virstring.c (virStrToLong_uip, virStrToLong_ulp) (virStrToLong_ullp): New functions. * src/libvirt_private.syms (virstring.h): Export them. * tests/virstringtest.c (testStringToLong): Test them. Signed-off-by: Eric Blake <eblake@redhat.com>
This commit is contained in:
parent
f18c02ec22
commit
7b045c8ce9
@ -1899,8 +1899,11 @@ virStrToLong_i;
|
||||
virStrToLong_l;
|
||||
virStrToLong_ll;
|
||||
virStrToLong_ui;
|
||||
virStrToLong_uip;
|
||||
virStrToLong_ul;
|
||||
virStrToLong_ull;
|
||||
virStrToLong_ullp;
|
||||
virStrToLong_ulp;
|
||||
virTrimSpaces;
|
||||
virVasprintfInternal;
|
||||
|
||||
|
@ -211,7 +211,9 @@ virStrToLong_i(char const *s, char **end_ptr, int base, int *result)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Just like virStrToLong_i, above, but produce an "unsigned int" value. */
|
||||
/* Just like virStrToLong_i, above, but produce an "unsigned int"
|
||||
* value. This version allows twos-complement wraparound of negative
|
||||
* numbers. */
|
||||
int
|
||||
virStrToLong_ui(char const *s, char **end_ptr, int base, unsigned int *result)
|
||||
{
|
||||
@ -242,6 +244,27 @@ virStrToLong_ui(char const *s, char **end_ptr, int base, unsigned int *result)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Just like virStrToLong_i, above, but produce an "unsigned int"
|
||||
* value. This version rejects any negative signs. */
|
||||
int
|
||||
virStrToLong_uip(char const *s, char **end_ptr, int base, unsigned int *result)
|
||||
{
|
||||
unsigned long int val;
|
||||
char *p;
|
||||
bool err = false;
|
||||
|
||||
errno = 0;
|
||||
val = strtoul(s, &p, base); /* exempt from syntax-check */
|
||||
err = (memchr(s, '-', p - s) ||
|
||||
errno || (!end_ptr && *p) || p == s || (unsigned int) val != val);
|
||||
if (end_ptr)
|
||||
*end_ptr = p;
|
||||
if (err)
|
||||
return -1;
|
||||
*result = val;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Just like virStrToLong_i, above, but produce a "long" value. */
|
||||
int
|
||||
virStrToLong_l(char const *s, char **end_ptr, int base, long *result)
|
||||
@ -261,7 +284,9 @@ virStrToLong_l(char const *s, char **end_ptr, int base, long *result)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Just like virStrToLong_i, above, but produce an "unsigned long" value. */
|
||||
/* Just like virStrToLong_i, above, but produce an "unsigned long"
|
||||
* value. This version allows twos-complement wraparound of negative
|
||||
* numbers. */
|
||||
int
|
||||
virStrToLong_ul(char const *s, char **end_ptr, int base, unsigned long *result)
|
||||
{
|
||||
@ -280,6 +305,28 @@ virStrToLong_ul(char const *s, char **end_ptr, int base, unsigned long *result)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Just like virStrToLong_i, above, but produce an "unsigned long"
|
||||
* value. This version rejects any negative signs. */
|
||||
int
|
||||
virStrToLong_ulp(char const *s, char **end_ptr, int base,
|
||||
unsigned long *result)
|
||||
{
|
||||
unsigned long int val;
|
||||
char *p;
|
||||
int err;
|
||||
|
||||
errno = 0;
|
||||
val = strtoul(s, &p, base); /* exempt from syntax-check */
|
||||
err = (memchr(s, '-', p - s) ||
|
||||
errno || (!end_ptr && *p) || p == s);
|
||||
if (end_ptr)
|
||||
*end_ptr = p;
|
||||
if (err)
|
||||
return -1;
|
||||
*result = val;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Just like virStrToLong_i, above, but produce a "long long" value. */
|
||||
int
|
||||
virStrToLong_ll(char const *s, char **end_ptr, int base, long long *result)
|
||||
@ -299,9 +346,12 @@ virStrToLong_ll(char const *s, char **end_ptr, int base, long long *result)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Just like virStrToLong_i, above, but produce an "unsigned long long" value. */
|
||||
/* Just like virStrToLong_i, above, but produce an "unsigned long
|
||||
* long" value. This version allows twos-complement wraparound of
|
||||
* negative numbers. */
|
||||
int
|
||||
virStrToLong_ull(char const *s, char **end_ptr, int base, unsigned long long *result)
|
||||
virStrToLong_ull(char const *s, char **end_ptr, int base,
|
||||
unsigned long long *result)
|
||||
{
|
||||
unsigned long long val;
|
||||
char *p;
|
||||
@ -318,6 +368,28 @@ virStrToLong_ull(char const *s, char **end_ptr, int base, unsigned long long *re
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Just like virStrToLong_i, above, but produce an "unsigned long
|
||||
* long" value. This version rejects any negative signs. */
|
||||
int
|
||||
virStrToLong_ullp(char const *s, char **end_ptr, int base,
|
||||
unsigned long long *result)
|
||||
{
|
||||
unsigned long long val;
|
||||
char *p;
|
||||
int err;
|
||||
|
||||
errno = 0;
|
||||
val = strtoull(s, &p, base); /* exempt from syntax-check */
|
||||
err = (memchr(s, '-', p - s) ||
|
||||
errno || (!end_ptr && *p) || p == s);
|
||||
if (end_ptr)
|
||||
*end_ptr = p;
|
||||
if (err)
|
||||
return -1;
|
||||
*result = val;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
virStrToDouble(char const *s,
|
||||
char **end_ptr,
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2007-2012 Red Hat, Inc.
|
||||
* Copyright (C) 2007-2014 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@ -50,6 +50,10 @@ int virStrToLong_ui(char const *s,
|
||||
char **end_ptr,
|
||||
int base,
|
||||
unsigned int *result);
|
||||
int virStrToLong_uip(char const *s,
|
||||
char **end_ptr,
|
||||
int base,
|
||||
unsigned int *result);
|
||||
int virStrToLong_l(char const *s,
|
||||
char **end_ptr,
|
||||
int base,
|
||||
@ -58,6 +62,10 @@ int virStrToLong_ul(char const *s,
|
||||
char **end_ptr,
|
||||
int base,
|
||||
unsigned long *result);
|
||||
int virStrToLong_ulp(char const *s,
|
||||
char **end_ptr,
|
||||
int base,
|
||||
unsigned long *result);
|
||||
int virStrToLong_ll(char const *s,
|
||||
char **end_ptr,
|
||||
int base,
|
||||
@ -66,6 +74,10 @@ int virStrToLong_ull(char const *s,
|
||||
char **end_ptr,
|
||||
int base,
|
||||
unsigned long long *result);
|
||||
int virStrToLong_ullp(char const *s,
|
||||
char **end_ptr,
|
||||
int base,
|
||||
unsigned long long *result);
|
||||
int virStrToDouble(char const *s,
|
||||
char **end_ptr,
|
||||
double *result);
|
||||
|
@ -408,6 +408,13 @@ testStringToLong(const void *opaque)
|
||||
char *end;
|
||||
long l;
|
||||
unsigned long ul;
|
||||
bool negative;
|
||||
|
||||
if (data->suffix)
|
||||
negative = !!memchr(data->str, '-',
|
||||
strlen(data->str) - strlen(data->suffix));
|
||||
else
|
||||
negative = !!strchr(data->str, '-');
|
||||
|
||||
#define TEST_ONE(Str, Suff, Type, Fn, Fmt, Exp, Exp_ret) \
|
||||
do { \
|
||||
@ -441,6 +448,11 @@ testStringToLong(const void *opaque)
|
||||
data->si, data->si_ret);
|
||||
TEST_ONE(data->str, data->suffix, unsigned int, ui, "%u",
|
||||
data->ui, data->ui_ret);
|
||||
if (negative)
|
||||
TEST_ONE(data->str, data->suffix, unsigned int, uip, "%u", 0U, -1);
|
||||
else
|
||||
TEST_ONE(data->str, data->suffix, unsigned int, uip, "%u",
|
||||
data->ui, data->ui_ret);
|
||||
|
||||
/* We hate adding new API with 'long', and prefer 'int' or 'long
|
||||
* long' instead, since platform-specific results are evil */
|
||||
@ -450,11 +462,22 @@ testStringToLong(const void *opaque)
|
||||
ul = (sizeof(int) == sizeof(long)) ? data->ui : data->ull;
|
||||
TEST_ONE(data->str, data->suffix, unsigned long, ul, "%lu",
|
||||
ul, (sizeof(int) == sizeof(long)) ? data->ui_ret : data->ull_ret);
|
||||
if (negative)
|
||||
TEST_ONE(data->str, data->suffix, unsigned long, ulp, "%lu", 0UL, -1);
|
||||
else
|
||||
TEST_ONE(data->str, data->suffix, unsigned long, ulp, "%lu", ul,
|
||||
(sizeof(int) == sizeof(long)) ? data->ui_ret : data->ull_ret);
|
||||
|
||||
TEST_ONE(data->str, data->suffix, long long, ll, "%lld",
|
||||
data->ll, data->ll_ret);
|
||||
TEST_ONE(data->str, data->suffix, unsigned long long, ull, "%llu",
|
||||
data->ull, data->ull_ret);
|
||||
if (negative)
|
||||
TEST_ONE(data->str, data->suffix, unsigned long long, ullp, "%llu",
|
||||
0ULL, -1);
|
||||
else
|
||||
TEST_ONE(data->str, data->suffix, unsigned long long, ullp, "%llu",
|
||||
data->ull, data->ull_ret);
|
||||
|
||||
#undef TEST_ONE
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user