ObjFW  Check-in [d7e496ba27]

Overview
Comment:OFLHAArchiveEntry: Skip level 2/3 header padding
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: d7e496ba275f7374f5b5183e80fd7260cd05c562fdf6dc4270164a81fa7300aa
User & Date: js on 2024-02-27 19:44:06
Other Links: manifest | tags
Context
2024-02-27
20:21
Minor documentation fix check-in: 402b0a26e6 user: js tags: trunk
19:52
OFLHAArchiveEntry: Skip level 2 header padding check-in: 657514726f user: js tags: 1.0
19:44
OFLHAArchiveEntry: Skip level 2/3 header padding check-in: d7e496ba27 user: js tags: trunk
00:57
OFStream: Minor documentation fix check-in: ed4319fab0 user: js tags: trunk
Changes

Modified src/OFLHAArchiveEntry.m from [2adb105405] to [49afc93b6c].

258
259
260
261
262
263
264
265
266
267
268


269
270
271
272
273
274

275
276


277
278
279
280
281
282
283
284
285

286
287
288
289
290
291
292
293
294
295
296


297
298
299
300
301
302
303
	if (function == NULL)
		return false;

	function(entry, extension, encoding);
	return true;
}

static void
readExtensions(OFLHAArchiveEntry *entry, OFStream *stream,
    OFStringEncoding encoding, bool allowFileName)
{


	for (;;) {
		uint32_t size;
		OFData *extension;

		if (entry->_headerLevel == 3)
			size = [stream readLittleEndianInt32];

		else
			size = [stream readLittleEndianInt16];



		if (size == 0)
			break;

		if (size < 2 || (entry->_headerLevel == 3 && size < 4))
			@throw [OFInvalidFormatException exception];

		extension = [stream readDataWithCount:
		    size - (entry->_headerLevel == 3 ? 4 : 2)];


		if (!parseExtension(entry, extension, encoding, allowFileName))
			[entry->_extensions addObject: extension];

		if (entry->_headerLevel == 1) {
			if (entry->_compressedSize < size)
				@throw [OFInvalidFormatException exception];

			entry->_compressedSize -= size;
		}
	}


}

static void
getFileNameAndDirectoryName(OFLHAArchiveEntry *entry, OFStringEncoding encoding,
    const char **fileName, size_t *fileNameLength,
    const char **directoryName, size_t *directoryNameLength)
{







|



>
>




|

>
|

>
>









>











>
>







258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
	if (function == NULL)
		return false;

	function(entry, extension, encoding);
	return true;
}

static size_t
readExtensions(OFLHAArchiveEntry *entry, OFStream *stream,
    OFStringEncoding encoding, bool allowFileName)
{
	size_t consumed = 0;

	for (;;) {
		uint32_t size;
		OFData *extension;

		if (entry->_headerLevel == 3) {
			size = [stream readLittleEndianInt32];
			consumed += 4;
		} else {
			size = [stream readLittleEndianInt16];
			consumed += 2;
		}

		if (size == 0)
			break;

		if (size < 2 || (entry->_headerLevel == 3 && size < 4))
			@throw [OFInvalidFormatException exception];

		extension = [stream readDataWithCount:
		    size - (entry->_headerLevel == 3 ? 4 : 2)];
		consumed += extension.count;

		if (!parseExtension(entry, extension, encoding, allowFileName))
			[entry->_extensions addObject: extension];

		if (entry->_headerLevel == 1) {
			if (entry->_compressedSize < size)
				@throw [OFInvalidFormatException exception];

			entry->_compressedSize -= size;
		}
	}

	return consumed;
}

static void
getFileNameAndDirectoryName(OFLHAArchiveEntry *entry, OFStringEncoding encoding,
    const char **fileName, size_t *fileNameLength,
    const char **directoryName, size_t *directoryNameLength)
{
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440


441
442
443
444
445
446
447
448
449


450






451



















452
453
454
455
456
457
458
				 * 1 for the operating system identifier, 2
				 * because we don't want to skip the size of
				 * the next extended header.
				 */
				extendedAreaSize -= 1 + 2;
			}

			/* Skip extended area. */
			if ([stream isKindOfClass: [OFSeekableStream class]])
				[(OFSeekableStream *)stream
				    seekToOffset: extendedAreaSize
					  whence: OFSeekCurrent];
			else {
				char buffer[256];

				while (extendedAreaSize > 0)
					extendedAreaSize -= [stream
					    readIntoBuffer: buffer
						    length: extendedAreaSize];
			}

			if (_headerLevel == 1)
				readExtensions(self, stream, encoding, false);

			objc_autoreleasePoolPop(pool);
			break;
		case 2:
		case 3:


			_modificationDate = [[OFDate alloc]
			    initWithTimeIntervalSince1970: date];

			_CRC16 = [stream readLittleEndianInt16];
			_operatingSystemIdentifier = [stream readInt8];

			if (_headerLevel == 3)
				/* Size of header. Ignored. */
				[stream readLittleEndianInt32];









			readExtensions(self, stream, encoding, true);




















			break;
		default:;
			OFString *version = [OFString
			    stringWithFormat: @"%u", _headerLevel];

			@throw [OFUnsupportedVersionException







|



















|
>
>







|
|
>
>

>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
				 * 1 for the operating system identifier, 2
				 * because we don't want to skip the size of
				 * the next extended header.
				 */
				extendedAreaSize -= 1 + 2;
			}

			/* Skip extended area */
			if ([stream isKindOfClass: [OFSeekableStream class]])
				[(OFSeekableStream *)stream
				    seekToOffset: extendedAreaSize
					  whence: OFSeekCurrent];
			else {
				char buffer[256];

				while (extendedAreaSize > 0)
					extendedAreaSize -= [stream
					    readIntoBuffer: buffer
						    length: extendedAreaSize];
			}

			if (_headerLevel == 1)
				readExtensions(self, stream, encoding, false);

			objc_autoreleasePoolPop(pool);
			break;
		case 2:
		case 3:;
			uint32_t padding = 0;

			_modificationDate = [[OFDate alloc]
			    initWithTimeIntervalSince1970: date];

			_CRC16 = [stream readLittleEndianInt16];
			_operatingSystemIdentifier = [stream readInt8];

			if (_headerLevel == 3)
				/* Size of entire header */
				padding = [stream readLittleEndianInt32];
			else
				padding = (header[1] << 8) | header[0];

			/*
			 * 21 for header, 2 for CRC16, 1 for operating system
			 * identifier.
			 */
			padding -= 21 + 2 + 1;

			padding -= readExtensions(self, stream, encoding, true);

			/* Skip padding */
			if ([stream isKindOfClass: [OFSeekableStream class]])
				[(OFSeekableStream *)stream
				    seekToOffset: padding
					  whence: OFSeekCurrent];
			else {
				while (padding > 0) {
					char buffer[512];
					size_t min = padding;

					if (min > 512)
						min = 512;

					padding -= [stream
					    readIntoBuffer: buffer
						    length: min];
				}
			}

			break;
		default:;
			OFString *version = [OFString
			    stringWithFormat: @"%u", _headerLevel];

			@throw [OFUnsupportedVersionException