1package plist
2
3import (
4	"bytes"
5	"testing"
6)
7
8/*
9	[]byte{
10		'b', 'p', 'l', 'i', 's', 't', '0', '0', // Magic
11
12		// Object Table
13		// Offset Table
14
15		// Trailer
16		0x00, 0x00, 0x00, 0x00, 0x00, //  - U8[5] Unused
17		0x01,                      //  - U8    Sort Version
18		0x01,                      //  - U8    Offset Table Entry Size (#bytes)
19		0x01,                      //  - U8    Object Reference Size (#bytes)
20		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //  - U64   # Objects
21		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //  - U64   Top Object
22		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //  - U64   Offset Table Offset
23	},
24*/
25
26var InvalidBplists = [][]byte{
27	// Too short
28	[]byte{
29		'b', 'p', 'l', 'i', 's', 't', '0', '0',
30		0x00,
31	},
32	// Bad magic
33	[]byte{
34		'x', 'p', 'l', 'i', 's', 't', '0', '0',
35
36		0x00,
37		0x08,
38
39		0x00, 0x00, 0x00, 0x00, 0x00,
40		0x00,
41		0x01,
42		0x01,
43		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
44		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
45		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09,
46	},
47	// Bad version
48	[]byte{
49		'b', 'p', 'l', 'i', 's', 't', '3', '0',
50
51		0x00,
52		0x08,
53
54		0x00, 0x00, 0x00, 0x00, 0x00,
55		0x00,
56		0x01,
57		0x01,
58		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
59		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
60		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09,
61	},
62	// Bad version II
63	[]byte{
64		'b', 'p', 'l', 'i', 's', 't', '@', 'A',
65
66		0x00,
67		0x08,
68
69		0x00, 0x00, 0x00, 0x00, 0x00,
70		0x00,
71		0x01,
72		0x01,
73		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
74		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
75		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09,
76	},
77	// Offset table inside trailer
78	[]byte{
79		'b', 'p', 'l', 'i', 's', 't', '0', '0',
80
81		0x00, 0x00, 0x00, 0x00, 0x00,
82		0x00,
83		0x01,
84		0x01,
85		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
86		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
87		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A,
88	},
89	// Offset table inside header
90	[]byte{
91		'b', 'p', 'l', 'i', 's', 't', '0', '0',
92
93		0x00, 0x00, 0x00, 0x00, 0x00,
94		0x00,
95		0x01,
96		0x01,
97		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
98		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
99		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
100	},
101	// Offset table off end of file
102	[]byte{
103		'b', 'p', 'l', 'i', 's', 't', '0', '0',
104
105		0x00, 0x00, 0x00, 0x00, 0x00,
106		0x00,
107		0x01,
108		0x01,
109		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
110		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
111		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00,
112	},
113	// Garbage between offset table and trailer
114	[]byte{
115		'b', 'p', 'l', 'i', 's', 't', '0', '0',
116
117		0x00,
118		0x09,
119
120		0xAB, 0xCD,
121
122		0x00, 0x00, 0x00, 0x00, 0x00,
123		0x00,
124		0x01,
125		0x01,
126		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
127		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
128		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A,
129	},
130	// Top Object out of range
131	[]byte{
132		'b', 'p', 'l', 'i', 's', 't', '0', '0',
133
134		0x00,
135		0x08,
136
137		0x00, 0x00, 0x00, 0x00, 0x00,
138		0x00,
139		0x01,
140		0x01,
141		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
142		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
143		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09,
144	},
145	// Object out of range
146	[]byte{
147		'b', 'p', 'l', 'i', 's', 't', '0', '0',
148
149		0x00,
150		0xFF,
151
152		0x00, 0x00, 0x00, 0x00, 0x00,
153		0x00,
154		0x01,
155		0x01,
156		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
157		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
158		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09,
159	},
160	// Object references too small (1 byte, but 257 objects)
161	[]byte{
162		'b', 'p', 'l', 'i', 's', 't', '0', '0',
163
164		0x00,
165
166		// 257 bytes worth of object table
167		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
168		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
169		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
170		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
171		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
172		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
173		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
174		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
175		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
176		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
177		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
178		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
179		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
180		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
181		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
182		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
183		0x00,
184
185		0x00, 0x00, 0x00, 0x00, 0x00,
186		0x00,
187		0x01,
188		0x01,
189		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
190		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
191		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09,
192	},
193	// Offset references too small (1 byte, but 257 bytes worth of objects)
194	[]byte{
195		'b', 'p', 'l', 'i', 's', 't', '0', '0',
196
197		// 257 bytes worth of "objects"
198		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
199		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
200		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
201		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
202		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
203		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
204		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
205		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
206		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
207		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
208		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
209		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
210		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
211		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
212		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
213		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
214		0x00,
215
216		0x00,
217
218		0x00, 0x00, 0x00, 0x00, 0x00,
219		0x00,
220		0x01,
221		0x01,
222		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
223		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
224		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x09,
225	},
226	// Too many objects
227	[]byte{
228		'b', 'p', 'l', 'i', 's', 't', '0', '0',
229
230		0x00,
231		0x08,
232
233		0x00, 0x00, 0x00, 0x00, 0x00,
234		0x00,
235		0x01,
236		0x01,
237		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
238		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
239		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09,
240	},
241	// String way too long
242	[]byte{
243		'b', 'p', 'l', 'i', 's', 't', '0', '0',
244
245		0x5F, 0x10, 0xFF,
246		0x08,
247
248		0x00, 0x00, 0x00, 0x00, 0x00,
249		0x00,
250		0x01,
251		0x01,
252		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
253		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
254		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B,
255	},
256	// UTF-16 String way too long
257	[]byte{
258		'b', 'p', 'l', 'i', 's', 't', '0', '0',
259
260		0x6F, 0x10, 0xFF,
261		0x08,
262
263		0x00, 0x00, 0x00, 0x00, 0x00,
264		0x00,
265		0x01,
266		0x01,
267		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
268		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
269		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B,
270	},
271	// Data way too long
272	[]byte{
273		'b', 'p', 'l', 'i', 's', 't', '0', '0',
274
275		0x4F, 0x10, 0xFF,
276		0x08,
277
278		0x00, 0x00, 0x00, 0x00, 0x00,
279		0x00,
280		0x01,
281		0x01,
282		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
283		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
284		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B,
285	},
286	// Array way too long
287	[]byte{
288		'b', 'p', 'l', 'i', 's', 't', '0', '0',
289
290		0xAF, 0x10, 0xFF,
291		0x08,
292
293		0x00, 0x00, 0x00, 0x00, 0x00,
294		0x00,
295		0x01,
296		0x01,
297		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
298		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
299		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B,
300	},
301	// Dictionary way too long
302	[]byte{
303		'b', 'p', 'l', 'i', 's', 't', '0', '0',
304
305		0xDF, 0x10, 0xFF,
306		0x08,
307
308		0x00, 0x00, 0x00, 0x00, 0x00,
309		0x00,
310		0x01,
311		0x01,
312		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
313		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
314		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B,
315	},
316	// Array self-referential
317	[]byte{
318		'b', 'p', 'l', 'i', 's', 't', '0', '0',
319
320		0xA1, 0x00,
321
322		0x08,
323
324		0x00, 0x00, 0x00, 0x00, 0x00,
325		0x00,
326		0x01,
327		0x01,
328		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
329		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
330		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A,
331	},
332	// Dictionary self-referential key
333	[]byte{
334		'b', 'p', 'l', 'i', 's', 't', '0', '0',
335
336		0xD1, 0x00, 0x01,
337		0x50, // 0-byte string
338
339		0x08, 0x0B,
340
341		0x00, 0x00, 0x00, 0x00, 0x00,
342		0x00,
343		0x01,
344		0x01,
345		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
346		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
347		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C,
348	},
349	// Dictionary self-referential value
350	[]byte{
351		'b', 'p', 'l', 'i', 's', 't', '0', '0',
352
353		0xD1, 0x01, 0x00,
354		0x50, // 0-byte string
355
356		0x08, 0x0B,
357
358		0x00, 0x00, 0x00, 0x00, 0x00,
359		0x00,
360		0x01,
361		0x01,
362		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
363		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
364		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C,
365	},
366	// Dictionary non-string key
367	[]byte{
368		'b', 'p', 'l', 'i', 's', 't', '0', '0',
369
370		0xD1, 0x01, 0x02,
371		0x08,
372		0x09,
373
374		0x08, 0x0B, 0x0C,
375
376		0x00, 0x00, 0x00, 0x00, 0x00,
377		0x00,
378		0x01,
379		0x01,
380		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
381		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
382		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D,
383	},
384	// Array contains invalid reference
385	[]byte{
386		'b', 'p', 'l', 'i', 's', 't', '0', '0',
387
388		0xA1, 0x0F,
389
390		0x08,
391
392		0x00, 0x00, 0x00, 0x00, 0x00,
393		0x00,
394		0x01,
395		0x01,
396		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
397		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
398		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A,
399	},
400	// Dictionary contains invalid reference
401	[]byte{
402		'b', 'p', 'l', 'i', 's', 't', '0', '0',
403
404		0xD1, 0x01, 0x0F,
405		0x50, // 0-byte string
406
407		0x08, 0x0B,
408
409		0x00, 0x00, 0x00, 0x00, 0x00,
410		0x00,
411		0x01,
412		0x01,
413		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
414		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
415		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C,
416	},
417	// Invalid float ("7-byte")
418	[]byte{
419		'b', 'p', 'l', 'i', 's', 't', '0', '0',
420
421		0x27,
422
423		0x08,
424
425		0x00, 0x00, 0x00, 0x00, 0x00,
426		0x00,
427		0x01,
428		0x01,
429		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
430		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
431		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09,
432	},
433	// Invalid integer (8^5)
434	[]byte{
435		'b', 'p', 'l', 'i', 's', 't', '0', '0',
436
437		0x15,
438
439		0x08,
440
441		0x00, 0x00, 0x00, 0x00, 0x00,
442		0x00,
443		0x01,
444		0x01,
445		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
446		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
447		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09,
448	},
449	// Invalid atom
450	[]byte{
451		'b', 'p', 'l', 'i', 's', 't', '0', '0',
452
453		0xFF,
454
455		0x08,
456
457		0x00, 0x00, 0x00, 0x00, 0x00,
458		0x00,
459		0x01,
460		0x01,
461		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
462		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
463		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09,
464	},
465
466	// array refers to self through a second level
467	[]byte{
468		'b', 'p', 'l', 'i', 's', 't', '0', '0',
469
470		0xA1, 0x01,
471		0xA1, 0x00,
472
473		0x08, 0x0A,
474
475		0x00, 0x00, 0x00, 0x00, 0x00,
476		0x00,
477		0x01,
478		0x01,
479		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
480		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
481		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C,
482	},
483}
484
485func TestInvalidBinaryPlists(t *testing.T) {
486	for _, data := range InvalidBplists {
487		buf := bytes.NewReader(data)
488		d := newBplistParser(buf)
489		_, err := d.parseDocument()
490		if err == nil {
491			t.Fatal("invalid plist failed to throw error")
492		} else {
493			t.Log(err)
494		}
495	}
496}
497