Repository: pyinstaller/pyinstaller

Issue:
Security-Alert: try to store file outside of dist-directory. Aborting. 'my..data.txt'
Including a data file with two consecutive periods in the filename like "my..data.txt" gives a "Security-Alert" error when using pyinstaller. Is this desired behavior or a bug? 

output log:
```
C:\Users\username\test_pyinstaller\compile>pyinstaller my_script2.spec
123 INFO: PyInstaller: 3.3.dev0+gbb9e52fb
124 INFO: Python: 3.5.2
124 INFO: Platform: Windows-7-6.1.7601-SP1
126 INFO: UPX is not available.
129 INFO: Extending PYTHONPATH with paths
['C:\\Users\\username\\test_pyinstaller',
 'C:\\Users\\username\\test_pyinstaller\\compile']
130 INFO: checking Analysis
130 INFO: Building Analysis because out00-Analysis.toc is non existent
130 INFO: Initializing module dependency graph...
141 INFO: Initializing module graph hooks...
143 INFO: Analyzing base_library.zip ...
5304 INFO: running Analysis out00-Analysis.toc
5726 INFO: Caching module hooks...
5731 INFO: Analyzing ..\my_script.py
5734 INFO: Loading module hooks...
5735 INFO: Loading module hook "hook-xml.py"...
6085 INFO: Loading module hook "hook-encodings.py"...
6449 INFO: Loading module hook "hook-pydoc.py"...
6467 INFO: Looking for ctypes DLLs
6479 INFO: Analyzing run-time hooks ...
6485 INFO: Looking for dynamic libraries
6593 INFO: Looking for eggs
6594 INFO: Using Python library C:\Users\username\AppData\Local\Continuum\Anaconda3\envs\py35\python35.dll
6594 INFO: Found binding redirects:
[]
6601 INFO: Warnings written to C:\Users\username\test_pyinstaller\compile\build\my_script2\warnmy_script2.txt
6609 INFO: Appending 'datas' from .spec
6611 INFO: checking PYZ
6611 INFO: Building PYZ because out00-PYZ.toc is non existent
6611 INFO: Building PYZ (ZlibArchive) C:\Users\username\test_pyinstaller\compile\build\my_script2\out00-PYZ.pyz
7223 INFO: Building PYZ (ZlibArchive) C:\Users\username\test_pyinstaller\compile\build\my_script2\out00-PYZ.pyz completed successfully.
7232 INFO: checking PKG
7232 INFO: Building PKG because out00-PKG.toc is non existent
7232 INFO: Building PKG (CArchive) out00-PKG.pkg
7249 INFO: Building PKG (CArchive) out00-PKG.pkg completed successfully.
7252 INFO: Bootloader C:\Users\username\AppData\Local\Continuum\Anaconda3\envs\py35\lib\site-packages\PyInstaller\bootloader\Windows-64bit\run.exe
7252 INFO: checking EXE
7252 INFO: Building EXE because out00-EXE.toc is non existent
7252 INFO: Building EXE from out00-EXE.toc
7253 INFO: Appending archive to EXE C:\Users\username\test_pyinstaller\compile\build\my_script2\my_script.exe
7256 INFO: Building EXE from out00-EXE.toc completed successfully.
7259 INFO: checking COLLECT
7259 INFO: Building COLLECT because out00-COLLECT.toc is non existent
7259 INFO: Building COLLECT out00-COLLECT.toc
Security-Alert: try to store file outside of dist-directory. Aborting. 'my..data.txt'
```
my_script2.spec:

```
# -*- mode: python -*-
block_cipher = None
a = Analysis(['..\\my_script.py'],
             pathex=['.'],
             binaries=[],
             datas=[ ('..\\my..data.txt', '.') ],
             hiddenimports=[],
             hookspath=[],
             runtime_hooks=[],
             excludes=[],
             win_no_prefer_redirects=False,
             win_private_assemblies=False,
             cipher=block_cipher)
pyz = PYZ(a.pure, a.zipped_data,
             cipher=block_cipher)
exe = EXE(pyz,
          a.scripts,
          exclude_binaries=True,
          name='my_script',
          debug=False,
          strip=False,
          upx=True,
          console=True )
coll = COLLECT(exe,
               a.binaries,
               a.zipfiles,
               a.datas,
               strip=False,
               upx=True,
               name='my_script')
```
my_script.py:
```
# -*- coding: utf-8 -*-
pass
```
my..data.txt:
```
data
```
Renaming "my..data.txt" to "my_data.txt" in the actual file and the .spec file lets it successfully generate the executable, but I'd much prefer being able to support any valid filename for input data files. I'm using Windows 7, Python 3.5, PyInstaller: 3.3.dev0+gbb9e52fb.



Discussion:
same error... Someone?
This is caused by https://github.com/pyinstaller/pyinstaller/blob/v3.3.1/PyInstaller/building/api.py#L681
```
 if os.pardir in os.path.normpath(inm) or os.path.isabs(inm):
```
Which also triggers if the filename contains `..` (which is `os.pardir` on Windows and Unix).

This needs to be changed into
```
if os.pardir in os.path.normpath(inm).split(os.sep) or os.path.isabs(inm):
```
thus checking the each path component

Resolving patch:
diff --git a/PyInstaller/building/api.py b/PyInstaller/building/api.py
--- a/PyInstaller/building/api.py
+++ b/PyInstaller/building/api.py
@@ -678,7 +678,8 @@ def assemble(self):
             if not os.path.exists(fnm) or not os.path.isfile(fnm) and is_path_to_egg(fnm):
                 # file is contained within python egg, it is added with the egg
                 continue
-            if os.pardir in os.path.normpath(inm) or os.path.isabs(inm):
+            if os.pardir in os.path.normpath(inm).split(os.sep) \
+               or os.path.isabs(inm):
                 raise SystemExit('Security-Alert: try to store file outside '
                                  'of dist-directory. Aborting. %r' % inm)
             tofnm = os.path.join(self.name, inm)


Test patch: