ObjFW  Check-in [e86d11f124]

Overview
Comment:OFZIPArchive: Improve signedness & range checks
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: e86d11f124b521bb20f021d457874f5f5df51a2f443a45cace35b633a2265609
User & Date: js on 2017-08-06 20:06:41
Other Links: manifest | tags
Context
2017-08-06
20:10
ofzip: Only print extraField if it exists check-in: b1356cb2f1 user: js tags: trunk
20:06
OFZIPArchive: Improve signedness & range checks check-in: e86d11f124 user: js tags: trunk
19:40
OFZIPArchive: Add write and append support check-in: 4594f434e7 user: js tags: trunk
Changes

Modified src/OFZIPArchive.m from [93d7047dfd] to [2160df43d2].

89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
@end

@interface OFZIPArchive_FileWriteStream: OFStream
{
	OFStream *_stream;
	uint32_t _CRC32;
@public
	uint64_t _bytesWritten;
	OFMutableZIPArchiveEntry *_entry;
}

- initWithStream: (OFStream *)stream
	   entry: (OFMutableZIPArchiveEntry *)entry;
@end








|







89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
@end

@interface OFZIPArchive_FileWriteStream: OFStream
{
	OFStream *_stream;
	uint32_t _CRC32;
@public
	int64_t _bytesWritten;
	OFMutableZIPArchiveEntry *_entry;
}

- initWithStream: (OFStream *)stream
	   entry: (OFMutableZIPArchiveEntry *)entry;
@end

399
400
401
402
403
404
405



