1 /* wvWare
2  * Copyright (C) Caolan McNamara, Dom Lachowicz, and others
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
17  * 02111-1307, USA.
18  */
19 
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23 
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include "wv.h"
27 
28 /*
29 Word writes out the pllfo first by writing out a PL of LFO structures.
30 It then enumerates through each LFO to figure out how many LFOLVLs each
31 one has (LFO.clfolvl), and writes out, in order, each LFOLVL structure
32 followed by its corresponding LVL structure (if LFOLVL.fFormatting is set).
33 */
34 
35 static int
multiplication_will_overflow(U32 a,U32 b)36 multiplication_will_overflow(U32 a, U32 b)
37 {
38   if((a > 0) && (b > 0) && (G_MAXUINT / a) >= b) {
39     return 0;
40   }
41 
42   return 1;
43 }
44 
45 int
wvGetLFO_records(LFO ** lfo,LFOLVL ** lfolvl,LVL ** lvl,U32 * nolfo,U32 * nooflvl,U32 offset,U32 len,wvStream * fd)46 wvGetLFO_records (LFO ** lfo, LFOLVL ** lfolvl, LVL ** lvl, U32 * nolfo,
47 		  U32 * nooflvl, U32 offset, U32 len, wvStream * fd)
48 {
49     U32 i;
50     U32 end;
51     *nooflvl = 0;
52     wvTrace (("lfo begins at %x len %d\n", offset, len));
53     wvStream_offset_from_end (fd, 0);
54     end = wvStream_tell (fd);
55     wvGetLFO_PLF (lfo, nolfo, offset, len, fd);
56 
57     for (i = 0; i < *nolfo; i++)
58 	*nooflvl += (*lfo)[i].clfolvl;
59     wvTrace (("pos %x %d\n", wvStream_tell (fd), *nooflvl));
60     wvTrace (("nolfo is %d nooflvl is %d\n", *nolfo, *nooflvl));
61 
62     if ((*nooflvl == 0) ||
63 	multiplication_will_overflow(sizeof (LFOLVL), *nooflvl) ||
64 	multiplication_will_overflow(sizeof (LVL), *nooflvl))
65       {
66 	  *lfolvl = NULL;
67 	  *lvl = NULL;
68 	  return (0);
69       }
70 
71     *lfolvl = (LFOLVL *) wvMalloc (sizeof (LFOLVL) * *nooflvl);
72     *lvl = (LVL *) wvMalloc (sizeof (LVL) * *nooflvl);
73 
74     i = 0;
75     while (i < *nooflvl)
76       {
77 	  wvInitLVL (&((*lvl)[i]));
78 	  wvTrace (("%d pos now %x %d\n", i, wvStream_tell (fd), *nooflvl));
79 	  if (wvStream_tell (fd) == end)
80 	    {
81 		wvWarning
82 		    ("LFOLVL off the end of the file, continuing anyway\n");
83 		i++;
84 		continue;
85 	    }
86 	  wvGetLFOLVL (&((*lfolvl)[i]), fd);
87 #if 0
88 	  if (wvInvalidLFOLVL (&((*lfolvl)[i])))
89 	      continue;
90 #endif
91 	  if ((*lfolvl)[i].fFormatting)
92 	    {
93 		wvTrace (("formatting set\n"));
94 		wvGetLVL (&((*lvl)[i]), fd);
95 	    }
96 	  i++;
97       }
98     return (0);
99 }
100 
101 int
wvGetLFO_PLF(LFO ** lfo,U32 * nolfo,U32 offset,U32 len,wvStream * fd)102 wvGetLFO_PLF (LFO ** lfo, U32 * nolfo, U32 offset, U32 len, wvStream * fd)
103 {
104     U32 i;
105     if (len == 0)
106       {
107 	  *lfo = NULL;
108 	  *nolfo = 0;
109       }
110     else
111       {
112 	  wvStream_goto (fd, offset);
113 	  *nolfo = read_32ubit (fd);
114 	  wvTrace (("%d\n", *nolfo));
115 
116 	  /* check for integer overflow */
117 	  if (multiplication_will_overflow(*nolfo, sizeof(LFO))) {
118 	    wvError (("Malicious document!\n"));
119 	    *nolfo = 0;
120 	    return (1);
121 	  } else {
122 	    *lfo = (LFO *) wvMalloc (*nolfo * sizeof(LFO));
123 	    if (*lfo == NULL)
124 	      {
125 		wvError (("NO MEM 1, failed to alloc %d bytes\n",
126 			  *nolfo * sizeof (LFO)));
127 		return (1);
128 	      }
129 	    for (i = 0; i < *nolfo; i++)
130 	      wvGetLFO (&((*lfo)[i]), fd);
131 	  }
132       }
133     return (0);
134 }
135 
136 void
wvGetLFO(LFO * item,wvStream * fd)137 wvGetLFO (LFO * item, wvStream * fd)
138 {
139     int i;
140     item->lsid = read_32ubit (fd);
141     item->reserved1 = read_32ubit (fd);
142     item->reserved2 = read_32ubit (fd);
143     item->clfolvl = read_8ubit (fd);
144     for (i = 0; i < 3; i++)
145 	item->reserved3[i] = read_8ubit (fd);
146 }
147 
148 void
wvInitLFO(LFO * item)149 wvInitLFO (LFO * item)
150 {
151     int i;
152     item->lsid = 0;
153     item->reserved1 = 0;
154     item->reserved2 = 0;
155     item->clfolvl = 0;
156     for (i = 0; i < 3; i++)
157 	item->reserved3[i] = 0;
158 }
159 
160 void
wvGetLFOLVL(LFOLVL * item,wvStream * fd)161 wvGetLFOLVL (LFOLVL * item, wvStream * fd)
162 {
163     U8 temp8;
164 #ifdef PURIFY
165     wvInitLFOLVL (item);
166 #endif
167     item->iStartAt = read_32ubit (fd);
168 
169     while (wvInvalidLFOLVL (item))
170       {
171 	  wvTrace (("pos %x\n", wvStream_tell (fd)));
172 	  item->iStartAt = read_32ubit (fd);
173       }
174 
175     temp8 = read_8ubit (fd);
176     item->ilvl = temp8 & 0x0F;
177     item->fStartAt = (temp8 & 0x10) >> 4;
178     item->fFormatting = (temp8 & 0x20) >> 5;
179     item->reserved1 = (temp8 & 0xC0) >> 6;
180     item->reserved2 = read_8ubit (fd);
181     item->reserved3 = read_8ubit (fd);
182     item->reserved4 = read_8ubit (fd);
183 }
184 
185 void
wvInitLFOLVL(LFOLVL * item)186 wvInitLFOLVL (LFOLVL * item)
187 {
188     item->iStartAt = 0;
189     item->ilvl = 0;
190     item->fStartAt = 0;
191     item->fFormatting = 0;
192     item->reserved1 = 0;
193     item->reserved2 = 0;
194     item->reserved3 = 0;
195     item->reserved4 = 0;
196 }
197 
198 int
wvInvalidLFOLVL(LFOLVL * item)199 wvInvalidLFOLVL (LFOLVL * item)
200 {
201 
202     if (item->iStartAt != 0xffffffff)
203 	return (0);
204 #if 0
205     /*
206        a bloody russian doc, from Sergey V. Udaltsov <svu@pop.convey.ru> caused
207        the removal of this section
208      */
209     if (item->ilvl != 0xf)
210 	return (0);
211     if (item->fStartAt != 1)
212 	return (0);
213     if (item->fFormatting != 1)
214 	return (0);
215     if (item->reserved1 != 0x3)
216 	return (0);
217     if (item->reserved2 != 0xff)
218 	return (0);
219     if (item->reserved3 != 0xff)
220 	return (0);
221     if (item->reserved4 != 0xff)
222 	return (0);
223 #endif
224     wvWarning (("invalid list entry, trucking along happily anyway\n"));
225     return (1);
226 }
227 
228 int
wvReleaseLFO_records(LFO ** lfo,LFOLVL ** lfolvl,LVL ** lvl,U32 nooflvl)229 wvReleaseLFO_records (LFO ** lfo, LFOLVL ** lfolvl, LVL ** lvl, U32 nooflvl)
230 {
231     U32 i;
232     wvTrace (("releasing %d lvl records\n", nooflvl));
233     wvFree (*lfo);
234     wvFree (*lfolvl);
235     for (i = 0; i < nooflvl; i++)
236 	wvReleaseLVL (&((*lvl)[i]));
237     wvFree (*lvl);
238     return (0);
239 }
240