Skip to content

Commit

Permalink
ctime parser: check int bounds
Browse files Browse the repository at this point in the history
  • Loading branch information
apreiml committed Mar 22, 2020
1 parent 6d71211 commit 44e947b
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 12 deletions.
37 changes: 26 additions & 11 deletions ctime/strptime.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,12 +81,27 @@ func (state *parseState) expectNext(expected string) {
state.next()
}

func (state *parseState) nextInt(chars int) int {
s := string(state.read(chars))
func (state *parseState) readInt(length int) int {
s := string(state.read(length))
i, err := strconv.Atoi(s)
if err != nil {
panic("Expected integer")
}
return i
}


func (state *parseState) nextInt(length int) int {
i := state.readInt(length)
state.next()
return i
}

func (state *parseState) nextIntBetween(length, min, max int) int {
i := state.readInt(length)
if (i < min || i > max) {
panic(fmt.Sprintf("Expected integer between %d and %d", min, max))
}
state.next()
return i
}
Expand All @@ -111,28 +126,28 @@ func (state *parseState) parseFormat() {
case '%':
state.expectNext("%")
case 'Y':
state.time.year = state.nextInt(4)
state.time.year = state.nextIntBetween(4, 0000, 9999)
case 'm':
state.time.month = state.nextInt(2)
state.time.month = state.nextIntBetween(2, 1, 12)
case 'd':
state.time.day = state.nextInt(2)
state.time.day = state.nextIntBetween(2, 1, 31)
case 'D':
state.time.month = state.nextInt(2)
state.time.month = state.nextIntBetween(2, 1, 12)
state.expectNext("/")
state.time.day = state.nextInt(2)
state.time.day = state.nextIntBetween(2, 1, 31)
state.expectNext("/")
year := state.nextInt(2)
year := state.nextIntBetween(2, 00, 99)
if year >= 69 {
state.time.year = 1900 + year
} else {
state.time.year = 2000 + year
}
case 'H':
state.time.hour = state.nextInt(2)
state.time.hour = state.nextIntBetween(2, 0, 24)
case 'M':
state.time.minute = state.nextInt(2)
state.time.minute = state.nextIntBetween(2, 0, 59)
case 'S':
state.time.second = state.nextInt(2)
state.time.second = state.nextIntBetween(2, 0, 59)
default:
panic(fmt.Sprintf("Unsupported format specifier %%%c. Patches are welcome.", f))
}
Expand Down
5 changes: 4 additions & 1 deletion ctime/strptime_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ func TestParseFail(t *testing.T) {
cases := []struct {
format, in string
}{
{"asdf", "jkld"},
{"asdf", "jkl;"},
{"aa", "a"},
{"%Y-%d-%m", "2020-12-28"},
{"%", "%"},
}

Expand All @@ -29,6 +31,7 @@ func TestSimple(t *testing.T) {
{"nodate", "nodate", "0001-01-01T00:00:00Z"},
{"%%", "%", "0001-01-01T00:00:00Z"},
{"%Y", "2020", "2020-01-01T00:00:00Z"},
{"%Y-%m-%d", "2020-12-28", "2020-12-28T00:00:00Z"},
{"%Y-%m-%d %H:%M:%S", "2020-02-12 17:37:25", "2020-02-12T17:37:25Z"},
{"%D", "02/12/20", "2020-02-12T00:00:00Z"},
{"example.org-%Y-%d-%m-%H-%M.sql.gpg", "example.org-2020-31-01-23-00.sql.gpg", "2020-01-31T23:00:00Z"},
Expand Down

0 comments on commit 44e947b

Please sign in to comment.