From: Matthew Dobson Commentary, choose better names for a few locals. --- lib/bitmap.c | 31 ++++++++++++++++++++++++------- 1 files changed, 24 insertions(+), 7 deletions(-) diff -puN lib/bitmap.c~bitmap-parsing-cleanup lib/bitmap.c --- 25/lib/bitmap.c~bitmap-parsing-cleanup 2004-01-20 09:24:14.000000000 -0800 +++ 25-akpm/lib/bitmap.c 2004-01-20 09:24:14.000000000 -0800 @@ -210,13 +210,13 @@ EXPORT_SYMBOL(bitmap_snprintf); * bits of the resultant bitmask. No chunk may specify a value larger * than 32 bits (-EOVERFLOW), and if a chunk specifies a smaller value * then leading 0-bits are prepended. -EINVAL is returned for illegal - * characters and for grouping errors such as "1,,5", ,44", "," and "". + * characters and for grouping errors such as "1,,5", ",44", "," and "". * Leading and trailing whitespace accepted, but not embedded whitespace. */ int bitmap_parse(const char __user *ubuf, unsigned int ubuflen, unsigned long *maskp, int nmaskbits) { - int i, c, oc, ndigits, totaldigits, nchunks, nbits; + int i, c, old_c, totaldigits, ndigits, nchunks, nbits; u32 chunk; bitmap_clear(maskp, nmaskbits); @@ -224,21 +224,39 @@ int bitmap_parse(const char __user *ubuf nchunks = nbits = totaldigits = c = 0; do { chunk = ndigits = 0; + + /* Get the next chunk of the bitmap */ while (ubuflen) { - oc = c; + old_c = c; if (get_user(c, ubuf++)) return -EFAULT; ubuflen--; if (isspace(c)) continue; - if (totaldigits && c && isspace(oc)) + + /* + * If the last character was a space and the current + * character isn't '\0', we've got embedded whitespace. + * This is a no-no, so throw an error. + */ + if (totaldigits && c && isspace(old_c)) return -EINVAL; - if (!c || c == ',') + + /* A '\0' or a ',' signal the end of the chunk */ + if (c == '\0' || c == ',') break; + if (!isxdigit(c)) return -EINVAL; + + /* + * Make sure there are at least 4 free bits in 'chunk'. + * If not, this hexdigit will overflow 'chunk', so + * throw an error. + */ if (chunk & ~((1UL << (CHUNKSZ - 4)) - 1)) return -EOVERFLOW; + chunk = (chunk << 4) | unhex(c); ndigits++; totaldigits++; } @@ -246,6 +264,7 @@ int bitmap_parse(const char __user *ubuf return -EINVAL; if (nchunks == 0 && chunk == 0) continue; + bitmap_shift_right(maskp, maskp, CHUNKSZ, nmaskbits); for (i = 0; i < CHUNKSZ; i++) if (chunk & (1 << i)) @@ -256,8 +275,6 @@ int bitmap_parse(const char __user *ubuf return -EOVERFLOW; } while (ubuflen && c == ','); - if (totaldigits == 0) - return -EINVAL; return 0; } EXPORT_SYMBOL(bitmap_parse); _