Skip to content

Commit

Permalink
cmd/compile: fix type checking of "make" arguments
Browse files Browse the repository at this point in the history
As part of type checking make's arguments, we were converting untyped
float and complex constant arguments to integers. However, we were
doing this without concern for whether the argument was a declared
constant. Thus a call like "make([]T, n)" could change n from an
untyped float or untyped complex to an untyped integer.

The fix here is to simply change checkmake to not call SetVal, which
will be handled by defaultlit anyway. However, we also need to
properly return the defaultlit result value to the caller, so
checkmake's *Node parameter is also changed to **Node.

Fixes #41680.

Change-Id: I858927a052f384ec38684570d37b10a6906961f7
Reviewed-on: https://go-review.googlesource.com/c/go/+/257966
Trust: Matthew Dempsky <[email protected]>
Run-TryBot: Matthew Dempsky <[email protected]>
Reviewed-by: Cuong Manh Le <[email protected]>
TryBot-Result: Go Bot <[email protected]>
  • Loading branch information
mdempsky committed Sep 28, 2020
1 parent c4971a1 commit ad0ab81
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 7 deletions.
16 changes: 9 additions & 7 deletions src/cmd/compile/internal/gc/typecheck.go
Original file line number Diff line number Diff line change
Expand Up @@ -1770,7 +1770,7 @@ func typecheck1(n *Node, top int) (res *Node) {
n.Type = nil
return n
}
if !checkmake(t, "len", l) || r != nil && !checkmake(t, "cap", r) {
if !checkmake(t, "len", &l) || r != nil && !checkmake(t, "cap", &r) {
n.Type = nil
return n
}
Expand All @@ -1794,7 +1794,7 @@ func typecheck1(n *Node, top int) (res *Node) {
n.Type = nil
return n
}
if !checkmake(t, "size", l) {
if !checkmake(t, "size", &l) {
n.Type = nil
return n
}
Expand All @@ -1815,7 +1815,7 @@ func typecheck1(n *Node, top int) (res *Node) {
n.Type = nil
return n
}
if !checkmake(t, "buffer", l) {
if !checkmake(t, "buffer", &l) {
n.Type = nil
return n
}
Expand Down Expand Up @@ -3729,7 +3729,8 @@ ret:
n.SetWalkdef(1)
}

func checkmake(t *types.Type, arg string, n *Node) bool {
func checkmake(t *types.Type, arg string, np **Node) bool {
n := *np
if !n.Type.IsInteger() && n.Type.Etype != TIDEAL {
yyerror("non-integer %s argument in make(%v) - %v", arg, t, n.Type)
return false
Expand All @@ -3739,12 +3740,12 @@ func checkmake(t *types.Type, arg string, n *Node) bool {
// to avoid redundant "constant NNN overflows int" errors.
switch consttype(n) {
case CTINT, CTRUNE, CTFLT, CTCPLX:
n.SetVal(toint(n.Val()))
if n.Val().U.(*Mpint).CmpInt64(0) < 0 {
v := toint(n.Val()).U.(*Mpint)
if v.CmpInt64(0) < 0 {
yyerror("negative %s argument in make(%v)", arg, t)
return false
}
if n.Val().U.(*Mpint).Cmp(maxintval[TINT]) > 0 {
if v.Cmp(maxintval[TINT]) > 0 {
yyerror("%s argument too large in make(%v)", arg, t)
return false
}
Expand All @@ -3756,6 +3757,7 @@ func checkmake(t *types.Type, arg string, n *Node) bool {
// for instance, indexlit might be called here and incorporate some
// of the bounds checks done for make.
n = defaultlit(n, types.Types[TINT])
*np = n

return true
}
Expand Down
21 changes: 21 additions & 0 deletions test/fixedbugs/issue41680.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// compile

// Copyright 2020 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package p

func F(s string) bool {
const m = 16
const n = 1e5
_ = make([]int, n)
return len(s) < n*m
}

func G() {
const n = 1e5
_ = make([]int, n)
f := n
var _ float64 = f
}

0 comments on commit ad0ab81

Please sign in to comment.