WineHQ
Bug Tracking Database – Bug 48471

 Bugzilla

 

Last modified: 2020-08-15 17:02:37 UTC  

Mismatching behavior of GetEnvironmentVariableW for empty / long values

Bug 48471 - Mismatching behavior of GetEnvironmentVariableW for empty / long values
Mismatching behavior of GetEnvironmentVariableW for empty / long values
Status: CLOSED FIXED
AppDB: Show Apps affected by this bug
Product: Wine
Classification: Unclassified
Component: kernel32
5.0-rc4
x86 Linux
: P2 normal
: ---
Assigned To: Mr. Bugs
: patch
Depends on:
Blocks:
  Show dependency tree
 
Reported: 2020-01-15 23:59 UTC by Vladimir Panteleev
Modified: 2020-08-15 17:02 UTC (History)
0 users

See Also:
Regression SHA1:
Fixed by SHA1: c4ef987429cef13bec1b7762bd70d99fee10670c
Distribution: ---
Staged patchset:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Vladimir Panteleev 2020-01-15 23:59:35 UTC
Attempting to build the Windows version of DMD, the reference compiler for the D programming language, fails under Wine. This seems to be caused by the following chain of events:

1. The makefile invokes a build program with a "VERBOSE=" on the command-line:

   https://github.com/dlang/dmd/blob/49dfbe54f4a0f62a0694aec9fb4184739903a0c2/src/win32.mak#L81

   (Here "$(VERBOSE)" is not set and expands to the empty string.)

2. The build program registers the command-line arguments into the process environment:

   https://github.com/dlang/dmd/blob/49dfbe54f4a0f62a0694aec9fb4184739903a0c2/src/build.d#L1359

   This sets the environment variable VERBOSE to the empty string.

3. Later, it attempts to check if the "VERBOSE" variable is in the environment:

   https://github.com/dlang/dmd/blob/49dfbe54f4a0f62a0694aec9fb4184739903a0c2/src/build.d#L1379

4. This calls the following Windows code in the standard library to read the environment:

   https://github.com/dlang/phobos/blob/e373b4e77448bc11c6e4ea6c85bcdb8f7ab86f20/std/process.d#L3506-L3515

5. For empty variables, the code behaves differently in Windows and Wine - Wine's implementation returns 0, while Windows returns 1. As a result, the standard library code throws an exception under Wine.

Writing a test program reveals further differences. The program:


#include <stdio.h>
#include <windows.h>

void main()
{
	WCHAR buf[4];
	DWORD size;
	int len, i;

	for (len = 0; len <= 2; len++)
	{
		for (i = 0; i < len; i++)
			buf[i] = 'a';
		buf[len] = 0;	

		SetEnvironmentVariableW(L"TESTVAR", buf);

		for (i = 0; i <= len + 1; i++)
		{
			DWORD err;
			SetLastError(1);
			buf[0] = 1;
			size = GetEnvironmentVariableW(L"TESTVAR", buf, i);
			err = GetLastError();
			printf("%d->%d: size=%d error=%d buf[0]=%d\n", 
				len, i, size, err, buf[0]);
		}
		printf("\n");
	}	
}


Output on Windows [Version 10.0.17134.648]:

0->0: size=1 error=1 buf[0]=1
0->1: size=0 error=1 buf[0]=0

1->0: size=2 error=1 buf[0]=1
1->1: size=2 error=1 buf[0]=0
1->2: size=1 error=1 buf[0]=97

2->0: size=3 error=1 buf[0]=1
2->1: size=3 error=1 buf[0]=0
2->2: size=3 error=1 buf[0]=0
2->3: size=2 error=1 buf[0]=97

Output on Wine:

0->0: size=0 error=1 buf[0]=1
0->1: size=0 error=1 buf[0]=0

1->0: size=2 error=122 buf[0]=1
1->1: size=2 error=122 buf[0]=1
1->2: size=1 error=1 buf[0]=97

2->0: size=3 error=122 buf[0]=1
2->1: size=3 error=122 buf[0]=1
2->2: size=3 error=122 buf[0]=1
2->3: size=2 error=1 buf[0]=97

We can observe these differences:

1. Wine returns 0 and not 1 when the variable is empty and the function is given a zero-length buffer.

2. Wine sets the last error to ERROR_INSUFFICIENT_BUFFER, while Windows doesn't.

3. Windows zeroes the buffer if the size is non-zero but still insufficient to hold the value. (This is not a bug as the behavior is specified in the documentation to be undefined.)
Comment 1 Vladimir Panteleev 2020-01-16 21:50:43 UTC
On Windows XP, the test program behaves differently:

0->0: size=0 error=234 buf[0]=1
0->1: size=0 error=1 buf[0]=0

1->0: size=2 error=1 buf[0]=1
1->1: size=2 error=1 buf[0]=1
1->2: size=1 error=1 buf[0]=97

2->0: size=3 error=1 buf[0]=1
2->1: size=3 error=1 buf[0]=1
2->2: size=3 error=1 buf[0]=1
2->3: size=2 error=1 buf[0]=97

(234 is ERROR_MORE_DATA)

So, this isn't so much of a Wine bug but rather Wine emulating the behavior of older Windows versions.

Though, seeing how it affects "real" software, perhaps this should be fixed anyway? D does not support any Windows versions exhibiting the old behavior.
Comment 2 Vladimir Panteleev 2020-01-20 11:43:56 UTC
Here is the result of running the above program on the Test Bot:
https://testbot.winehq.org/JobDetails.pl?Key=63451

Observations:
- Windows XP is the only one which returns an error when given an empty buffer (which is what Wine does now).
- Windows XP and 2003 do not clear the buffer if the value does not fit.
- All other versions produce the same output (like the Windows 10 log in the description above).
Comment 3 Vladimir Panteleev 2020-01-23 05:11:23 UTC
My latest patch was rejected because I left an old test inconsistent with the rest of the file:

https://source.winehq.org/patches/data/176822

Upon attempting to fix this, I discovered that the reason the test was that way was because Wine's GetEnvironmentVariableA hid another inconsistency, in that it resets GetLastError to NO_ERROR when it doesn't fail, instead of preserving the error (like Windows and GetEnvironmentVariableW). I guess I will include a fix for that in the next patch series version.
Comment 4 Gijs Vermeulen 2020-05-18 05:56:16 UTC
Wine now matches the test program except for 3) from your problems list in the description, but as you mentioned that isn't a bug.

Marking FIXED.
Comment 5 Alexandre Julliard 2020-05-22 13:52:20 UTC
Closing bugs fixed in 5.9.
Comment 6 Michael Stefaniuc 2020-08-07 11:35:25 UTC
Removing the 5.0.x milestone from bug fixes included in 5.0.2.


Privacy Policy
If you have a privacy inquiry regarding this site, please write to [email protected]

Hosted By CodeWeavers