]> www.fi.muni.cz Git - evince.git/blob - backend/dvi/mdvi-lib/vf.c
backends: Fix several security issues in the dvi-backend.
[evince.git] / backend / dvi / mdvi-lib / vf.c
1 /* vf.c -- VF font support */
2 /*
3  * Copyright (C) 2000, Matias Atria
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18  */
19
20 #include <config.h>
21 #include <string.h>
22
23 #include "mdvi.h"
24 #include "private.h"
25
26 static int  vf_load_font __PROTO((DviParams *, DviFont *));
27 static void vf_free_macros __PROTO((DviFont *));
28
29 /* only symbol exported by this file */
30 DviFontInfo vf_font_info = {
31         "VF",
32         1, /* virtual fonts scale just fine */
33         vf_load_font,
34         NULL,   /* get_glyph */
35         NULL,   /* shrink0 */
36         NULL,   /* shrink1 */
37         vf_free_macros,
38         NULL,   /* reset */
39         NULL,   /* lookup */
40         kpse_vf_format,
41         NULL
42 };
43
44 DviFontInfo ovf_font_info = {
45         "OVF",
46         1, /* virtual fonts scale just fine */
47         vf_load_font,
48         NULL,   /* get_glyph */
49         NULL,   /* shrink0 */
50         NULL,   /* shrink1 */
51         vf_free_macros,
52         NULL,   /* reset */
53         NULL,   /* lookup */
54         kpse_ovf_format,
55         NULL
56 };
57
58 static int vf_load_font(DviParams *params, DviFont *font)
59 {
60         FILE    *p;
61         Uchar   *macros;
62         int     msize;
63         int     mlen;
64         Int32   checksum;
65         long    alpha, beta, z;
66         int     op;
67         int     i;
68         int     nchars;
69         int     loc, hic;
70         DviFontRef *last;
71         
72         macros = NULL;
73         msize = mlen = 0;
74         p = font->in;
75         
76         if(fuget1(p) != 247 || fuget1(p) != 202)
77                 goto badvf;
78         mlen = fuget1(p);
79         fseek(p, (long)mlen, SEEK_CUR);
80         checksum = fuget4(p);
81         if(checksum && font->checksum && checksum != font->checksum) {
82                 mdvi_warning(_("%s: Checksum mismatch (expected %u, got %u)\n"),
83                              font->fontname, font->checksum, checksum);
84         } else if(!font->checksum)
85                 font->checksum = checksum;
86         font->design = fuget4(p);
87         
88         /* read all the fonts in the preamble */
89         last = NULL;
90
91         /* initialize alpha, beta and z for TFM width computation */
92         TFMPREPARE(font->scale, z, alpha, beta);
93
94         op = fuget1(p); 
95         while(op >= DVI_FNT_DEF1 && op <= DVI_FNT_DEF4) {
96                 DviFontRef *ref;
97                 Int32   scale, design;
98                 Uint32  checksum;
99                 int     id;
100                 int     n;
101                 int     hdpi;
102                 int     vdpi;
103                 char    *name;
104                 
105                 /* process fnt_def commands */
106                 
107                 id = fugetn(p, op - DVI_FNT_DEF1 + 1);
108                 checksum = fuget4(p);
109                 scale = fuget4(p);
110                 design = fuget4(p);
111
112                 /* scale this font according to our parent's scale */
113                 scale = TFMSCALE(scale, z, alpha, beta);
114                 design = FROUND(params->tfm_conv * design);
115
116                 /* compute the resolution */
117                 hdpi = FROUND(params->mag * params->dpi * scale / design);
118                 vdpi = FROUND(params->mag * params->vdpi * scale / design);
119                 n = fuget1(p) + fuget1(p);
120                 name = mdvi_malloc(n + 1);
121                 fread(name, 1, n, p);
122                 name[n] = 0;
123                 DEBUG((DBG_FONTS, "(vf) %s: defined font `%s' at %.1fpt (%dx%d dpi)\n",
124                         font->fontname, name, 
125                         (double)scale / (params->tfm_conv * 0x100000), hdpi, vdpi));
126
127                 /* get the font */
128                 ref = font_reference(params, id, name, checksum, hdpi, vdpi, scale);
129                 if(ref == NULL) {
130                         mdvi_error(_("(vf) %s: could not load font `%s'\n"), 
131                                    font->fontname, name);
132                         goto error;
133                 }
134                 mdvi_free(name);
135                 if(last == NULL)
136                         font->subfonts = last = ref;
137                 else
138                         last->next = ref;
139                 ref->next = NULL;
140                 op = fuget1(p);
141         }
142         
143         if(op >= DVI_FNT_DEF1 && op <= DVI_FNT_DEF4)
144                 goto error;
145
146         /* This function correctly reads both .vf and .ovf files */
147         
148         font->chars = xnalloc(DviFontChar, 256);
149         for(i = 0; i < 256; i++)
150                 font->chars[i].offset = 0;
151         nchars = 256;
152         loc = -1; hic = -1;
153         /* now read the characters themselves */
154         while(op <= 242) {
155                 int     pl;
156                 Int32   cc;
157                 Int32   tfm;
158                 
159                 if(op == 242) {
160                         pl = fuget4(p);
161                         cc = fuget4(p);
162                         tfm = fuget4(p);
163                 } else {
164                         pl = op;
165                         cc = fuget1(p);
166                         tfm = fuget3(p);
167                 }
168                 if (cc < 0 || cc > 65536) {
169                         /* TeX engines do not support char codes bigger than 65535 */
170                         mdvi_error(_("(vf) %s: unexpected character %d\n"),
171                                    font->fontname, cc);
172                         goto error;
173                 }
174                 if(loc < 0 || cc < loc)
175                         loc = cc;
176                 if(hic < 0 || cc > hic)
177                         hic = cc;
178                 if(cc >= nchars) {
179                         font->chars = xresize(font->chars, 
180                                 DviFontChar, cc + 16);
181                         for(i = nchars; i < cc + 16; i++)
182                                 font->chars[i].offset = 0;
183                         nchars = cc + 16;
184                 }
185                 if(font->chars[cc].offset) {
186                         mdvi_error(_("(vf) %s: character %d redefined\n"),
187                                    font->fontname, cc);
188                         goto error;
189                 }
190                                 
191                 DEBUG((DBG_GLYPHS, "(vf) %s: defined character %d (macro length %d)\n",
192                         font->fontname, cc, pl));
193                 font->chars[cc].width = pl + 1;
194                 font->chars[cc].code = cc;
195                 font->chars[cc].tfmwidth = TFMSCALE(tfm, z, alpha, beta);
196                 font->chars[cc].offset = mlen;
197                 font->chars[cc].loaded = 1;
198                 if(mlen + pl + 1 > msize) {
199                         msize = mlen + pl + 256;
200                         macros = xresize(macros, Uchar, msize);
201                 }
202                 if(pl && fread(macros + mlen, 1, pl, p) != pl)
203                         break;
204                 macros[mlen+pl] = DVI_EOP;
205                 mlen += pl + 1;
206                 op = fuget1(p);
207         }
208         if(op != 248) {
209                 mdvi_error(_("(vf) %s: no postamble\n"), font->fontname);
210                 goto error;
211         }
212
213         /* make macro memory just big enough */
214         if(msize > mlen) {
215                 macros = xresize(macros, Uchar, mlen);
216                 msize = mlen;
217         }
218         
219         DEBUG((DBG_FONTS|DBG_GLYPHS, 
220                 "(vf) %s: macros use %d bytes\n", font->fontname, msize));
221
222         if(loc > 0 || hic < nchars-1) {
223                 memmove(font->chars, font->chars + loc,
224                         (hic - loc + 1) * sizeof(DviFontChar));
225                 font->chars = xresize(font->chars,
226                         DviFontChar, hic - loc + 1);
227         }
228         font->loc = loc;
229         font->hic = hic;
230         font->private = macros;
231
232         return 0;
233         
234 badvf:
235         mdvi_error(_("%s: File corrupted, or not a VF file.\n"), font->fontname);
236 error:
237         if(font->chars)
238                 mdvi_free(font->chars);
239         if(macros)
240                 mdvi_free(macros);
241         return -1;
242 }
243
244 static void vf_free_macros(DviFont *font)
245 {
246         mdvi_free(font->private);       
247 }