summaryrefslogtreecommitdiffstats
path: root/usr.sbin/vidcontrol
diff options
context:
space:
mode:
authorsobomax <sobomax@FreeBSD.org>2001-04-09 17:24:29 +0000
committersobomax <sobomax@FreeBSD.org>2001-04-09 17:24:29 +0000
commitc6519e3e0388685fc2a942ced6420a40fc7f38a5 (patch)
tree6ca7b010816880f6fc270e856bc54f9b1974b251 /usr.sbin/vidcontrol
parentd06e42bb7e201adc51a3604b67db6591e901e7f0 (diff)
downloadFreeBSD-src-c6519e3e0388685fc2a942ced6420a40fc7f38a5.zip
FreeBSD-src-c6519e3e0388685fc2a942ced6420a40fc7f38a5.tar.gz
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)
Diffstat (limited to 'usr.sbin/vidcontrol')
-rw-r--r--usr.sbin/vidcontrol/decode.c39
-rw-r--r--usr.sbin/vidcontrol/decode.h4
-rw-r--r--usr.sbin/vidcontrol/vidcontrol.114
-rw-r--r--usr.sbin/vidcontrol/vidcontrol.c117
4 files changed, 131 insertions, 43 deletions
diff --git a/usr.sbin/vidcontrol/decode.c b/usr.sbin/vidcontrol/decode.c
index 1990595..3c6b467 100644
--- a/usr.sbin/vidcontrol/decode.c
+++ b/usr.sbin/vidcontrol/decode.c
@@ -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);
diff --git a/usr.sbin/vidcontrol/decode.h b/usr.sbin/vidcontrol/decode.h
index b939af4..1f1cba4 100644
--- a/usr.sbin/vidcontrol/decode.h
+++ b/usr.sbin/vidcontrol/decode.h
@@ -1 +1,3 @@
-int decode(FILE *fd, char *buffer);
+/* $FreeBSD$ */
+
+int decode(FILE *fd, char *buffer, int len);
diff --git a/usr.sbin/vidcontrol/vidcontrol.1 b/usr.sbin/vidcontrol/vidcontrol.1
index ab92c54..91b6cf3 100644
--- a/usr.sbin/vidcontrol/vidcontrol.1
+++ b/usr.sbin/vidcontrol/vidcontrol.1
@@ -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
diff --git a/usr.sbin/vidcontrol/vidcontrol.c b/usr.sbin/vidcontrol/vidcontrol.c
index 42e457b..24ef988 100644
--- a/usr.sbin/vidcontrol/vidcontrol.c
+++ b/usr.sbin/vidcontrol/vidcontrol.c
@@ -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;
+ 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);
}
+
fontmap = (char*) malloc(size);
- if (decode(fd, fontmap) != size) {
+ if (decode(fd, fontmap, size) != size) {
rewind(fd);
- if (fread(fontmap, 1, size, fd) != size) {
- warnx("bad font file");
+ 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,
OpenPOWER on IntegriCloud