diff --git a/src/applications/auth/provider/PhabricatorAuthProviderOAuth1JIRA.php b/src/applications/auth/provider/PhabricatorAuthProviderOAuth1JIRA.php
--- a/src/applications/auth/provider/PhabricatorAuthProviderOAuth1JIRA.php
+++ b/src/applications/auth/provider/PhabricatorAuthProviderOAuth1JIRA.php
@@ -114,7 +114,7 @@
     if (!strlen($values[$key_name])) {
       $errors[] = pht('JIRA instance name is required.');
       $issues[$key_name] = pht('Required');
-    } else if (!preg_match('/^[a-z0-9.]+$/', $values[$key_name])) {
+    } else if (!preg_match('/^[a-z0-9.]+\z/', $values[$key_name])) {
       $errors[] = pht(
         'JIRA instance name must contain only lowercase letters, digits, and '.
         'period.');
diff --git a/src/applications/diffusion/conduit/ConduitAPI_diffusion_getcommits_Method.php b/src/applications/diffusion/conduit/ConduitAPI_diffusion_getcommits_Method.php
--- a/src/applications/diffusion/conduit/ConduitAPI_diffusion_getcommits_Method.php
+++ b/src/applications/diffusion/conduit/ConduitAPI_diffusion_getcommits_Method.php
@@ -41,7 +41,7 @@
     $commits = array_fill_keys($commits, array());
     foreach ($commits as $name => $info) {
       $matches = null;
-      if (!preg_match('/^r([A-Z]+)([0-9a-f]+)$/', $name, $matches)) {
+      if (!preg_match('/^r([A-Z]+)([0-9a-f]+)\z/', $name, $matches)) {
         $results[$name] = array(
           'error' => 'ERR-UNPARSEABLE',
         );
diff --git a/src/applications/diffusion/controller/DiffusionRepositoryCreateController.php b/src/applications/diffusion/controller/DiffusionRepositoryCreateController.php
--- a/src/applications/diffusion/controller/DiffusionRepositoryCreateController.php
+++ b/src/applications/diffusion/controller/DiffusionRepositoryCreateController.php
@@ -365,7 +365,7 @@
       $c_call->setError(pht('Required'));
       $page->addPageError(
         pht('You must choose a callsign for this repository.'));
-    } else if (!preg_match('/^[A-Z]+$/', $v_call)) {
+    } else if (!preg_match('/^[A-Z]+\z/', $v_call)) {
       $c_call->setError(pht('Invalid'));
       $page->addPageError(
         pht('The callsign must contain only UPPERCASE letters.'));
diff --git a/src/applications/diffusion/ssh/DiffusionSSHSubversionServeWorkflow.php b/src/applications/diffusion/ssh/DiffusionSSHSubversionServeWorkflow.php
--- a/src/applications/diffusion/ssh/DiffusionSSHSubversionServeWorkflow.php
+++ b/src/applications/diffusion/ssh/DiffusionSSHSubversionServeWorkflow.php
@@ -233,7 +233,7 @@
       rtrim($repository->getLocalPath(), '/'),
       $path);
 
-    if (preg_match('(^/diffusion/[A-Z]+/$)', $path)) {
+    if (preg_match('(^/diffusion/[A-Z]+/\z)', $path)) {
       $path = rtrim($path, '/');
     }
 
diff --git a/src/applications/diffusion/ssh/DiffusionSSHWorkflow.php b/src/applications/diffusion/ssh/DiffusionSSHWorkflow.php
--- a/src/applications/diffusion/ssh/DiffusionSSHWorkflow.php
+++ b/src/applications/diffusion/ssh/DiffusionSSHWorkflow.php
@@ -54,7 +54,7 @@
   protected function loadRepository($path) {
     $viewer = $this->getUser();
 
-    $regex = '@^/?diffusion/(?P<callsign>[A-Z]+)(?:/|$)@';
+    $regex = '@^/?diffusion/(?P<callsign>[A-Z]+)(?:/|\z)@';
     $matches = null;
     if (!preg_match($regex, $path, $matches)) {
       throw new Exception(
diff --git a/src/applications/diviner/atom/DivinerAtomRef.php b/src/applications/diviner/atom/DivinerAtomRef.php
--- a/src/applications/diviner/atom/DivinerAtomRef.php
+++ b/src/applications/diviner/atom/DivinerAtomRef.php
@@ -43,7 +43,7 @@
 
   public function setName($name) {
     $normal_name = self::normalizeString($name);
-    if (preg_match('/^@[0-9]+$/', $normal_name)) {
+    if (preg_match('/^@[0-9]+\z/', $normal_name)) {
       throw new Exception(
         "Atom names must not be in the form '/@\d+/'. This pattern is ".
         "reserved for disambiguating atoms with similar names.");
diff --git a/src/applications/diviner/workflow/DivinerWorkflow.php b/src/applications/diviner/workflow/DivinerWorkflow.php
--- a/src/applications/diviner/workflow/DivinerWorkflow.php
+++ b/src/applications/diviner/workflow/DivinerWorkflow.php
@@ -52,7 +52,7 @@
     }
     $book['root'] = Filesystem::resolvePath($book['root'], $full_path);
 
-    if (!preg_match('/^[a-z][a-z-]*$/', $book['name'])) {
+    if (!preg_match('/^[a-z][a-z-]*\z/', $book['name'])) {
       $name = $book['name'];
       throw new PhutilArgumentUsageException(
         "Book configuration '{$book_path}' has name '{$name}', but book names ".
diff --git a/src/applications/files/engine/PhabricatorLocalDiskFileStorageEngine.php b/src/applications/files/engine/PhabricatorLocalDiskFileStorageEngine.php
--- a/src/applications/files/engine/PhabricatorLocalDiskFileStorageEngine.php
+++ b/src/applications/files/engine/PhabricatorLocalDiskFileStorageEngine.php
@@ -113,7 +113,7 @@
     // Make sure there's no funny business going on here. Users normally have
     // no ability to affect the content of handles, but double-check that
     // we're only accessing local storage just in case.
-    if (!preg_match('@^[a-f0-9]{2}/[a-f0-9]{2}/[a-f0-9]{28}$@', $handle)) {
+    if (!preg_match('@^[a-f0-9]{2}/[a-f0-9]{2}/[a-f0-9]{28}\z@', $handle)) {
       throw new Exception(
         "Local disk filesystem handle '{$handle}' is malformed!");
     }
diff --git a/src/applications/macro/controller/PhabricatorMacroEditController.php b/src/applications/macro/controller/PhabricatorMacroEditController.php
--- a/src/applications/macro/controller/PhabricatorMacroEditController.php
+++ b/src/applications/macro/controller/PhabricatorMacroEditController.php
@@ -48,7 +48,7 @@
         if (!strlen($macro->getName())) {
           $errors[] = pht('Macro name is required.');
           $e_name = pht('Required');
-        } else if (!preg_match('/^[a-z0-9:_-]{3,}$/', $macro->getName())) {
+        } else if (!preg_match('/^[a-z0-9:_-]{3,}\z/', $macro->getName())) {
           $errors[] = pht(
             'Macro must be at least three characters long and contain only '.
             'lowercase letters, digits, hyphens, colons and underscores.');
diff --git a/src/applications/people/storage/PhabricatorUser.php b/src/applications/people/storage/PhabricatorUser.php
--- a/src/applications/people/storage/PhabricatorUser.php
+++ b/src/applications/people/storage/PhabricatorUser.php
@@ -610,7 +610,7 @@
       return false;
     }
 
-    return (bool)preg_match('/^[a-zA-Z0-9._-]*[a-zA-Z0-9_-]$/', $username);
+    return (bool)preg_match('/^[a-zA-Z0-9._-]*[a-zA-Z0-9_-]\z/', $username);
   }
 
   public static function getDefaultProfileImageURI() {
diff --git a/src/applications/people/storage/PhabricatorUserEmail.php b/src/applications/people/storage/PhabricatorUserEmail.php
--- a/src/applications/people/storage/PhabricatorUserEmail.php
+++ b/src/applications/people/storage/PhabricatorUserEmail.php
@@ -49,7 +49,7 @@
     // To this end, we're roughly verifying that there's some normal text, an
     // "@" symbol, and then some more normal text.
 
-    $email_regex = '(^[a-z0-9_+.!-]+@[a-z0-9_+:.-]+$)i';
+    $email_regex = '(^[a-z0-9_+.!-]+@[a-z0-9_+:.-]+\z)i';
     if (!preg_match($email_regex, $address)) {
       return false;
     }
diff --git a/src/applications/people/storage/__tests__/PhabricatorUserEmailTestCase.php b/src/applications/people/storage/__tests__/PhabricatorUserEmailTestCase.php
--- a/src/applications/people/storage/__tests__/PhabricatorUserEmailTestCase.php
+++ b/src/applications/people/storage/__tests__/PhabricatorUserEmailTestCase.php
@@ -27,6 +27,13 @@
       '@@' => false,
       '@' => false,
       'user@' => false,
+
+      "user@domain.com\n" => false,
+      "user@\ndomain.com" => false,
+      "\nuser@domain.com" => false,
+      "user@domain.com\r" => false,
+      "user@\rdomain.com" => false,
+      "\ruser@domain.com" => false,
     );
 
     foreach ($tests as $input => $expect) {
diff --git a/src/applications/people/storage/__tests__/PhabricatorUserTestCase.php b/src/applications/people/storage/__tests__/PhabricatorUserTestCase.php
--- a/src/applications/people/storage/__tests__/PhabricatorUserTestCase.php
+++ b/src/applications/people/storage/__tests__/PhabricatorUserTestCase.php
@@ -36,6 +36,13 @@
       'a,lincoln'   => false,
       'a&lincoln'   => false,
       'a/lincoln'   => false,
+
+      "username\n"  => false,
+      "user\nname"  => false,
+      "\nusername"  => false,
+      "username\r"  => false,
+      "user\rname"  => false,
+      "\rusername"  => false,
     );
 
     foreach ($map as $name => $expect) {
diff --git a/src/applications/phlux/controller/PhluxEditController.php b/src/applications/phlux/controller/PhluxEditController.php
--- a/src/applications/phlux/controller/PhluxEditController.php
+++ b/src/applications/phlux/controller/PhluxEditController.php
@@ -48,7 +48,7 @@
         if (!strlen($key)) {
           $errors[] = pht('Variable key is required.');
           $e_key = pht('Required');
-        } else if (!preg_match('/^[a-z0-9.-]+$/', $key)) {
+        } else if (!preg_match('/^[a-z0-9.-]+\z/', $key)) {
           $errors[] = pht(
             'Variable key "%s" must contain only lowercase letters, digits, '.
             'period, and hyphen.',
diff --git a/src/applications/repository/conduit/ConduitAPI_repository_create_Method.php b/src/applications/repository/conduit/ConduitAPI_repository_create_Method.php
--- a/src/applications/repository/conduit/ConduitAPI_repository_create_Method.php
+++ b/src/applications/repository/conduit/ConduitAPI_repository_create_Method.php
@@ -79,7 +79,7 @@
     $repository->setName($request->getValue('name'));
 
     $callsign = $request->getValue('callsign');
-    if (!preg_match('/^[A-Z]+$/', $callsign)) {
+    if (!preg_match('/^[A-Z]+\z/', $callsign)) {
       throw new ConduitException('ERR-BAD-CALLSIGN');
     }
     $repository->setCallsign($callsign);