SA-CORE-2019-012 by samuel.mortenson, larowlan, pwolanin, Sam152, Jasu_M, David_Rothstein, michieltcs, Ayesh, alexpott, xjm, vijaycs85, mcdruid

merge-requests/26/head
Lee Rowlands 2019-12-18 19:07:45 +10:00
parent 6f60277f75
commit 75689e47e6
No known key found for this signature in database
GPG Key ID: 2B829A3DF9204DC4
2 changed files with 98 additions and 59 deletions

View File

@ -38,10 +38,10 @@ class ArchiverTar implements ArchiverInterface {
public function extract($path, Array $files = array()) {
if ($files) {
$this->tar->extractList($files, $path);
$this->tar->extractList($files, $path, '', FALSE, FALSE);
}
else {
$this->tar->extract($path);
$this->tar->extract($path, FALSE, FALSE);
}
return $this;

View File

@ -40,35 +40,23 @@
*/
/**
* Note on Drupal 8 porting.
* This file origin is Tar.php, release 1.4.5 (stable) with some code
* from PEAR.php, release 1.10.5 (stable) both at http://pear.php.net.
* Note on Drupal 7 porting.
* This file origin is Tar.php, release 1.4.9 (stable) with some code
* from PEAR.php, release 1.10.10 (stable) both at http://pear.php.net.
* To simplify future porting from pear of this file, you should not
* do cosmetic or other non significant changes to this file.
* The following changes have been done:
* Added namespace Drupal\Core\Archiver.
* Removed require_once 'PEAR.php'.
* Added defintion of OS_WINDOWS taken from PEAR.php.
* Renamed class to ArchiveTar.
* Removed extends PEAR from class.
* Removed call parent:: __construct().
* Changed PEAR::loadExtension($extname) to this->loadExtension($extname).
* Added function loadExtension() taken from PEAR.php.
* Changed all calls of unlink() to drupal_unlink().
* Changed $this->error_object = &$this->raiseError($p_message)
* to throw new \Exception($p_message).
* to throw new Exception($p_message).
*/
/**
* Note on Drupal 7 backporting from Drupal 8.
* File origin is core/lib/Drupal/Core/Archiver/ArchiveTar.php from Drupal 8.
* The following changes have been done:
* Removed namespace Drupal\Core\Archiver.
* Renamed class to Archive_Tar.
* Changed \Exception to Exception.
*/
// Drupal removal require_once 'PEAR.php'.
// Drupal addition OS_WINDOWS as defined in PEAR.php.
@ -153,6 +141,18 @@ class Archive_Tar
*/
public $error_object = null;
/**
* Format for data extraction
*
* @var string
*/
public $_fmt = '';
/**
* @var int Length of the read buffer in bytes
*/
protected $buffer_length;
/**
* Archive_Tar Class constructor. This flavour of the constructor only
* declare a new Archive_Tar object, identifying it by the name of the
@ -165,10 +165,11 @@ class Archive_Tar
* parameter indicates if gzip, bz2 or lzma2 compression
* is required. For compatibility reason the
* boolean value 'true' means 'gz'.
* @param int $buffer_length Length of the read buffer in bytes
*
* @return bool
*/
public function __construct($p_tarname, $p_compress = null)
public function __construct($p_tarname, $p_compress = null, $buffer_length = 512)
{
// Drupal removal parent::__construct().
@ -263,15 +264,16 @@ class Archive_Tar
if (version_compare(PHP_VERSION, "5.5.0-dev") < 0) {
$this->_fmt = "a100filename/a8mode/a8uid/a8gid/a12size/a12mtime/" .
"a8checksum/a1typeflag/a100link/a6magic/a2version/" .
"a32uname/a32gname/a8devmajor/a8devminor/a131prefix";
"a8checksum/a1typeflag/a100link/a6magic/a2version/" .
"a32uname/a32gname/a8devmajor/a8devminor/a131prefix";
} else {
$this->_fmt = "Z100filename/Z8mode/Z8uid/Z8gid/Z12size/Z12mtime/" .
"Z8checksum/Z1typeflag/Z100link/Z6magic/Z2version/" .
"Z32uname/Z32gname/Z8devmajor/Z8devminor/Z131prefix";
"Z8checksum/Z1typeflag/Z100link/Z6magic/Z2version/" .
"Z32uname/Z32gname/Z8devmajor/Z8devminor/Z131prefix";
}
$this->buffer_length = $buffer_length;
}
public function __destruct()
@ -371,11 +373,12 @@ class Archive_Tar
/**
* @param string $p_path
* @param bool $p_preserve
* @param bool $p_symlinks
* @return bool
*/
public function extract($p_path = '', $p_preserve = false)
public function extract($p_path = '', $p_preserve = false, $p_symlinks = true)
{
return $this->extractModify($p_path, '', $p_preserve);
return $this->extractModify($p_path, '', $p_preserve, $p_symlinks);
}
/**
@ -616,11 +619,12 @@ class Archive_Tar
* removed if present at the beginning of
* the file/dir path.
* @param boolean $p_preserve Preserve user/group ownership of files
* @param boolean $p_symlinks Allow symlinks.
*
* @return boolean true on success, false on error.
* @see extractList()
*/
public function extractModify($p_path, $p_remove_path, $p_preserve = false)
public function extractModify($p_path, $p_remove_path, $p_preserve = false, $p_symlinks = true)
{
$v_result = true;
$v_list_detail = array();
@ -632,7 +636,8 @@ class Archive_Tar
"complete",
0,
$p_remove_path,
$p_preserve
$p_preserve,
$p_symlinks
);
$this->_close();
}
@ -676,11 +681,12 @@ class Archive_Tar
* removed if present at the beginning of
* the file/dir path.
* @param boolean $p_preserve Preserve user/group ownership of files
* @param boolean $p_symlinks Allow symlinks.
*
* @return true on success, false on error.
* @see extractModify()
*/
public function extractList($p_filelist, $p_path = '', $p_remove_path = '', $p_preserve = false)
public function extractList($p_filelist, $p_path = '', $p_remove_path = '', $p_preserve = false, $p_symlinks = true)
{
$v_result = true;
$v_list_detail = array();
@ -701,7 +707,8 @@ class Archive_Tar
"partial",
$v_list,
$p_remove_path,
$p_preserve
$p_preserve,
$p_symlinks
);
$this->_close();
}
@ -1326,8 +1333,15 @@ class Archive_Tar
return false;
}
while (($v_buffer = fread($v_file, 512)) != '') {
$v_binary_data = pack("a512", "$v_buffer");
while (($v_buffer = fread($v_file, $this->buffer_length)) != '') {
$buffer_length = strlen("$v_buffer");
if ($buffer_length != $this->buffer_length) {
$pack_size = ((int)($buffer_length / 512) + 1) * 512;
$pack_format = sprintf('a%d', $pack_size);
} else {
$pack_format = sprintf('a%d', $this->buffer_length);
}
$v_binary_data = pack($pack_format, "$v_buffer");
$this->_writeBlock($v_binary_data);
}
@ -1532,7 +1546,8 @@ class Archive_Tar
$p_type = '',
$p_uid = 0,
$p_gid = 0
) {
)
{
$p_filename = $this->_pathReduction($p_filename);
if (strlen($p_filename) > 99) {
@ -1745,7 +1760,16 @@ class Archive_Tar
}
// ----- Extract the checksum
$v_header['checksum'] = OctDec(trim($v_data['checksum']));
$v_data_checksum = trim($v_data['checksum']);
if (!preg_match('/^[0-7]*$/', $v_data_checksum)) {
$this->_error(
'Invalid checksum for file "' . $v_data['filename']
. '" : ' . $v_data_checksum . ' extracted'
);
return false;
}
$v_header['checksum'] = OctDec($v_data_checksum);
if ($v_header['checksum'] != $v_checksum) {
$v_header['filename'] = '';
@ -1839,10 +1863,7 @@ class Archive_Tar
if (strpos($file, 'phar://') === 0) {
return true;
}
if (strpos($file, DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR) !== false) {
return true;
}
if (strpos($file, '..' . DIRECTORY_SEPARATOR) === 0) {
if (strpos($file, '../') !== false || strpos($file, '..\\') !== false) {
return true;
}
return false;
@ -1908,19 +1929,23 @@ class Archive_Tar
}
switch ($v_header['typeflag']) {
case 'L': {
if (!$this->_readLongHeader($v_header)) {
return null;
case 'L':
{
if (!$this->_readLongHeader($v_header)) {
return null;
}
}
} break;
break;
case 'K': {
$v_link_header = $v_header;
if (!$this->_readLongHeader($v_link_header)) {
return null;
case 'K':
{
$v_link_header = $v_header;
if (!$this->_readLongHeader($v_link_header)) {
return null;
}
$v_header['link'] = $v_link_header['filename'];
}
$v_header['link'] = $v_link_header['filename'];
} break;
break;
}
if ($v_header['filename'] == $p_filename) {
@ -1960,6 +1985,7 @@ class Archive_Tar
* @param string $p_file_list
* @param string $p_remove_path
* @param bool $p_preserve
* @param bool $p_symlinks
* @return bool
*/
public function _extractList(
@ -1968,8 +1994,10 @@ class Archive_Tar
$p_mode,
$p_file_list,
$p_remove_path,
$p_preserve = false
) {
$p_preserve = false,
$p_symlinks = true
)
{
$v_result = true;
$v_nb = 0;
$v_extract_all = true;
@ -2022,19 +2050,23 @@ class Archive_Tar
}
switch ($v_header['typeflag']) {
case 'L': {
if (!$this->_readLongHeader($v_header)) {
return null;
case 'L':
{
if (!$this->_readLongHeader($v_header)) {
return null;
}
}
} break;
break;
case 'K': {
$v_link_header = $v_header;
if (!$this->_readLongHeader($v_link_header)) {
return null;
case 'K':
{
$v_link_header = $v_header;
if (!$this->_readLongHeader($v_link_header)) {
return null;
}
$v_header['link'] = $v_link_header['filename'];
}
$v_header['link'] = $v_link_header['filename'];
} break;
break;
}
// ignore extended / pax headers
@ -2146,6 +2178,13 @@ class Archive_Tar
}
}
} elseif ($v_header['typeflag'] == "2") {
if (!$p_symlinks) {
$this->_warning('Symbolic links are not allowed. '
. 'Unable to extract {'
. $v_header['filename'] . '}'
);
return false;
}
if (@file_exists($v_header['filename'])) {
@drupal_unlink($v_header['filename']);
}