express

4.17.14.18.2
lib/router/index.js
~lib/router/index.jsModified
+25−14
Index: package/lib/router/index.js
===================================================================
--- package/lib/router/index.js
+++ package/lib/router/index.js
@@ -107,10 +107,10 @@
   var len = params.length;
   var ret;
 
   if (name[0] === ':') {
-    deprecate('router.param(' + JSON.stringify(name) + ', fn): Use router.param(' + JSON.stringify(name.substr(1)) + ', fn) instead');
-    name = name.substr(1);
+    deprecate('router.param(' + JSON.stringify(name) + ', fn): Use router.param(' + JSON.stringify(name.slice(1)) + ', fn) instead')
+    name = name.slice(1)
   }
 
   for (var i = 0; i < len; ++i) {
     if (ret = params[i](name, fn)) {
@@ -141,8 +141,9 @@
   var idx = 0;
   var protohost = getProtohost(req.url) || ''
   var removed = '';
   var slashAdded = false;
+  var sync = 0
   var paramcalled = {};
 
   // store options for OPTIONS request
   // only used if OPTIONS request
@@ -179,16 +180,16 @@
       : err;
 
     // remove added slash
     if (slashAdded) {
-      req.url = req.url.substr(1);
+      req.url = req.url.slice(1)
       slashAdded = false;
     }
 
     // restore altered req.url
     if (removed.length !== 0) {
       req.baseUrl = parentUrl;
-      req.url = protohost + removed + req.url.substr(protohost.length);
+      req.url = protohost + removed + req.url.slice(protohost.length)
       removed = '';
     }
 
     // signal to exit router
@@ -202,8 +203,13 @@
       setImmediate(done, layerError);
       return;
     }
 
+    // max sync stack
+    if (++sync > 100) {
+      return setImmediate(next, err)
+    }
+
     // get pathname of request
     var path = getPathname(req);
 
     if (path == null) {
@@ -250,9 +256,8 @@
 
       // don't even bother matching route
       if (!has_method && method !== 'HEAD') {
         match = false;
-        continue;
       }
     }
 
     // no match
@@ -273,30 +278,36 @@
 
     // this should be done for the layer
     self.process_params(layer, paramcalled, req, res, function (err) {
       if (err) {
-        return next(layerError || err);
+        next(layerError || err)
+      } else if (route) {
+        layer.handle_request(req, res, next)
+      } else {
+        trim_prefix(layer, layerError, layerPath, path)
       }
 
-      if (route) {
-        return layer.handle_request(req, res, next);
-      }
-
-      trim_prefix(layer, layerError, layerPath, path);
+      sync = 0
     });
   }
 
   function trim_prefix(layer, layerError, layerPath, path) {
     if (layerPath.length !== 0) {
+      // Validate path is a prefix match
+      if (layerPath !== path.slice(0, layerPath.length)) {
+        next(layerError)
+        return
+      }
+
       // Validate path breaks on a path separator
       var c = path[layerPath.length]
       if (c && c !== '/' && c !== '.') return next(layerError)
 
       // Trim off the part of the url that matches the route
       // middleware (.use stuff) needs to have the path stripped
       debug('trim prefix (%s) from url %s', layerPath, req.url);
       removed = layerPath;
-      req.url = protohost + req.url.substr(protohost.length + removed.length);
+      req.url = protohost + req.url.slice(protohost.length + removed.length)
 
       // Ensure leading slash
       if (!protohost && req.url[0] !== '/') {
         req.url = '/' + req.url;
@@ -540,12 +551,12 @@
   var searchIndex = url.indexOf('?')
   var pathLength = searchIndex !== -1
     ? searchIndex
     : url.length
-  var fqdnIndex = url.substr(0, pathLength).indexOf('://')
+  var fqdnIndex = url.slice(0, pathLength).indexOf('://')
 
   return fqdnIndex !== -1
-    ? url.substr(0, url.indexOf('/', 3 + fqdnIndex))
+    ? url.substring(0, url.indexOf('/', 3 + fqdnIndex))
     : undefined
 }
 
 // get type for error message