diff --git a/core/modules/search/search.module b/core/modules/search/search.module
index 14ffc80..f95c948 100644
--- a/core/modules/search/search.module
+++ b/core/modules/search/search.module
@@ -985,6 +985,7 @@ function search_form($form, &$form_state, $action = '', $keys = '', $module = NU
     $prompt = t('Enter your keywords');
   }
 
+  $keys = _search_escape_initial_char($keys, TRUE);
   $form['#action'] = url($action);
   // Record the $action for later use in redirecting.
   $form_state['action'] = $action;
@@ -1052,7 +1053,7 @@ function search_box_form_submit($form, &$form_state) {
   $form_id = $form['form_id']['#value'];
   $info = search_get_default_module_info();
   if ($info) {
-    $form_state['redirect'] = 'search/' . $info['path'] . '/' . trim($form_state['values'][$form_id]);
+    $form_state['redirect'] = 'search/' . $info['path'] . '/' . _search_escape_initial_char(trim($form_state['values'][$form_id]));
   }
   else {
     form_set_error(NULL, t('Search is currently disabled.'), 'error');
@@ -1074,6 +1075,7 @@ function search_box_form_submit($form, &$form_state) {
  *   supplied or if the given search module is not active.
  */
 function search_data($keys, $module, $conditions = NULL) {
+  $keys = _search_escape_initial_char($keys, TRUE);
   if (module_hook($module, 'search_execute')) {
     $results = module_invoke($module, 'search_execute', $keys, $conditions);
     if (module_hook($module, 'search_page')) {
@@ -1326,3 +1328,24 @@ function search_forms() {
   );
   return $forms;
 }
+
+/**
+ * Url en- or decodes a '.' if it is the initial character in a string.
+ *
+ * @param string $string
+ *   The string to have encoded or decoded.
+ * @param bool $encode
+ *   Wether to en- or decode. Defaults to TRUE that will encode.
+ *
+ * @return string
+ *   The string with any initial '.' url en- or decoded.
+ **/
+function _search_escape_initial_char($string, $encode = TRUE) {
+  if ($encode && (substr($string, 0, 1) == '.')) {
+    return '%2E' . substr($string, 1);
+  }
+  elseif (substr($string, 0, 3) == '%2E') {
+    return '.' . substr($string, 3);
+  }
+  return $string;
+}
diff --git a/core/modules/search/search.pages.inc b/core/modules/search/search.pages.inc
index 1b7c3ef..5b5ef3c 100644
--- a/core/modules/search/search.pages.inc
+++ b/core/modules/search/search.pages.inc
@@ -154,7 +154,6 @@ function search_form_submit($form, &$form_state) {
     form_set_error('keys', t('Please enter some keywords.'));
     // Fall through to the form redirect.
   }
-
-  $form_state['redirect'] = $form_state['action'] . '/' . $keys;
+  $form_state['redirect'] = $form_state['action'] . '/' . _search_escape_initial_char($keys);
   return;
 }
diff --git a/core/modules/search/search.test b/core/modules/search/search.test
index 1ee4e6f..64a0e95 100644
--- a/core/modules/search/search.test
+++ b/core/modules/search/search.test
@@ -1252,6 +1252,10 @@ class SearchNumbersTestCase extends DrupalWebTestCase {
   function setUp() {
     parent::setUp('search');
 
+    // Turn clean urls on. There can be problems with searches starting with
+    // a '.' with clean urls on, so make sure this gets tested.
+    variable_set('clean_url', 1);
+
     $this->test_user = $this->drupalCreateUser(array('search content', 'access content', 'administer nodes', 'access site reports'));
     $this->drupalLogin($this->test_user);
 
@@ -1273,6 +1277,7 @@ class SearchNumbersTestCase extends DrupalWebTestCase {
       'over fifty characters' => '666666666666666666666666666666666666666666666666666666666666',
       'date', '01/02/2009',
       'commas', '987,654,321',
+      'starting decimal', '.35',
     );
 
     foreach ($this->numbers as $doc => $num) {
