Skip to content

Commit

Permalink
Merge pull request #3460 from kolyshkin/no-regexp
Browse files Browse the repository at this point in the history
Do not use regexp
  • Loading branch information
thaJeztah committed Feb 6, 2023
2 parents 32d7413 + 0ac9880 commit df47453
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 18 deletions.
27 changes: 15 additions & 12 deletions libcontainer/cgroups/systemd/common.go
Expand Up @@ -6,7 +6,6 @@ import (
"fmt"
"math"
"os"
"regexp"
"strconv"
"strings"
"sync"
Expand Down Expand Up @@ -231,18 +230,22 @@ func systemdVersion(cm *dbusConnManager) int {
return version
}

func systemdVersionAtoi(verStr string) (int, error) {
// verStr should be of the form:
// "v245.4-1.fc32", "245", "v245-1.fc32", "245-1.fc32" (without quotes).
// The result for all of the above should be 245.
// Thus, we unconditionally remove the "v" prefix
// and then match on the first integer we can grab.
re := regexp.MustCompile(`v?([0-9]+)`)
matches := re.FindStringSubmatch(verStr)
if len(matches) < 2 {
return 0, fmt.Errorf("can't parse version %s: incorrect number of matches %v", verStr, matches)
// systemdVersionAtoi extracts a numeric systemd version from the argument.
// The argument should be of the form: "v245.4-1.fc32", "245", "v245-1.fc32",
// "245-1.fc32" (with or without quotes). The result for all of the above
// should be 245.
func systemdVersionAtoi(str string) (int, error) {
// Unconditionally remove the leading prefix ("v).
str = strings.TrimLeft(str, `"v`)
// Match on the first integer we can grab.
for i := 0; i < len(str); i++ {
if str[i] < '0' || str[i] > '9' {
// First non-digit: cut the tail.
str = str[:i]
break
}
}
ver, err := strconv.Atoi(matches[1])
ver, err := strconv.Atoi(str)
if err != nil {
return -1, fmt.Errorf("can't parse version: %w", err)
}
Expand Down
7 changes: 5 additions & 2 deletions libcontainer/cgroups/systemd/systemd_test.go
Expand Up @@ -35,8 +35,11 @@ func TestSystemdVersion(t *testing.T) {
{`"v245.4-1.fc32"`, 245, false},
{`"241-1"`, 241, false},
{`"v241-1"`, 241, false},
{"NaN", 0, true},
{"", 0, true},
{`333.45"`, 333, false},
{`v321-0`, 321, false},
{"NaN", -1, true},
{"", -1, true},
{"v", -1, true},
}
for _, sdTest := range systemdVersionTests {
ver, err := systemdVersionAtoi(sdTest.verStr)
Expand Down
44 changes: 40 additions & 4 deletions libcontainer/factory_linux.go
Expand Up @@ -5,7 +5,6 @@ import (
"errors"
"fmt"
"os"
"regexp"
"runtime/debug"
"strconv"

Expand All @@ -27,8 +26,6 @@ const (
execFifoFilename = "exec.fifo"
)

var idRegex = regexp.MustCompile(`^[\w+-\.]+$`)

// Create creates a new container with the given id inside a given state
// directory (root), and returns a Container object.
//
Expand Down Expand Up @@ -260,8 +257,47 @@ func loadState(root string) (*State, error) {
return state, nil
}

// validateID checks if the supplied container ID is valid, returning
// the ErrInvalidID in case it is not.
//
// The format of valid ID was never formally defined, instead the code
// was modified to allow or disallow specific characters.
//
// Currently, a valid ID is a non-empty string consisting only of
// the following characters:
// - uppercase (A-Z) and lowercase (a-z) Latin letters;
// - digits (0-9);
// - underscore (_);
// - plus sign (+);
// - minus sign (-);
// - period (.).
//
// In addition, IDs that can't be used to represent a file name
// (such as . or ..) are rejected.

func validateID(id string) error {
if !idRegex.MatchString(id) || string(os.PathSeparator)+id != utils.CleanPath(string(os.PathSeparator)+id) {
if len(id) < 1 {
return ErrInvalidID
}

// Allowed characters: 0-9 A-Z a-z _ + - .
for i := 0; i < len(id); i++ {
c := id[i]
switch {
case c >= 'a' && c <= 'z':
case c >= 'A' && c <= 'Z':
case c >= '0' && c <= '9':
case c == '_':
case c == '+':
case c == '-':
case c == '.':
default:
return ErrInvalidID
}

}

if string(os.PathSeparator)+id != utils.CleanPath(string(os.PathSeparator)+id) {
return ErrInvalidID
}

Expand Down

0 comments on commit df47453

Please sign in to comment.