From d37ba903d8d0c9c3d7de8280b55229c23cebad18 Mon Sep 17 00:00:00 2001 From: Ulrich Müller Date: Tue, 8 Dec 2015 17:56:52 +0100 Subject: put.c: Avoid out of bounds stack read. Fix the extract() function not to access unnecessary array elements; this avoids an out-of-bounds read when called from btoe() or etob(). Change the insert() function to use similar logic as extract(). Bug: 567608 --- patchsets/skey/1.1.5/14_all_extract-insert.patch | 84 ++++++++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 patchsets/skey/1.1.5/14_all_extract-insert.patch diff --git a/patchsets/skey/1.1.5/14_all_extract-insert.patch b/patchsets/skey/1.1.5/14_all_extract-insert.patch new file mode 100644 index 0000000..62e3efc --- /dev/null +++ b/patchsets/skey/1.1.5/14_all_extract-insert.patch @@ -0,0 +1,84 @@ +https://bugs.gentoo.org/567608 +Fix the extract() function not to access unnecessary array elements; +this avoids an out-of-bounds read when called from btoe() or etob(). +Change the insert() function to use similar logic as extract(). + +--- skey-1.1.5-orig/put.c ++++ skey-1.1.5/put.c +@@ -2221,37 +2221,20 @@ + + static void insert(char *s, int x, int start, int length) + { +- unsigned char cl; +- unsigned char cc; +- unsigned char cr; + unsigned int y; +- int shift; ++ int end, i; + + assert(length <= 11); + assert(start >= 0); + assert(length >= 0); + assert(start + length <= 66); + +- shift = ((8 - ((start + length) % 8)) % 8); +- y = (int) x << shift; +- cl = (y >> 16) & 0xff; +- cc = (y >> 8) & 0xff; +- cr = y & 0xff; +- if (shift + length > 16) +- { +- s[start / 8] |= cl; +- s[start / 8 + 1] |= cc; +- s[start / 8 + 2] |= cr; +- } +- else if (shift + length > 8) +- { +- s[start / 8] |= cc; +- s[start / 8 + 1] |= cr; +- } +- else +- { +- s[start / 8] |= cr; +- } ++ end = start + length - 1; ++ y = x << (7 - end % 8); ++ for (i = end / 8; i >= start / 8; i--) { ++ s[i] |= y & 0xff; ++ y >>= 8; ++ } + } + + static void standard(char *word) +@@ -2274,22 +2257,22 @@ + /* Extract 'length' bits from the char array 's' starting with bit 'start' */ + static unsigned int extract(char *s, int start, int length) + { +- unsigned char cl; +- unsigned char cc; +- unsigned char cr; + unsigned int x; ++ int end, i; + + assert(length <= 11); + assert(start >= 0); + assert(length >= 0); + assert(start + length <= 66); + +- cl = s[start / 8]; +- cc = s[start / 8 + 1]; +- cr = s[start / 8 + 2]; +- x = ((int)(cl << 8 | cc) << 8 | cr); +- x = x >> (24 - (length + (start % 8))); +- x = (x & (0xffff >> (16 - length))); ++ end = start + length - 1; ++ x = 0; ++ for (i = start / 8; i <= end / 8; i++) { ++ x <<= 8; ++ x |= (unsigned char)s[i]; ++ } ++ x >>= 7 - end % 8; ++ x &= (1 << length) - 1; + + return x; + } -- cgit v1.2.3-65-gdbad