mirror of
https://github.com/golang/go
synced 2024-11-19 00:44:40 -07:00
text/template: don't evaluate '.' as a float64
When using a '.' constant literal as a reflect.Value variadic argument, idealConstant would incorrectly result in a float64. This is because rune literals can be represented as a float64, and contain a period, which tricked the logic into thinking the literal must have been a floating point number. This also happened with other characters that can be part of a floating point number, such as 'e' or 'P'. To fix these edge cases, exit the case sooner if the literal was a rune, since that should always go to the int case instead. Finally, add test cases that verify that they behave properly. These would error before, since eq would receive a mix of int and float64, which aren't comparable. Fixes #34483. Change-Id: Icfcb7803bfa0cf317a1d1adacacad3d69a57eb42 Reviewed-on: https://go-review.googlesource.com/c/go/+/196808 Run-TryBot: Daniel Martí <mvdan@mvdan.cc> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Tom Payne <tom@airmap.com> Reviewed-by: Rob Pike <r@golang.org>
This commit is contained in:
parent
95cbcc5c1c
commit
0f7b4e72a0
@ -496,20 +496,29 @@ func (s *state) idealConstant(constant *parse.NumberNode) reflect.Value {
|
||||
switch {
|
||||
case constant.IsComplex:
|
||||
return reflect.ValueOf(constant.Complex128) // incontrovertible.
|
||||
case constant.IsFloat && !isHexInt(constant.Text) && strings.ContainsAny(constant.Text, ".eEpP"):
|
||||
|
||||
case constant.IsFloat &&
|
||||
!isHexInt(constant.Text) && !isRuneInt(constant.Text) &&
|
||||
strings.ContainsAny(constant.Text, ".eEpP"):
|
||||
return reflect.ValueOf(constant.Float64)
|
||||
|
||||
case constant.IsInt:
|
||||
n := int(constant.Int64)
|
||||
if int64(n) != constant.Int64 {
|
||||
s.errorf("%s overflows int", constant.Text)
|
||||
}
|
||||
return reflect.ValueOf(n)
|
||||
|
||||
case constant.IsUint:
|
||||
s.errorf("%s overflows int", constant.Text)
|
||||
}
|
||||
return zero
|
||||
}
|
||||
|
||||
func isRuneInt(s string) bool {
|
||||
return len(s) > 0 && s[0] == '\''
|
||||
}
|
||||
|
||||
func isHexInt(s string) bool {
|
||||
return len(s) > 2 && s[0] == '0' && (s[1] == 'x' || s[1] == 'X') && !strings.ContainsAny(s, "pP")
|
||||
}
|
||||
|
@ -663,6 +663,12 @@ var execTests = []execTest{
|
||||
{"bug17c", "{{len .NonEmptyInterfacePtS}}", "2", tVal, true},
|
||||
{"bug17d", "{{index .NonEmptyInterfacePtS 0}}", "a", tVal, true},
|
||||
{"bug17e", "{{range .NonEmptyInterfacePtS}}-{{.}}-{{end}}", "-a--b-", tVal, true},
|
||||
|
||||
// More variadic function corner cases. Some runes would get evaluated
|
||||
// as constant floats instead of ints. Issue 34483.
|
||||
{"bug18a", "{{eq . '.'}}", "true", '.', true},
|
||||
{"bug18b", "{{eq . 'e'}}", "true", 'e', true},
|
||||
{"bug18c", "{{eq . 'P'}}", "true", 'P', true},
|
||||
}
|
||||
|
||||
func zeroArgs() string {
|
||||
|
Loading…
Reference in New Issue
Block a user