提交 c56f17e5 编写于 作者: P Peter Krempa

virbitmap: Refactor virBitmapParse to avoid access beyond bounds of array

The virBitmapParse function was calling virBitmapIsSet() function that
requires the caller to check the bounds of the bitmap without checking
them. This resulted into crashes when parsing a bitmap string that was
exceeding the bounds used as argument.

This patch refactors the function to use virBitmapSetBit without
checking if the bit is set (this function does the checks internally)
and then counts the bits in the bitmap afterwards (instead of keeping
track while parsing the string).

This patch also changes the "parse_error" label to a more common
"error".

The refactor should also get rid of the need to call sa_assert on the
returned variable as the callpath should allow coverity to infer the
possible return values.

Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=997367

Thanks to Alex Jia for tracking down the issue. This issue is introduced
by commit 0fc89098.

(cherry picked from commit 47b9127e)
上级 16572bc7
...@@ -294,7 +294,6 @@ virBitmapParse(const char *str, ...@@ -294,7 +294,6 @@ virBitmapParse(const char *str,
virBitmapPtr *bitmap, virBitmapPtr *bitmap,
size_t bitmapSize) size_t bitmapSize)
{ {
int ret = 0;
bool neg = false; bool neg = false;
const char *cur; const char *cur;
char *tmp; char *tmp;
...@@ -326,12 +325,12 @@ virBitmapParse(const char *str, ...@@ -326,12 +325,12 @@ virBitmapParse(const char *str,
} }
if (!c_isdigit(*cur)) if (!c_isdigit(*cur))
goto parse_error; goto error;
if (virStrToLong_i(cur, &tmp, 10, &start) < 0) if (virStrToLong_i(cur, &tmp, 10, &start) < 0)
goto parse_error; goto error;
if (start < 0) if (start < 0)
goto parse_error; goto error;
cur = tmp; cur = tmp;
...@@ -339,35 +338,29 @@ virBitmapParse(const char *str, ...@@ -339,35 +338,29 @@ virBitmapParse(const char *str,
if (*cur == ',' || *cur == 0 || *cur == terminator) { if (*cur == ',' || *cur == 0 || *cur == terminator) {
if (neg) { if (neg) {
if (virBitmapIsSet(*bitmap, start)) { if (virBitmapClearBit(*bitmap, start) < 0)
ignore_value(virBitmapClearBit(*bitmap, start)); goto error;
ret--;
}
} else { } else {
if (!virBitmapIsSet(*bitmap, start)) { if (virBitmapSetBit(*bitmap, start) < 0)
ignore_value(virBitmapSetBit(*bitmap, start)); goto error;
ret++;
}
} }
} else if (*cur == '-') { } else if (*cur == '-') {
if (neg) if (neg)
goto parse_error; goto error;
cur++; cur++;
virSkipSpaces(&cur); virSkipSpaces(&cur);
if (virStrToLong_i(cur, &tmp, 10, &last) < 0) if (virStrToLong_i(cur, &tmp, 10, &last) < 0)
goto parse_error; goto error;
if (last < start) if (last < start)
goto parse_error; goto error;
cur = tmp; cur = tmp;
for (i = start; i <= last; i++) { for (i = start; i <= last; i++) {
if (!virBitmapIsSet(*bitmap, i)) { if (virBitmapSetBit(*bitmap, i) < 0)
ignore_value(virBitmapSetBit(*bitmap, i)); goto error;
ret++;
}
} }
virSkipSpaces(&cur); virSkipSpaces(&cur);
...@@ -380,14 +373,13 @@ virBitmapParse(const char *str, ...@@ -380,14 +373,13 @@ virBitmapParse(const char *str,
} else if (*cur == 0 || *cur == terminator) { } else if (*cur == 0 || *cur == terminator) {
break; break;
} else { } else {
goto parse_error; goto error;
} }
} }
sa_assert(ret >= 0); return virBitmapCountBits(*bitmap);
return ret;
parse_error: error:
virBitmapFree(*bitmap); virBitmapFree(*bitmap);
*bitmap = NULL; *bitmap = NULL;
return -1; return -1;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册