diff options
| author | arseny.kapoulkine <arseny.kapoulkine@99668b35-9821-0410-8761-19e4c4f06640> | 2010-09-20 21:26:21 +0000 | 
|---|---|---|
| committer | arseny.kapoulkine <arseny.kapoulkine@99668b35-9821-0410-8761-19e4c4f06640> | 2010-09-20 21:26:21 +0000 | 
| commit | 21b129a7e49f25b1963f3371a910272725013dff (patch) | |
| tree | c0ba2d47e8ad715172a5dc8f618c77978a9a9343 /src | |
| parent | b84eb7bdba7cb56b880c62a83eadd14108cac2db (diff) | |
Improved large file support: added overflow checks, _ftelli64/_fseeki64 are used on MSVC
git-svn-id: http://pugixml.googlecode.com/svn/trunk@743 99668b35-9821-0410-8761-19e4c4f06640
Diffstat (limited to 'src')
| -rw-r--r-- | src/pugixml.cpp | 38 | 
1 files changed, 31 insertions, 7 deletions
diff --git a/src/pugixml.cpp b/src/pugixml.cpp index 24b4a6a..5c327ff 100644 --- a/src/pugixml.cpp +++ b/src/pugixml.cpp @@ -2981,34 +2981,58 @@ namespace  	{  		if (!file) return make_parse_result(status_file_not_found); +		// we need to get length of entire file to load it in memory; the only (relatively) sane way to do it is via seek/tell trick +	#if defined(_MSC_VER) && _MSC_VER >= 1400 +		// there are 64-bit versions of fseek/ftell, let's use them +		typedef __int64 length_type; + +		_fseeki64(file, 0, SEEK_END); +		length_type length = _ftelli64(file); +		_fseeki64(file, 0, SEEK_SET); +	#else +		// if this is a 32-bit OS, long is enough; if this is a unix system, long is 64-bit, which is enough; otherwise we can't do anything anyway. +		typedef long length_type; +  		fseek(file, 0, SEEK_END); -		long length = ftell(file); +		length_type length = ftell(file);  		fseek(file, 0, SEEK_SET); +	#endif +		// check for I/O errors  		if (length < 0)  		{  			fclose(file);  			return make_parse_result(status_io_error);  		} -		char* s = static_cast<char*>(global_allocate(length > 0 ? length : 1)); +		// check for overflow +		if (static_cast<length_type>(static_cast<size_t>(length)) != length) +		{ +			fclose(file); +			return make_parse_result(status_out_of_memory); +		} + +		// allocate buffer for the whole file +		size_t size = static_cast<size_t>(length); +		char* contents = static_cast<char*>(global_allocate(length > 0 ? size : 1)); -		if (!s) +		if (!contents)  		{  			fclose(file);  			return make_parse_result(status_out_of_memory);  		} -		size_t read = fread(s, 1, (size_t)length, file); +		// read file in memory +		size_t read_size = fread(contents, 1, size, file);  		fclose(file); -		if (read != (size_t)length) +		if (read_size != size)  		{ -			global_deallocate(s); +			global_deallocate(contents);  			return make_parse_result(status_io_error);  		} -		return doc.load_buffer_inplace_own(s, length, options, encoding); +		return doc.load_buffer_inplace_own(contents, size, options, encoding);  	}  #ifndef PUGIXML_NO_STL  | 
