From 0611d4d57113cc33eed9b59ed7c13fe826bbc396 Mon Sep 17 00:00:00 2001 From: Chris Gross <gross.364@osu.edu> Date: Thu, 21 Mar 2019 12:58:48 -0400 Subject: [PATCH] 7.x-1.13 Release Candidate 2 --- CHANGELOG.txt | 5 +++++ includes/bootstrap.inc | 2 +- includes/file.inc | 25 +++++++++++++++++++++++-- modules/simpletest/tests/file.test | 17 +++++++++++++++++ profiles/wcm_base/CHANGELOG.txt | 4 ++++ 5 files changed, 50 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 8c651312..8a567dc0 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,6 +1,11 @@ Drupal 7.xx, xxxx-xx-xx (development version) ----------------------- +Drupal 7.65, 2019-03-20 +----------------------- +- Fixed security issues: + - SA-CORE-2019-004 + Drupal 7.64, 2019-02-06 ----------------------- - [regression] Unset the 'host' header in drupal_http_request() during redirect diff --git a/includes/bootstrap.inc b/includes/bootstrap.inc index db2ac1f5..1b5c5340 100644 --- a/includes/bootstrap.inc +++ b/includes/bootstrap.inc @@ -8,7 +8,7 @@ /** * The current system version. */ -define('VERSION', '7.64'); +define('VERSION', '7.65'); /** * Core API compatibility. diff --git a/includes/file.inc b/includes/file.inc index d6f31560..8943d63a 100644 --- a/includes/file.inc +++ b/includes/file.inc @@ -997,8 +997,15 @@ function file_build_uri($path) { * @return * The destination filepath, or FALSE if the file already exists * and FILE_EXISTS_ERROR is specified. + * + * @throws RuntimeException + * Thrown if the filename contains invalid UTF-8. */ function file_destination($destination, $replace) { + $basename = drupal_basename($destination); + if (!drupal_validate_utf8($basename)) { + throw new RuntimeException(sprintf("Invalid filename '%s'", $basename)); + } if (file_exists($destination)) { switch ($replace) { case FILE_EXISTS_REPLACE: @@ -1006,7 +1013,6 @@ function file_destination($destination, $replace) { break; case FILE_EXISTS_RENAME: - $basename = drupal_basename($destination); $directory = drupal_dirname($destination); $destination = file_create_filename($basename, $directory); break; @@ -1222,11 +1228,20 @@ function file_unmunge_filename($filename) { * @return * File path consisting of $directory and a unique filename based off * of $basename. + * + * @throws RuntimeException + * Thrown if the $basename is not valid UTF-8 or another error occurs + * stripping control characters. */ function file_create_filename($basename, $directory) { + $original = $basename; // Strip control characters (ASCII value < 32). Though these are allowed in // some filesystems, not many applications handle them well. $basename = preg_replace('/[\x00-\x1F]/u', '_', $basename); + if (preg_last_error() !== PREG_NO_ERROR) { + throw new RuntimeException(sprintf("Invalid filename '%s'", $original)); + } + if (substr(PHP_OS, 0, 3) == 'WIN') { // These characters are not allowed in Windows filenames $basename = str_replace(array(':', '*', '?', '"', '<', '>', '|'), '_', $basename); @@ -1567,7 +1582,13 @@ function file_save_upload($form_field_name, $validators = array(), $destination if (substr($destination, -1) != '/') { $destination .= '/'; } - $file->destination = file_destination($destination . $file->filename, $replace); + try { + $file->destination = file_destination($destination . $file->filename, $replace); + } + catch (RuntimeException $e) { + drupal_set_message(t('The file %source could not be uploaded because the name is invalid.', array('%source' => $form_field_name)), 'error'); + return FALSE; + } // If file_destination() returns FALSE then $replace == FILE_EXISTS_ERROR and // there's an existing file so we need to bail. if ($file->destination === FALSE) { diff --git a/modules/simpletest/tests/file.test b/modules/simpletest/tests/file.test index 55dd1906..032f2cba 100644 --- a/modules/simpletest/tests/file.test +++ b/modules/simpletest/tests/file.test @@ -957,6 +957,15 @@ class FileDirectoryTest extends FileTestCase { $path = file_create_filename($basename, $directory); $this->assertEqual($path, $expected, format_string('Creating a new filepath from %original equals %new.', array('%new' => $path, '%original' => $original)), 'File'); + try { + $filename = "a\xFFtest\x80€.txt"; + file_create_filename($filename, $directory); + $this->fail('Expected exception not thrown'); + } + catch (RuntimeException $e) { + $this->assertEqual("Invalid filename '$filename'", $e->getMessage()); + } + // @TODO: Finally we copy a file into a directory several times, to ensure a properly iterating filename suffix. } @@ -989,6 +998,14 @@ class FileDirectoryTest extends FileTestCase { $this->assertNotEqual($path, $destination, 'A new filepath destination is created when filepath destination already exists with FILE_EXISTS_RENAME.', 'File'); $path = file_destination($destination, FILE_EXISTS_ERROR); $this->assertEqual($path, FALSE, 'An error is returned when filepath destination already exists with FILE_EXISTS_ERROR.', 'File'); + + try { + file_destination("core/misc/a\xFFtest\x80€.txt", FILE_EXISTS_REPLACE); + $this->fail('Expected exception not thrown'); + } + catch (RuntimeException $e) { + $this->assertEqual("Invalid filename 'a\xFFtest\x80€.txt'", $e->getMessage()); + } } /** diff --git a/profiles/wcm_base/CHANGELOG.txt b/profiles/wcm_base/CHANGELOG.txt index 95a733ad..5f210c5f 100644 --- a/profiles/wcm_base/CHANGELOG.txt +++ b/profiles/wcm_base/CHANGELOG.txt @@ -1,3 +1,7 @@ +WCM Base 7.x-1.13-rc2, 2019-03-20 +--------------------------------- +- WCM Base: Updated Drupal core to 7.65 per SA-CORE-2019-004. + WCM Base 7.x-1.13-rc1, 2019-03-13 --------------------------------- - WCM Base: -- GitLab