diff -ru a/sys/libkern/bcd.c b/sys/libkern/bcd.c --- a/sys/libkern/bcd.c +++ b/sys/libkern/bcd.c @@ -2,6 +2,12 @@ /* * Some data-tables that are often used. * Cannot be copyrighted. + * + * DOMAIN CONTRACT (indexed via the macros in sys/sys/libkern.h, which + * wrap indices into range): + * bcd2bin_data[154] valid BCD byte indices 0x00..0x99 + * bin2bcd_data[100] valid binary indices 0..99 + * hex2ascii_data[37] radix-36 digits 0..35 plus NUL */ #include diff -ru a/sys/sys/libkern.h b/sys/sys/libkern.h --- a/sys/sys/libkern.h +++ b/sys/sys/libkern.h @@ -56,9 +56,15 @@ extern u_char const bin2bcd_data[]; extern char const hex2ascii_data[]; -#define bcd2bin(bcd) (bcd2bin_data[bcd]) -#define bin2bcd(bin) (bin2bcd_data[bin]) -#define hex2ascii(hex) (hex2ascii_data[hex]) +/* + * The tables in sys/libkern/bcd.c are sized exactly for their valid + * domains: bin2bcd_data[100] (0..99), bcd2bin_data[154] (0x00..0x99) + * and hex2ascii_data[37] (0..35 + NUL). Wrap the index into the object + * so device- or ioctl-supplied bytes cannot read past the end. + */ +#define bcd2bin(bcd) (bcd2bin_data[(u_int)(bcd) % 154]) +#define bin2bcd(bin) (bin2bcd_data[(u_char)(bin) % 100]) +#define hex2ascii(hex) (hex2ascii_data[(u_char)(hex) % 37]) /* * Number of bytes needed for hexadecimal representation