Hiroyuki Kaguchi <fj7025cf(a)aa.jp.fujitsu.com> wrote:
libvirt fails in parsing when MAC address like
"00:16:3e:12:3:61"
is specified for installation.
This is because virt-install can pass 1-digit (like 3) for
MAC address from Cset:316 for Solaris
But libvirt cannot support this MAC 1-digit (like 3) parameter.
Thanks for the patch.
Any change that eliminates a sscanf-based parser is a good one ;-)
A few suggestions:
...
+static int
+parseMacAddr(const char* str, unsigned char *addr)
+{
+ int i;
Initialize errno to 0 before the loop.
Otherwise, an incoming nonzero value could cause rejection
of a valid MAC address.
+ for (i = 0; i < 6; i++) {
+ char *end_ptr;
+ unsigned long result;
+
+ if (!isdigit(*str) && !isalpha(*str))
+ break;
Use isxdigit instead, and add a comment
saying this is solely to avoid accepting the leading
space or "+" that strtoul would otherwise accept.
if (!isxdigit(*str))
break;
+
+ result = strtoul(str, &end_ptr, 16);
+
+ if ((end_ptr - str) < 1 || 2 < (end_ptr - str) ||
+ (errno == ERANGE) ||
While it's ok to test errno == ERANGE,
testing errno != 0 is a little better.
+ (0xFF < result))
+ break;
+
+ addr[i] = (unsigned char) result;
The following test ensures that there is a ":" between adjacent
pairs, but does not require a terminating NUL byte. That means
it would accept arbitrary text after a valid sixth component,
e.g., "00:16:3e:12:3:61-anything-at-all" or a less-contrived
s/0/O/ typo, e.g., "00:16:3e:12:3:6O"
+ if (*end_ptr != ':')
+ return (i == 5) ? 0 : -1;
You can use this instead:
if (*end_ptr != (i < 5 ? ':' : '\0'))
return -1;
if (i == 5)
return 0;
...
virBufferAddLit(buf, "(vif ");
if (mac != NULL) {
- unsigned int addr[12];
- int tmp = sscanf((const char *) mac,
- "%01x%01x:%01x%01x:%01x%01x:%01x%01x:%01x%01x:%01x%01x",
- (unsigned int *) &addr[0],
- (unsigned int *) &addr[1],
- (unsigned int *) &addr[2],
- (unsigned int *) &addr[3],
- (unsigned int *) &addr[4],
- (unsigned int *) &addr[5],
- (unsigned int *) &addr[6],
- (unsigned int *) &addr[7],
- (unsigned int *) &addr[8],
- (unsigned int *) &addr[9],
- (unsigned int *) &addr[10],
- (unsigned int *) &addr[11]);
- if (tmp != 12 || strlen((const char *) mac) != 17) {
+ unsigned char addr[6];
+ if (parseMacAddr((const char*) mac, addr) == -1) {
virXMLError(conn, VIR_ERR_INVALID_MAC, (const char *) mac, 0);
goto error;
}