Allow user to omit font size specification when loading a font. In addition

the following fixes had been made:

- check the size of the font being loaded and compare it with possible sizes
  to minimise possibility of loading something that is not a fontfile at all
  and turning console screen into garbage;

- prevent buffer overflow (and coredump as a result ) when loading valid
  uuencoded file with size that exceeds allocated buffer;

- correct and improve several error messages.

Approved by:	-audit, -hackers (silently)
This commit is contained in:
sobomax 2001-04-09 17:24:29 +00:00
parent 47ef52ef40
commit f771fe1a20
4 changed files with 133 additions and 45 deletions

View File

@ -35,10 +35,11 @@ static const char rcsid[] =
#include <string.h>
#include "decode.h"
int decode(FILE *fd, char *buffer)
int decode(FILE *fd, char *buffer, int len)
{
int n, pos = 0;
char *p;
int n, pos = 0, tpos;
char *bp, *p;
char tbuffer[3];
char temp[128];
#define DEC(c) (((c) - ' ') & 0x3f)
@ -48,31 +49,49 @@ int decode(FILE *fd, char *buffer)
return(0);
} while (strncmp(temp, "begin ", 6));
sscanf(temp, "begin %o %s", &n, temp);
bp = buffer;
for (;;) {
if (!fgets(p = temp, sizeof(temp), fd))
return(0);
if ((n = DEC(*p)) <= 0)
break;
for (++p; n > 0; p += 4, n -= 3)
for (++p; n > 0; p += 4, n -= 3) {
tpos = 0;
if (n >= 3) {
buffer[pos++] = DEC(p[0])<<2 | DEC(p[1])>>4;
buffer[pos++] = DEC(p[1])<<4 | DEC(p[2])>>2;
buffer[pos++] = DEC(p[2])<<6 | DEC(p[3]);
tbuffer[tpos++] = DEC(p[0])<<2 | DEC(p[1])>>4;
tbuffer[tpos++] = DEC(p[1])<<4 | DEC(p[2])>>2;
tbuffer[tpos++] = DEC(p[2])<<6 | DEC(p[3]);
}
else {
if (n >= 1) {
buffer[pos++] =
tbuffer[tpos++] =
DEC(p[0])<<2 | DEC(p[1])>>4;
}
if (n >= 2) {
buffer[pos++] =
tbuffer[tpos++] =
DEC(p[1])<<4 | DEC(p[2])>>2;
}
if (n >= 3) {
buffer[pos++] =
tbuffer[tpos++] =
DEC(p[2])<<6 | DEC(p[3]);
}
}
if (tpos == 0)
continue;
if (tpos + pos > len) {
tpos = len - pos;
/*
* Arrange return value > len to indicate
* overflow.
*/
pos++;
}
bcopy(tbuffer, bp, tpos);
pos += tpos;
bp += tpos;
if (pos > len)
return(pos);
}
}
if (!fgets(temp, sizeof(temp), fd) || strcmp(temp, "end\n"))
return(0);

View File

@ -1 +1,3 @@
int decode(FILE *fd, char *buffer);
/* $FreeBSD$ */
int decode(FILE *fd, char *buffer, int len);

View File

@ -24,7 +24,7 @@
.Op Fl b Ar color
.Op Fl c Ar appearance
.Op Fl d
.Op Fl f Ar size Ar file
.Op Fl f Oo Ar size Oc Ar \ file
.Op Fl g Ar geometry
.Op Fl i Cm adapter | mode
.Op Fl l Ar screen_map
@ -142,7 +142,7 @@ or
Used together with the
.Xr moused 8
daemon for text mode cut & paste functionality.
.It Fl f Ar size Ar file
.It Fl f [ Ar size ] Ar file
Load font
.Ar file
for
@ -157,6 +157,11 @@ You can also use the menu-driven
.Xr vidfont 1
command to load the font of your choice.
.Pp
.Ar Size
may be omitted, in this case
.Nm
will try to guess it from the size of font file.
.Pp
Note that older video cards, such as MDA and CGA, do not support
software font.
See also
@ -296,6 +301,11 @@ you may abbreviate the file name as
.Pp
.Dl vidcontrol -f 8x16 iso-8x16
.Pp
Furthermore, you can also omit font size
.Dq 8x16 :
.Pp
.Dl vidcontrol -f iso-8x16
.Pp
Likewise, you can also abbreviate the screen output map file name for
the
.Fl l

View File

