#34294: File locking fails if argtypes redefined
----------------------------------------+------------------------
               Reporter:  Grub4K        |          Owner:  nobody
                   Type:  Bug           |         Status:  new
              Component:  Core (Other)  |        Version:  dev
               Severity:  Normal        |       Keywords:
           Triage Stage:  Unreviewed    |      Has patch:  1
    Needs documentation:  0             |    Needs tests:  0
Patch needs improvement:  0             |  Easy pickings:  0
                  UI/UX:  0             |
----------------------------------------+------------------------
 `django.core.files.locks` uses `ctypes.windll.kernel32` which is a global
 instance. If other code redefines `windll.kernel32.LockFileEx.argtypes`
 the function fails with an error.
 I am not sure how to write a test since its global
 {{{#!python
 import ctypes
 import ctypes.wintypes

 from django.core.files import locks


 class OVERLAPPED(ctypes.Structure):
     _fields_ = [
         ("Internal", ctypes.wintypes.LPVOID),
         ("InternalHigh", ctypes.wintypes.LPVOID),
         ("Offset", ctypes.wintypes.DWORD),
         ("OffsetHigh", ctypes.wintypes.DWORD),
         ("hEvent", ctypes.wintypes.HANDLE),
     ]


 ctypes.windll.kernel32.LockFileEx.argtypes = [
     ctypes.wintypes.HANDLE,
     ctypes.wintypes.DWORD,
     ctypes.wintypes.DWORD,
     ctypes.wintypes.DWORD,
     ctypes.wintypes.DWORD,
     ctypes.wintypes.DWORD,
 ]

 with open("./file", "w") as f:
     locks.lock(f, locks.LOCK_EX)
 }}}
 Possible patch:
 {{{#!diff
 diff --git a/django/core/files/locks.py b/django/core/files/locks.py
 index 5752b08a69..c0f471f87d 100644
 --- a/django/core/files/locks.py
 +++ b/django/core/files/locks.py
 @@ -32,12 +32,12 @@ if os.name == "nt":
          POINTER,
          Structure,
          Union,
 +        WinDLL,
          byref,
          c_int64,
          c_ulong,
          c_void_p,
          sizeof,
 -        windll,
      )
      from ctypes.wintypes import BOOL, DWORD, HANDLE

 @@ -73,10 +73,11 @@ if os.name == "nt":
      LPOVERLAPPED = POINTER(OVERLAPPED)

      # --- Define function prototypes for extra safety ---
 -    LockFileEx = windll.kernel32.LockFileEx
 +    kernel32 = WinDLL("kernel32")
 +    LockFileEx = kernel32.LockFileEx
      LockFileEx.restype = BOOL
      LockFileEx.argtypes = [HANDLE, DWORD, DWORD, DWORD, DWORD,
 LPOVERLAPPED]
 -    UnlockFileEx = windll.kernel32.UnlockFileEx
 +    UnlockFileEx = kernel32.UnlockFileEx
      UnlockFileEx.restype = BOOL
      UnlockFileEx.argtypes = [HANDLE, DWORD, DWORD, DWORD, LPOVERLAPPED]

 diff --git a/tests/files/tests.py b/tests/files/tests.py
 index b3478d2732..d0e633cb7a 100644
 --- a/tests/files/tests.py
 +++ b/tests/files/tests.py
 @@ -200,6 +200,32 @@ class FileTests(unittest.TestCase):
              self.assertIs(locks.unlock(f1), True)
              self.assertIs(locks.unlock(f2), True)

 +    @unittest.skipIf(os.name != "nt", "File locking usees WinDLL on
 windows only")
 +    def test_local_windll(self):
 +        import ctypes
 +        import ctypes.wintypes
 +
 +        old_argtypes = ctypes.windll.kernel32.LockFileEx.argtypes
 +        try:
 +            ctypes.windll.kernel32.LockFileEx.argtypes = [
 +                ctypes.wintypes.HANDLE,
 +                ctypes.wintypes.DWORD,
 +                ctypes.wintypes.DWORD,
 +                ctypes.wintypes.DWORD,
 +                ctypes.wintypes.DWORD,
 +                ctypes.wintypes.DWORD,
 +            ]
 +            file_path = Path(__file__).parent / "test.png"
 +            with open(file_path) as file:
 +                try:
 +                    locks.lock(file, locks.LOCK_EX)
 +                except Exception:
 +                    self.fail("Locking raised exception with changed
 argtypes")
 +                else:
 +                    locks.unlock(file)
 +        finally:
 +            ctypes.windll.kernel32.LockFileEx.argtypes = old_argtypes
 +

  class NoNameFileTestCase(unittest.TestCase):
      """
 }}}

-- 
Ticket URL: <https://code.djangoproject.com/ticket/34294>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/01070185ea9467cc-6f6dcd32-cdfb-4b33-85a8-ccda35cb51c9-000000%40eu-central-1.amazonses.com.

Reply via email to