bpo-33001: Prevent buffer overrun in os.symlink (GH-5989)

(cherry picked from commit 6921e73e33edc3c61bc2d78ed558eaa22a89a564)

Co-authored-by: Steve Dower <steve.dower@microsoft.com>
diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py
index 4f8a2a7..e509188 100644
--- a/Lib/test/test_os.py
+++ b/Lib/test/test_os.py
@@ -2164,6 +2164,40 @@
         target = os.readlink(r'C:\Users\All Users')
         self.assertTrue(os.path.samefile(target, r'C:\ProgramData'))
 
+    def test_buffer_overflow(self):
+        # Older versions would have a buffer overflow when detecting
+        # whether a link source was a directory. This test ensures we
+        # no longer crash, but does not otherwise validate the behavior
+        segment = 'X' * 27
+        path = os.path.join(*[segment] * 10)
+        test_cases = [
+            # overflow with absolute src
+            ('\\' + path, segment),
+            # overflow dest with relative src
+            (segment, path),
+            # overflow when joining src
+            (path[:180], path[:180]),
+        ]
+        for src, dest in test_cases:
+            try:
+                os.symlink(src, dest)
+            except FileNotFoundError:
+                pass
+            else:
+                try:
+                    os.remove(dest)
+                except OSError:
+                    pass
+            # Also test with bytes, since that is a separate code path.
+            try:
+                os.symlink(os.fsencode(src), os.fsencode(dest))
+            except FileNotFoundError:
+                pass
+            else:
+                try:
+                    os.remove(dest)
+                except OSError:
+                    pass
 
 @unittest.skipUnless(sys.platform == "win32", "Win32 specific tests")
 class Win32JunctionTests(unittest.TestCase):