1616# Version scheme (MAJOR.MINOR.PATCH) should orientate on "Semantic Versioning" https://semver.org/
1717# Every change in this script should result in increasing the version number accordingly (exceptions may be cosmetic
1818# changes)
19- CLIENT_VERSION = "1.4.0 "
19+ CLIENT_VERSION = "1.4.1 "
2020
2121# Timeout for analysis with Cppcheck in seconds
2222CPPCHECK_TIMEOUT = 30 * 60
@@ -344,10 +344,19 @@ def download_package(work_path, package, bandwidth_limit):
344344 return destfile
345345
346346
347+ def __is_inside_path (base_path , path ):
348+ try :
349+ return os .path .commonpath ([base_path , path ]) == base_path
350+ except ValueError :
351+ # paths are on different drives
352+ return False
353+
354+
347355def unpack_package (work_path , tgz , cpp_only = False , c_only = False , skip_files = None ):
348356 temp_path = os .path .join (work_path , 'temp' )
349357 __remove_tree (temp_path )
350358 os .mkdir (temp_path )
359+ real_temp_path = os .path .realpath (temp_path )
351360
352361 header_endings = ('.hpp' , '.h++' , '.hxx' , '.hh' , '.h' )
353362 cpp_source_endings = ('.cpp' , '.c++' , '.cxx' , '.cc' , '.tpp' , '.txx' , '.ipp' , '.ixx' , '.qml' )
@@ -367,10 +376,19 @@ def unpack_package(work_path, tgz, cpp_only=False, c_only=False, skip_files=None
367376 total = 0
368377 extracted = 0
369378 skipped = 0
379+ # Python versions with extraction filters reject members that leave temp_path as well
380+ extract_args = {'filter' : 'data' } if hasattr (tarfile , 'data_filter' ) else {}
370381 for member in tf :
371382 total += 1
372- if member .name .startswith (('/' , '..' )):
373- # Skip dangerous file names
383+ member_path = os .path .realpath (os .path .join (temp_path , member .name ))
384+ link_path = None
385+ if member .issym ():
386+ link_path = os .path .realpath (os .path .join (os .path .dirname (member_path ), member .linkname ))
387+ elif member .islnk ():
388+ link_path = os .path .realpath (os .path .join (temp_path , member .linkname ))
389+ if not __is_inside_path (real_temp_path , member_path ) or \
390+ (link_path is not None and not __is_inside_path (real_temp_path , link_path )):
391+ # Skip dangerous file names and links pointing outside of temp_path
374392 # print('skipping dangerous file: ' + member.name)
375393 skipped += 1
376394 continue
@@ -388,14 +406,16 @@ def unpack_package(work_path, tgz, cpp_only=False, c_only=False, skip_files=None
388406 skipped += 1
389407 continue
390408 try :
391- tf .extract (member .name , temp_path )
409+ tf .extract (member .name , temp_path , ** extract_args )
392410 if is_source :
393411 source_found = True
394412 extracted += 1
395413 except OSError :
396414 pass
397415 except AttributeError :
398416 pass
417+ except tarfile .TarError :
418+ pass
399419 print ('extracted {} of {} files (skipped {}{})' .format (extracted , total , skipped , (' / only headers' if (extracted and not source_found ) else '' )))
400420 return temp_path , source_found
401421
0 commit comments