@ -41,6 +41,8 @@ static const char rcsid[] =
#include <sys/fbio.h>
#include <sys/consio.h>
#include <sys/errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "path.h"
#include "decode.h"
@ -74,12 +76,13 @@ usage()
}
char *
nextarg(int ac, char **av, int *indp, int oc)
nextarg(int ac, char **av, int *indp, int oc, int strict)
{
if (*indp < ac)
return(av[(*indp)++]);
errx(1, "option requires two arguments -- %c", oc);
return("");
if (strict != 0)
errx(1, "option requires two arguments -- %c", oc);
return(NULL);
}
char *
@ -129,7 +132,7 @@ load_scrnmap(char *filename)
return;
}
size = sizeof(scrnmap);
if (decode(fd, (char *)&scrnmap) != size) {
if (decode(fd, (char *)&scrnmap, size) != size) {
rewind(fd);
if (fread(&scrnmap, 1, size, fd) != size) {
warnx("bad screenmap file");
@ -176,16 +179,38 @@ print_scrnmap()
}
int
fsize(FILE *file)
{
struct stat sb;
if (fstat(fileno(file), &sb) == 0)
return sb.st_size;
else
return -1;
}
#define DATASIZE(x) ((x).w * (x).h * 256 / 8)
void
load_font(char *type, char *filename)
{
FILE *fd = 0;
int i, size;
unsigned long io;
FILE *fd = NULL;
int h, i, size, w;
unsigned long io = 0; /* silence stupid gcc(1) in the Wall mode */
char *name, *fontmap;
char *prefix[] = {"", "", FONT_PATH, FONT_PATH, NULL};
char *postfix[] = {"", ".fnt", "", ".fnt"};
struct sizeinfo {
int w;
int h;
unsigned long io;
} sizes[] = {{8, 16, PIO_FONT8x16},
{8, 14, PIO_FONT8x14},
{8, 8, PIO_FONT8x8},
{0, 0, 0}};
for (i=0; prefix[i]; i++) {
name = mkfullname(prefix[i], filename, postfix[i]);
fd = fopen(name, "r");
@ -193,31 +218,57 @@ load_font(char *type, char *filename)
break;
}
if (fd == NULL) {
warn("font file not found");
warn("%s: can't load font file", filename);
return;
}
if (!strcmp(type, "8x8")) {
size = 8*256;
io = PIO_FONT8x8;
}
else if (!strcmp(type, "8x14")) {
size = 14*256;
io = PIO_FONT8x14;
}
else if (!strcmp(type, "8x16")) {
size = 16*256;
io = PIO_FONT8x16;
}
else {
warn("bad font size specification");
fclose(fd);
return;
}
fontmap = (char*) malloc(size);
if (decode(fd, fontmap) != size) {
if (type != NULL) {
size = 0;
if (sscanf(type, "%dx%d", &w, &h) == 2)
for (i = 0; sizes[i].w != 0; i++)
if (sizes[i].w == w && sizes[i].h == h) {
size = DATASIZE(sizes[i]);
io = sizes[i].io;
}
if (size == 0) {
warnx("%s: bad font size specification", type);
fclose(fd);
return;
}
} else {
/* Apply heuristics */
int j;
int dsize[2];
size = DATASIZE(sizes[0]);
fontmap = (char*) malloc(size);
dsize[0] = decode(fd, fontmap, size);
dsize[1] = fsize(fd);
free(fontmap);
size = 0;
for (j = 0; j < 2; j++)
for (i = 0; sizes[i].w != 0; i++)
if (DATASIZE(sizes[i]) == dsize[j]) {
size = dsize[j];
io = sizes[i].io;
j = 2; /* XXX */
break;
}
if (size == 0) {
warnx("%s: can't guess font size", filename);
fclose(fd);
return;
}
rewind(fd);
if (fread(fontmap, 1, size, fd) != size) {
warnx("bad font file");
}
fontmap = (char*) malloc(size);
if (decode(fd, fontmap, size) != size) {
rewind(fd);
if (fsize(fd) != size || fread(fontmap, 1, size, fd) != size) {
warnx("%s: bad font file", filename);
fclose(fd);
free(fontmap);
return;
@ -590,7 +641,8 @@ test_frame()
int
main(int argc, char **argv)
{
int opt;
char *font, *type;
int opt;
info.size = sizeof(info);
@ -608,8 +660,13 @@ main(int argc, char **argv)
print_scrnmap();
break;
case 'f':
load_font(optarg,
nextarg(argc, argv, &optind, 'f'));
type = optarg;
font = nextarg(argc, argv, &optind, 'f', 0);
if (font == NULL) {
type = NULL;
font = optarg;
}
load_font(type, font);
break;
case 'g':
if (sscanf(optarg, "%dx%d", &vesa_cols,