406
407
408
409
410
411
412
	if ((_mode == OF_ZIP_ARCHIVE_MODE_WRITE ||
	    _mode == OF_ZIP_ARCHIVE_MODE_APPEND) &&
	    [_lastReturnedStream isKindOfClass:
	    [OFZIPArchive_FileWriteStream class]]) {
		OFZIPArchive_FileWriteStream *stream =
		    (OFZIPArchive_FileWriteStream *)_lastReturnedStream;




		_offset += stream->_bytesWritten;

		if (stream->_entry != nil) {
			[_entries addObject: stream->_entry];
			[_pathToEntryMap setObject: stream->_entry
					    forKey: [stream->_entry fileName]];
		}







>
>
>







399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
	if ((_mode == OF_ZIP_ARCHIVE_MODE_WRITE ||
	    _mode == OF_ZIP_ARCHIVE_MODE_APPEND) &&
	    [_lastReturnedStream isKindOfClass:
	    [OFZIPArchive_FileWriteStream class]]) {
		OFZIPArchive_FileWriteStream *stream =
		    (OFZIPArchive_FileWriteStream *)_lastReturnedStream;

		if (INT64_MAX - _offset < stream->_bytesWritten)
			@throw [OFOutOfRangeException exception];

		_offset += stream->_bytesWritten;

		if (stream->_entry != nil) {
			[_entries addObject: stream->_entry];
			[_pathToEntryMap setObject: stream->_entry
					    forKey: [stream->_entry fileName]];
		}
466
467
468
469
470
471
472

473
474
475
476
477
478
479
{
	/* TODO: Avoid data descriptor when _stream is an OFSeekableStream */
	void *pool;
	OFMutableZIPArchiveEntry *entry;
	OFString *fileName;
	OFData *extraField;
	uint16_t fileNameLength, extraFieldLength;


	if (_mode != OF_ZIP_ARCHIVE_MODE_WRITE &&
	    _mode != OF_ZIP_ARCHIVE_MODE_APPEND)
		@throw [OFInvalidArgumentException exception];

	pool = objc_autoreleasePoolPush();
	entry = [[entry_ mutableCopy] autorelease];







>







469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
{
	/* TODO: Avoid data descriptor when _stream is an OFSeekableStream */
	void *pool;
	OFMutableZIPArchiveEntry *entry;
	OFString *fileName;
	OFData *extraField;
	uint16_t fileNameLength, extraFieldLength;
	int64_t offsetAdd = 0;

	if (_mode != OF_ZIP_ARCHIVE_MODE_WRITE &&
	    _mode != OF_ZIP_ARCHIVE_MODE_APPEND)
		@throw [OFInvalidArgumentException exception];

	pool = objc_autoreleasePoolPush();
	entry = [[entry_ mutableCopy] autorelease];
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530





531
532
533
534
535
536
537
	[_stream writeLittleEndianInt16: [entry compressionMethod]];
	[_stream writeLittleEndianInt16: [entry of_lastModifiedFileTime]];
	[_stream writeLittleEndianInt16: [entry of_lastModifiedFileDate]];
	/* We use the data descriptor */
	[_stream writeLittleEndianInt32: 0];
	[_stream writeLittleEndianInt32: 0];
	[_stream writeLittleEndianInt32: 0];
	_offset += 4 + (5 * 2) + (3 * 4);

	fileName = [entry fileName];
	fileNameLength = [fileName UTF8StringLength];
	extraField = [entry extraField];
	extraFieldLength = [extraField count];

	[_stream writeLittleEndianInt16: fileNameLength];
	[_stream writeLittleEndianInt16: extraFieldLength];
	_offset += 2 * 2;

	[_stream writeString: fileName];
	if (extraField != nil)
		[_stream writeData: extraField];
	_offset += fileNameLength + extraFieldLength;






	_lastReturnedStream = [[OFZIPArchive_FileWriteStream alloc]
	     initWithStream: _stream
		      entry: entry];

	objc_autoreleasePoolPop(pool);








|








|




|
>
>
>
>
>







513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
	[_stream writeLittleEndianInt16: [entry compressionMethod]];
	[_stream writeLittleEndianInt16: [entry of_lastModifiedFileTime]];
	[_stream writeLittleEndianInt16: [entry of_lastModifiedFileDate]];
	/* We use the data descriptor */
	[_stream writeLittleEndianInt32: 0];
	[_stream writeLittleEndianInt32: 0];
	[_stream writeLittleEndianInt32: 0];
	offsetAdd += 4 + (5 * 2) + (3 * 4);

	fileName = [entry fileName];
	fileNameLength = [fileName UTF8StringLength];
	extraField = [entry extraField];
	extraFieldLength = [extraField count];

	[_stream writeLittleEndianInt16: fileNameLength];
	[_stream writeLittleEndianInt16: extraFieldLength];
	offsetAdd += 2 * 2;

	[_stream writeString: fileName];
	if (extraField != nil)
		[_stream writeData: extraField];
	offsetAdd += fileNameLength + extraFieldLength;

	if (INT64_MAX - _offset < offsetAdd)
		@throw [OFOutOfRangeException exception];

	_offset += offsetAdd;

	_lastReturnedStream = [[OFZIPArchive_FileWriteStream alloc]
	     initWithStream: _stream
		      entry: entry];

	objc_autoreleasePoolPop(pool);

813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833

	[super dealloc];
}

- (void)lowlevelWriteBuffer: (const void *)buffer
		     length: (size_t)length
{
	if (length > INT64_MAX || INT64_MAX - _bytesWritten < length)
		@throw [OFOutOfRangeException exception];

	[_stream writeBuffer: buffer
		      length: length];

	_bytesWritten += length;
	_CRC32 = of_crc32(_CRC32, buffer, length);
}

- (void)close
{
	uint32_t bytesWritten;








|





|







822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842

	[super dealloc];
}

- (void)lowlevelWriteBuffer: (const void *)buffer
		     length: (size_t)length
{
	if (length > INT64_MAX || INT64_MAX - _bytesWritten < (int64_t)length)
		@throw [OFOutOfRangeException exception];

	[_stream writeBuffer: buffer
		      length: length];

	_bytesWritten += (int64_t)length;
	_CRC32 = of_crc32(_CRC32, buffer, length);
}

- (void)close
{
	uint32_t bytesWritten;