Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

text/template: constant overflows int in template engine for 386 builds #25833

Closed
arkadiam opened this issue Jun 11, 2018 · 11 comments
Closed

text/template: constant overflows int in template engine for 386 builds #25833

arkadiam opened this issue Jun 11, 2018 · 11 comments
Assignees
Milestone

Comments

@arkadiam
Copy link

@arkadiam arkadiam commented Jun 11, 2018

What version of Go are you using (go version)?

go version go1.10.3 linux/amd64

Does this issue reproduce with the latest release?

yes

What operating system and processor architecture are you using (go env)?

GOARCH="amd64"
GOHOSTARCH="amd64"
GOHOSTOS="linux"

Bug exists when program built as:
env GOOS=linux GOARCH=386 go build
AND
env GOOS=linux GOARCH=386 GO386=387 go build
AND when run in GoPlayground

It works correct in amd64 architecture environment.

What did you do?

I'm trying to compare time.Duration variable with the constant in text/template.

Variable:
duration := 10*time.Minute
Template:
{{if gt . 60000000000}}true{{else}}false{{end}}

If the code is build for 386 architecture it fails with run-time error:
template: :1:10: executing "" at <60000000000>: 60000000000 overflows int

It fails in GoPlayground too:

https://play.golang.org/p/frPKxFsZKE6

What did you expect to see?

template engine should properly evaluate constants like 60000000000 for 386 builds

What did you see instead?

60000000000 overflows int

@alexd765
Copy link
Contributor

@alexd765 alexd765 commented Jun 11, 2018

This is working as intended. According to the spec the untyped constans are bool, rune, int, float64, complex128 or string and int is int32 on 386.

You can achieve your desired outcome by using a func instead of constants.
For example https://play.golang.org/p/WX8lceupjWg

@bcmills
Copy link
Member

@bcmills bcmills commented Jun 11, 2018

This is somewhat related to #20616, in that it's awkward for the validity of a template to depend on the architecture.

@bcmills
Copy link
Member

@bcmills bcmills commented Jun 11, 2018

@alexd765

This is working as intended. […] int is int32 on 386.

In ordinary Go code, an untyped integer constant can exceed the bounds of int as long as it is compared with things larger than an int.
(https://play.golang.org/p/jh8x23eOrEG)

However, as currently implemented in text/template, the meaning of an untyped constant does not depend on the context in which it is used: it doesn't “behave like Go's untyped constants” unless you assume that . is of an interface type, which would be inconsistent with the other behaviors in text/template.

That difference is not mentioned in the text/template documentation. If it is not a bug in the implementation, I would argue that it is a bug in the documentation.

@bcmills bcmills added this to the Go1.12 milestone Jun 11, 2018
@bcmills
Copy link
Member

@bcmills bcmills commented Jun 11, 2018

This needs a decision on whether the defect is in the implementation or the documentation.

@ianlancetaylor ianlancetaylor changed the title Constant overflows int in template engine for 386 builds text/template: constant overflows int in template engine for 386 builds Jun 11, 2018
@arkadiam
Copy link
Author

@arkadiam arkadiam commented Jun 12, 2018

Shouldn't the parser seeing 60000000000 choose appropriate data type, independently from the architecture?

There was mentioning of "untyped constans". Is there way of specifying constant type like:
int64(60000000000) or 60000000000.(int64) or with some other syntax

@alexd765 thanks for the hint with the functions. In my case I've changed constant to float 60.0 and called .Seconds on duration. It gives enough precision for my use case.

@bcmills
Copy link
Member

@bcmills bcmills commented Jun 12, 2018

Shouldn't the parser seeing 60000000000 choose appropriate data type, independently from the architecture?

Ordinary numeric constants in Go are untyped (see https://blog.golang.org/constants). They are interpreted as a specific type only when assigned to or compared with a variable.

Is there way of specifying constant type like:
int64(60000000000) or 60000000000.(int64) or with some other syntax

None that I can find in the text/template documentation.

@bcmills
Copy link
Member

@bcmills bcmills commented Jun 12, 2018

Here is an interesting tidbit from the docs (emphasis mine):

The comparison functions work on basic types only (or named basic types, such as "type Celsius float32"). They implement the Go rules for comparison of values, except that size and exact type are ignored, so any integer value, signed or unsigned, may be compared with any other integer value.

To me, that suggests that the defect is in the implementation.

@rsc
Copy link
Contributor

@rsc rsc commented Sep 26, 2018

Forget that this is gt - that's just a function that anyone can write. The real question is what happens when you call a function expecting interface{} with an ideal very large constant. I think the answer has to be that it turns into int. It would be too surprising for it to turn into int64. This affects all user-installed functions, not just gt.

/cc @robpike

@robpike robpike self-assigned this Sep 26, 2018
@robpike
Copy link
Contributor

@robpike robpike commented Oct 11, 2018

I feel this is missing documentation and will address it there.

@robpike
Copy link
Contributor

@robpike robpike commented Oct 11, 2018

See https://play.golang.org/p/EfqrzctYxRc. Go does this too.

@gopherbot
Copy link

@gopherbot gopherbot commented Oct 11, 2018

Change https://golang.org/cl/141378 mentions this issue: text/template: explain that integer constants can overflow

@gopherbot gopherbot closed this in 9a9dc36 Oct 11, 2018
@golang golang locked and limited conversation to collaborators Oct 11, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
6 participants
You can’t perform that action at this time.