Validate psfu headers to avoid integer overflows.
PATCH 1/1 Validate psfu headers to avoid integer overflows.
The psfu parser does not properly validate parsed values:
* unsigned int values are casted to signed int values when parameters are supplied, therefore they must be checked against INT_MAX (local size_t variables are used)
* fontwidth must not be larger than INT_MAX - 7, otherwise later alignment codes would overflow, e.g. (fontwidth + 7) / 8
* "ftoffset + fontlen * charsize" is prone to overflow, make sure that it does not; later on it will be checked against file size
* when parsing multiple files, make sure that the sum of all fonts won't overflow
---
Attached are two files which will crash the current code:
$ setfont setfont-fpe.psfu # font width too large Floating point exception $ psfxtable -i psfxtable-segfault.psfu # on 32 bit archs Segmentation fault
Maybe there are more ways to trigger overflows, which makes it a good target for fuzzing.
--- src/psffontop.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+)
src/psffontop.c +22 -0
@@ -2,6 +2,7 @@* psffontop.c - [email protected], 990921 */ +#include <limits.h> #include <stdio.h> #include <stdlib.h> #include <string.h>
@@ -275,6 +276,27 @@ readpsffont(FILE *fontf, char **allbufp, int *allszp,fprintf (stderr, u, progname);exit (EX_DATAERR ); } +if (INT_MAX -7 < fontwidth) { +char *u =_ ("%s: Input file: font width too large\n" ); +fprintf (stderr, u, progname); +exit (EX_DATAERR ); + } + +/* validate header to avoid integer overflows */ +if ((size_t )(INT_MAX - fontpos0) < fontlen || +INT_MAX /sizeof (struct unicode_list ) < fontpos0 + fontlen || +INT_MAX / charsize < fontlen) { +char *u =_ ("%s: too many glyphs to load\n" ); +fprintf (stderr, u, progname); +exit (EX_DATAERR ); + } +if (ftoffset > inputbuflth || +INT_MAX - ftoffset < fontlen * charsize) { +char *u =_ ("%s: Input file: bad offset\n" ); +fprintf (stderr, u, progname); +exit (EX_DATAERR ); + } + i = ftoffset + fontlen * charsize;if (i > inputlth || (!hastable && i != inputlth)) {char *u =_ ("%s: Input file: bad input length (%d)\n" );
Signature · 1 line
2.5.0