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:
parent
92d86b9e1e
commit
5e0db936b5
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=75344
@ -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);
|
||||
|
@ -1 +1,3 @@
|
||||
int decode(FILE *fd, char *buffer);
|
||||
/* $FreeBSD$ */
|
||||
|
||||
int decode(FILE *fd, char *buffer, int len);
|
||||
|
@ -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
|
||||
|
@ -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)++]);
|
||||
if (strict != 0)
|
||||
errx(1, "option requires two arguments -- %c", oc);
|
||||
return("");
|
||||
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;
|
||||
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;
|
||||
}
|
||||
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");
|
||||
|
||||
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);
|
||||
if (decode(fd, fontmap) != 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,6 +641,7 @@ test_frame()
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
char *font, *type;
|
||||
int opt;
|
||||
|
||||
|
||||
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user