Skip to content

Commit

Permalink
Security Patch Control Characters in Protocol
Browse files Browse the repository at this point in the history
  • Loading branch information
oleibman committed Jan 24, 2025
1 parent 7af20c3 commit e237309
Show file tree
Hide file tree
Showing 11 changed files with 464 additions and 136 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,13 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com)
and this project adheres to [Semantic Versioning](https://semver.org).

# TBD - 2.3.7

### Fixed

- Backported security patch for control characters in protocol.
- Use Composer\Pcre in Xls/Parser. Partial backport of [PR #4203](https://github.com/PHPOffice/PhpSpreadsheet/pull/4203)

# 2025-01=11 - 2.3.6

### Deprecated
Expand Down
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@
"ext-xmlwriter": "*",
"ext-zip": "*",
"ext-zlib": "*",
"composer/pcre": "^3.2",
"maennchen/zipstream-php": "^2.1 || ^3.0",
"markbaker/complex": "^3.0",
"markbaker/matrix": "^3.0",
Expand Down
160 changes: 80 additions & 80 deletions composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions phpstan.neon.dist
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ includes:
- phpstan-baseline.neon
- vendor/phpstan/phpstan-phpunit/extension.neon
- vendor/phpstan/phpstan-phpunit/rules.neon
- vendor/composer/pcre/extension.neon

parameters:
level: 8
Expand Down
5 changes: 4 additions & 1 deletion src/PhpSpreadsheet/Reader/Html.php
Original file line number Diff line number Diff line change
Expand Up @@ -1045,7 +1045,10 @@ private function insertImage(Worksheet $sheet, string $column, int $row, array $
$name = $attributes['alt'] ?? null;

$drawing = new Drawing();
$drawing->setPath($src);
$drawing->setPath($src, false);
if ($drawing->getPath() === '') {
return;
}
$drawing->setWorksheet($sheet);
$drawing->setCoordinates($column . $row);
$drawing->setOffsetX(0);
Expand Down
2 changes: 1 addition & 1 deletion src/PhpSpreadsheet/Worksheet/Drawing.php
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ public function setPath(string $path, bool $verifyFile = true, ?ZipArchive $zip

$this->path = '';
// Check if a URL has been passed. https://stackoverflow.com/a/2058596/1252979
if (filter_var($path, FILTER_VALIDATE_URL)) {
if (filter_var($path, FILTER_VALIDATE_URL) || (preg_match('/^([\\w\\s\\x00-\\x1f]+):/u', $path) && !preg_match('/^([\\w]+):/u', $path))) {
if (!preg_match('/^(http|https|file|ftp|s3):/', $path)) {
throw new PhpSpreadsheetException('Invalid protocol for linked drawing');
}
Expand Down
19 changes: 17 additions & 2 deletions src/PhpSpreadsheet/Writer/Html.php
Original file line number Diff line number Diff line change
Expand Up @@ -1528,9 +1528,10 @@ private function generateRow(Worksheet $worksheet, array $values, int $row, stri
$url = $worksheet->getHyperlink($coordinate)->getUrl();
$urlDecode1 = html_entity_decode($url, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
$urlTrim = preg_replace('/^\\s+/u', '', $urlDecode1) ?? $urlDecode1;
$parseScheme = preg_match('/^([\\w\\s]+):/u', strtolower($urlTrim), $matches);
if ($parseScheme === 1 && !in_array($matches[1], ['http', 'https', 'file', 'ftp', 's3'], true)) {
$parseScheme = preg_match('/^([\\w\\s\\x00-\\x1f]+):/u', strtolower($urlTrim), $matches);
if ($parseScheme === 1 && !in_array($matches[1], ['http', 'https', 'file', 'ftp', 'mailto', 's3'], true)) {
$cellData = htmlspecialchars($url, Settings::htmlEntityFlags());
$cellData = self::replaceControlChars($cellData);
} else {
$cellData = '<a href="' . htmlspecialchars($url, Settings::htmlEntityFlags()) . '" title="' . htmlspecialchars($worksheet->getHyperlink($coordinate)->getTooltip(), Settings::htmlEntityFlags()) . '">' . $cellData . '</a>';
}
Expand Down Expand Up @@ -1580,6 +1581,20 @@ private function generateRow(Worksheet $worksheet, array $values, int $row, stri
return $html;
}

private static function replaceNonAscii(array $matches): string
{
return '&#' . mb_ord($matches[0], 'UTF-8') . ';';
}

private static function replaceControlChars(string $convert): string
{
return (string) preg_replace_callback(
'/[\\x00-\\x1f]/',
[self::class, 'replaceNonAscii'],
$convert
);
}

/**
* Takes array where of CSS properties / values and converts to CSS string.
*/
Expand Down
Loading

0 comments on commit e237309

Please sign in to comment.