classification
Title: Regression: Python 3.5.0 shutil.copy2 doesn't raise PermissionError on Windows 7
Type: Stage: resolved
Components: Windows Versions: Python 3.5
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: steve.dower Nosy List: eryksun, nre3976, paul.moore, python-dev, steve.dower, tim.golden, zach.ware
Priority: high Keywords: 3.5regression

Created on 2015-09-22 13:48 by nre3976, last changed 2015-09-23 01:24 by steve.dower. This issue is now closed.

Messages (4)
msg251322 - (view) Author: Nick Evans (nre3976) Date: 2015-09-22 13:48
Python 3.5.0 shutil.copy2 doesn't raise PermissionError when it does not have permission to copy a file (tested on Windows 7):

C:\Users\X\Desktop>C:\Users\X\AppData\Local\Programs\Python\Python35-32\python.exe
Python 3.5.0 (v3.5.0:374f501f4567, Sep 13 2015, 02:16:59) [MSC v.1900 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import shutil
>>> shutil.copy2("test.txt", "/")
'/test.txt'
>>> shutil.copy2("test.txt", "C:\\")
'C:\\test.txt'

NB: The file is not copied.

Python 3.4.3 does raise PermissionError:

C:\Users\X\Desktop>C:\Python34\python.exe
Python 3.4.3 (v3.4.3:9b73f1c3e601, Feb 24 2015, 22:44:40) [MSC v.1600 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import shutil
>>> shutil.copy2("test.txt", "/")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Python34\lib\shutil.py", line 245, in copy2
    copyfile(src, dst, follow_symlinks=follow_symlinks)
  File "C:\Python34\lib\shutil.py", line 109, in copyfile
    with open(dst, 'wb') as fdst:
PermissionError: [Errno 13] Permission denied: '/test.txt'
>>> shutil.copy2("test.txt", "C:\\")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Python34\lib\shutil.py", line 245, in copy2
    copyfile(src, dst, follow_symlinks=follow_symlinks)
  File "C:\Python34\lib\shutil.py", line 109, in copyfile
    with open(dst, 'wb') as fdst:
PermissionError: [Errno 13] Permission denied: 'C:\\test.txt'
msg251336 - (view) Author: Eryk Sun (eryksun) * (Python triager) Date: 2015-09-22 17:56
This issue doesn't pertain to the 64-bit version.

    C:\Temp>py -3.5
    Python 3.5.0 (v3.5.0:374f501f4567, Sep 13 2015, 02:27:37) 
    [MSC v.1900 64 bit (AMD64)] on win32
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import shutil
    >>> shutil.copy2('test.txt', 'C:\\')
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "C:\Program Files\Python 3.5\lib\shutil.py", line 251, in copy2
        copyfile(src, dst, follow_symlinks=follow_symlinks)
      File "C:\Program Files\Python 3.5\lib\shutil.py", line 115, in copyfile
        with open(dst, 'wb') as fdst:
    PermissionError: [Errno 13] Permission denied: 'C:\\test.txt'

In the 32-bit version, creating a file in the system root directory gets virtualized when the user doesn't have write access. It's not specific to shutil.copy2.

    C:\Temp>py -3.5-32
    Python 3.5.0 (v3.5.0:374f501f4567, Sep 13 2015, 02:16:59) 
    [MSC v.1900 32 bit (Intel)] on win32
    Type "help", "copyright", "credits" or "license" for more information.
    >>> open('C:\\test.txt', 'w').close()
    >>> import pathlib
    >>> pathlib.Path('C:\\test.txt').resolve()
    WindowsPath('C:/Users/usradm/AppData/Local/VirtualStore/test.txt')

You can verify in the task manager's details tab that UAC Virtualization is enabled for 32-bit python.exe and disabled for 64-bit python.exe. The problem is that the manifest is missing the requestedExecutionLevel, which should be present and set to "asInvoker". This is discussed in the MSDN article [New UAC Technologies for Windows Vista][1].

    >>> os.system('sigcheck -q -m "%s"' % sys.executable)
    c:\users\usradm\appdata\local\programs\python\python35-32\python.exe:
            Verified:       Signed
            Signing date:   2:17 AM 9/13/2015
            Publisher:      Python Software Foundation
            Description:    Python
            Product:        Python
            Prod version:   3.5.0
            File version:   3.5.0
            MachineType:    32-bit
            Manifest:
    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
      <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
        <application>
          <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
          <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
          <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
          <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
          <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
        </application>
      </compatibility>
    </assembly>

3.4's manifest sets the requestedExecutionLevel:

    C:\Temp>py -3.4-32
    Python 3.4.3 (v3.4.3:9b73f1c3e601, Feb 24 2015, 22:43:06) 
    [MSC v.1600 32 bit (Intel)] on win32
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import os, sys
    >>> os.system('sigcheck -q -m "%s"' % sys.executable)
    c:\users\usradm\appdata\local\programs\python\python34-32\python.exe:
            Verified:       Unsigned
            Link date:      9:43 PM 2/24/2015
            Publisher:      n/a
            Description:    n/a
            Product:        n/a
            Prod version:   n/a
            File version:   n/a
            MachineType:    32-bit
            Manifest:
    <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
      <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
        <security>
          <requestedPrivileges>
            <requestedExecutionLevel level="asInvoker" uiAccess="false"></requestedExecutionLevel>
          </requestedPrivileges>
        </security>
      </trustInfo>
    </assembly> 

[1]: https://msdn.microsoft.com/en-us/library/bb756960
msg251346 - (view) Author: Steve Dower (steve.dower) * (Python committer) Date: 2015-09-22 21:34
Confirmed. I have a trivial fix coming to restore the requestedExecutionLevel.
msg251364 - (view) Author: Roundup Robot (python-dev) (Python triager) Date: 2015-09-23 00:01
New changeset b7f0f1d1e923 by Steve Dower in branch '3.5':
Issue #25213: Restores requestedExecutionLevel to manifest to disable UAC virtualization.
https://hg.python.org/cpython/rev/b7f0f1d1e923
History
Date User Action Args
2015-09-23 01:24:05steve.dowersetstatus: open -> closed
resolution: fixed
stage: resolved
2015-09-23 00:01:51python-devsetnosy: + python-dev
messages: + msg251364
2015-09-22 21:34:30steve.dowersetassignee: steve.dower
messages: + msg251346
2015-09-22 17:56:16eryksunsetpriority: normal -> high

nosy: + paul.moore, tim.golden, eryksun, zach.ware, steve.dower
messages: + msg251336

components: + Windows, - Library (Lib)
keywords: + 3.5regression
2015-09-22 13:48:40nre3976create