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