Bug 9411 - LockFile() + !HAVE_LARGE_FILE_SUPPORT + length=long.MaxValue = exception
Summary: LockFile() + !HAVE_LARGE_FILE_SUPPORT + length=long.MaxValue = exception
Status: RESOLVED FIXED
Alias: None
Product: Runtime
Classification: Mono
Component: io-layer ()
Version: unspecified
Hardware: PC Mac OS
: --- normal
Target Milestone: ---
Assignee: Bugzilla
URL:
Depends on:
Blocks:
 
Reported: 2013-01-09 00:17 UTC by Jonathan Pryor
Modified: 2013-01-09 12:01 UTC (History)
2 users (show)

Tags:
Is this bug a regression?: ---
Last known good build:

Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.


Please create a new report on GitHub or Developer Community with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:
Status:
RESOLVED FIXED

Description Jonathan Pryor 2013-01-09 00:17:35 UTC
Context:

http://forums.xamarin.com/discussion/738/problems-with-filestream-lock/
http://lists.ximian.com/pipermail/mono-devel-list/2013-January/039981.html

The following fails on platforms that do _not_ have "large file support":

	using (var f = File.Create (Path.Combine (
			Environment.GetFolderPath (Environment.SpecialFolder.Personal),
			"foo.dat"))) {
		f.Lock (0, long.MaxValue);

It dies with:

> System.IO.IOException: Lock violation on path /data/data/Scratch.FileLocking/files/foo.dat
>   at System.IO.FileStream.Lock (Int64 position, Int64 length) [0x00000] in <filename unknown>:0 

The reason why: signed/unsigned mismatch.

LockFile() takes "logical" 64-bit offset and length values which are split into "high" and "low" values, and uses these values to call _wapi_lock_file_region(). The problem is the !HAVE_LARGE_FILE_SUPPORT block:

https://github.com/mono/mono/blob/master/mono/io-layer/locking.c#L117

	offset = offset_low;
	length = length_low;

offset and length are `off_t`, and on non-large-file-support platforms `off_t` is a 32-bit int. Due to the value masking performed in ves_icall_System_IO_MonoIO_Lock(), length_low will be 0xFFFFFFFF (which is correct!), and thus the value of `length` will be -1 (which is the bug).

A plausible fix would be to change the offset & length assignment to instead be:

	offset = offset_low > INT_MAX ? INT_MAX : offset_low;
	length = length_low > INT_MAX ? INT_MAX : length_low;
Comment 1 Jonathan Pryor 2013-01-09 00:21:24 UTC
ALTERNATIVELY: LockFile() should error out when we're on a 32-bit only platform and a 64-bit offset/region has been specified.

Alas, LockFile() doesn't specify an error to return when a "bad" offset is specified, so I'm not sure what's "correct". Erroring out seems to be the saner thing to do, though, as silently altering (truncating!) file offset + region lock length seems like a Bad Idea™.
Comment 2 Jonathan Pryor 2013-01-09 12:01:44 UTC
> The following fails on platforms that do _not_ have "large file support":

It should fail; this is correct behavior.

The "problem" is that the error doesn't tell you what the error is:

> System.IO.IOException: Lock violation on path ...

Why is there a lock violation? There isn't one; the problem is that a parameter is invalid.

Fixed in master/6c5d76dd by checking for the overflows and setting ERROR_INVALID_PARAMETER instead of ERROR_LOCK_VIOLATION when LockFIle() is given unsupportable parameters.