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