From e89087fc5136444fb669aa74751ad825214976c0 Mon Sep 17 00:00:00 2001 From: epriestley Date: Thu, 10 Aug 2017 03:31:20 -0700 Subject: [PATCH] Fix a hang in fancy date picker for Ye Olde Time Years Summary: Fixes T12960. When the user enters a date like "1917", we currently loop ~20 million times. Instead: - Be a little more careful about parsing. - Javascript's default behavior of interpreting "2001-02-31" as "2001-03-03" ("February 31" -> "March 3") already seems reasonable, so just let it do that. Test Plan: Verified these behaviors: - `2017-08-08` - Valid, recent. - `17-08-08` - Valid, recent. - `1917-08-08` - Valid, a century ago, no loop. - `2017-02-31` - "February 31", interpreted as "March 3" by Javascsript, seems reasonable. - `Quack` - Default, current time. - `0/0/0`, `0/99/0` - Default, current time. Reviewers: avivey, chad Reviewed By: chad Maniphest Tasks: T12960 Differential Revision: https://secure.phabricator.com/D18383 --- resources/celerity/map.php | 18 ++++---- .../rsrc/js/core/behavior-fancy-datepicker.js | 44 ++++++++++++------- 2 files changed, 37 insertions(+), 25 deletions(-) diff --git a/resources/celerity/map.php b/resources/celerity/map.php index c0bc1bf629..54832d23ae 100644 --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -484,7 +484,7 @@ return array( 'rsrc/js/core/behavior-device.js' => 'bb1dd507', 'rsrc/js/core/behavior-drag-and-drop-textarea.js' => '484a6e22', 'rsrc/js/core/behavior-error-log.js' => '6882e80a', - 'rsrc/js/core/behavior-fancy-datepicker.js' => 'a9210d03', + 'rsrc/js/core/behavior-fancy-datepicker.js' => 'ecf4e799', 'rsrc/js/core/behavior-file-tree.js' => '88236f00', 'rsrc/js/core/behavior-form.js' => '5c54cbf3', 'rsrc/js/core/behavior-gesture.js' => '3ab51e2c', @@ -633,7 +633,7 @@ return array( 'javelin-behavior-editengine-reorder-fields' => 'b59e1e96', 'javelin-behavior-error-log' => '6882e80a', 'javelin-behavior-event-all-day' => 'b41537c9', - 'javelin-behavior-fancy-datepicker' => 'a9210d03', + 'javelin-behavior-fancy-datepicker' => 'ecf4e799', 'javelin-behavior-global-drag-and-drop' => '960f6a39', 'javelin-behavior-herald-rule-editor' => '7ebaeed3', 'javelin-behavior-high-security-warning' => 'a464fe03', @@ -1716,13 +1716,6 @@ return array( 'javelin-uri', 'phabricator-keyboard-shortcut', ), - 'a9210d03' => array( - 'javelin-behavior', - 'javelin-util', - 'javelin-dom', - 'javelin-stratcom', - 'javelin-vector', - ), 'a9f88de2' => array( 'javelin-behavior', 'javelin-dom', @@ -2105,6 +2098,13 @@ return array( 'javelin-dom', 'phabricator-draggable-list', ), + 'ecf4e799' => array( + 'javelin-behavior', + 'javelin-util', + 'javelin-dom', + 'javelin-stratcom', + 'javelin-vector', + ), 'edf8a145' => array( 'javelin-behavior', 'javelin-uri', diff --git a/webroot/rsrc/js/core/behavior-fancy-datepicker.js b/webroot/rsrc/js/core/behavior-fancy-datepicker.js index 15558dbfe1..afd5ff25ad 100644 --- a/webroot/rsrc/js/core/behavior-fancy-datepicker.js +++ b/webroot/rsrc/js/core/behavior-fancy-datepicker.js @@ -287,26 +287,38 @@ JX.behavior('fancy-datepicker', function(config, statics) { }; function getValidDate() { - var written_date = new Date(value_y, value_m-1, value_d); + var year_int = parseInt(value_y, 10); + if (isNaN(year_int) || year_int < 0) { + return new Date(); + } + + // If the user enters "11" for the year, interpret it as "2011" (which + // is almost certainly what they mean) not "1911" (which is the default + // behavior of Javascript). + if (year_int < 70) { + year_int += 2000; + } + + var month_int = parseInt(value_m, 10); + if (isNaN(month_int) || month_int < 1 || month_int > 12) { + return new Date(); + } + + // In Javascript, January is "0", not "1", so adjust the value down. + month_int = month_int - 1; + + var day_int = parseInt(value_d, 10); + if (isNaN(day_int) || day_int < 1 || day_int > 31) { + return new Date(); + } + + var written_date = new Date(year_int, month_int, day_int); if (isNaN(written_date.getTime())) { return new Date(); - } else { - //year 01 should be 2001, not 1901 - if (written_date.getYear() < 70) { - value_y += 2000; - written_date = new Date(value_y, value_m-1, value_d); - } - - // adjust for a date like February 31 - var adjust = 1; - while (written_date.getMonth() !== value_m-1) { - written_date = new Date(value_y, value_m-1, value_d-adjust); - adjust++; - } - - return written_date; } + + return written_date; }