@@ -470,28 +470,73 @@ func simpleNormalizePath(path string) (string, bool) {
470
470
return "" , false
471
471
}
472
472
473
+ // hasRelativePathSegment reports whether p contains ".", "..", "./", "../", "/.", "/..", "//", "/./", or "/../".
473
474
func hasRelativePathSegment (p string ) bool {
474
- if p == "." || p == ".." {
475
- return true
475
+ n := len (p )
476
+ if n == 0 {
477
+ return false
476
478
}
477
479
478
- if strings . HasPrefix ( p , "./" ) || strings . HasPrefix ( p , "../" ) {
480
+ if p == "." || p == ".." {
479
481
return true
480
482
}
481
483
482
- if strings .HasSuffix (p , "/." ) || strings .HasSuffix (p , "/.." ) {
483
- return true
484
+ // Leading "./" OR "../"
485
+ if p [0 ] == '.' {
486
+ if n >= 2 && p [1 ] == '/' {
487
+ return true
488
+ }
489
+ // Leading "../"
490
+ if n >= 3 && p [1 ] == '.' && p [2 ] == '/' {
491
+ return true
492
+ }
484
493
}
485
-
486
- if strings .Contains (p , "//" ) {
487
- return true
494
+ // Trailing "/." OR "/.."
495
+ if p [n - 1 ] == '.' {
496
+ if n >= 2 && p [n - 2 ] == '/' {
497
+ return true
498
+ }
499
+ if n >= 3 && p [n - 2 ] == '.' && p [n - 3 ] == '/' {
500
+ return true
501
+ }
488
502
}
489
503
490
- if strings .Contains (p , "/./" ) || strings .Contains (p , "/../" ) {
491
- return true
504
+ // Now look for any `//` or `/./` or `/../`
505
+
506
+ prevSlash := false
507
+ segLen := 0 // length of current segment since last slash
508
+ dotCount := 0 // consecutive dots at start of the current segment; -1 => not only dots
509
+
510
+ for i := range n {
511
+ c := p [i ]
512
+ if c == '/' {
513
+ // "//"
514
+ if prevSlash {
515
+ return true
516
+ }
517
+ // "/./" or "/../"
518
+ if (segLen == 1 && dotCount == 1 ) || (segLen == 2 && dotCount == 2 ) {
519
+ return true
520
+ }
521
+ prevSlash = true
522
+ segLen = 0
523
+ dotCount = 0
524
+ continue
525
+ }
526
+
527
+ if c == '.' {
528
+ if dotCount >= 0 {
529
+ dotCount ++
530
+ }
531
+ } else {
532
+ dotCount = - 1
533
+ }
534
+ segLen ++
535
+ prevSlash = false
492
536
}
493
537
494
- return false
538
+ // Trailing "/." or "/.."
539
+ return (segLen == 1 && dotCount == 1 ) || (segLen == 2 && dotCount == 2 )
495
540
}
496
541
497
542
func NormalizePath (path string ) string {
0 commit comments