mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-10-28 16:36:04 +08:00
Catch range and elided-literal writes to protected fields
Range clauses can assign a protected field directly, and an elided
literal inside a []*T or map[K]*T composite initializes a fresh header
just like &T{...} does. Both bypassed the write check.
This commit is contained in:
1 parent
424618b8aa
commit
f4d9da17e9
3 files changed
+48
-1
No files matched your search
@@ -38,6 +38,7 @@ func (p *protectedFieldPass) run() (any, error) {
|
||||
for c := range in.Root().Preorder(
|
||||
(*ast.AssignStmt)(nil),
|
||||
(*ast.IncDecStmt)(nil),
|
||||
(*ast.RangeStmt)(nil),
|
||||
(*ast.UnaryExpr)(nil),
|
||||
(*ast.CompositeLit)(nil),
|
||||
(*ast.FuncType)(nil),
|
||||
@@ -50,6 +51,13 @@ func (p *protectedFieldPass) run() (any, error) {
|
||||
}
|
||||
case *ast.IncDecStmt:
|
||||
p.checkWrite(node.X, "write to")
|
||||
case *ast.RangeStmt:
|
||||
if node.Key != nil {
|
||||
p.checkWrite(node.Key, "write to")
|
||||
}
|
||||
if node.Value != nil {
|
||||
p.checkWrite(node.Value, "write to")
|
||||
}
|
||||
case *ast.UnaryExpr:
|
||||
if node.Op == token.AND {
|
||||
p.checkWrite(node.X, "address of")
|
||||
@@ -107,7 +115,12 @@ func (p *protectedFieldPass) checkWrite(expr ast.Expr, what string) {
|
||||
}
|
||||
|
||||
func (p *protectedFieldPass) checkLiteral(lit *ast.CompositeLit) {
|
||||
st, ok := p.pass.TypesInfo.TypeOf(lit).Underlying().(*types.Struct)
|
||||
typ := p.pass.TypesInfo.TypeOf(lit)
|
||||
// Elided literals in []*T or map[K]*T composites have type *T.
|
||||
if ptr, ok := typ.Underlying().(*types.Pointer); ok {
|
||||
typ = ptr.Elem()
|
||||
}
|
||||
st, ok := typ.Underlying().(*types.Struct)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -17,6 +17,14 @@ func writes(h *record.Header, s *record.Small, d *record.Defined) {
|
||||
h.Flags = 1
|
||||
_ = &h.Flags
|
||||
_ = h.Kind
|
||||
for _, h.Kind = range []record.Kind{record.KindLarge} {
|
||||
}
|
||||
for h.Kind = range record.Kind(2) {
|
||||
}
|
||||
var kinds []record.Kind
|
||||
for _, kind := range kinds {
|
||||
_ = kind
|
||||
}
|
||||
}
|
||||
|
||||
func literals() {
|
||||
@@ -25,6 +33,10 @@ func literals() {
|
||||
_ = &record.Header{Flags: 1}
|
||||
_ = &record.Small{}
|
||||
_ = &record.Alias{Kind: record.KindSmall}
|
||||
_ = []*record.Header{{Kind: record.KindLarge}}
|
||||
_ = []*record.Header{{record.KindLarge, 1}}
|
||||
_ = map[int]*record.Header{0: {Kind: record.KindLarge}}
|
||||
_ = []*record.Header{{Flags: 1}}
|
||||
}
|
||||
|
||||
func copies(h *record.Header, s *record.Small, hs []record.Header) {
|
||||
|
||||
@@ -29,6 +29,18 @@
|
||||
h.Flags = 1
|
||||
_ = &h.Flags
|
||||
_ = h.Kind
|
||||
for _, h.Kind = range []record.Kind{record.KindLarge} {
|
||||
~
|
||||
!!! protectedfield: write to protected field Kind
|
||||
}
|
||||
for h.Kind = range record.Kind(2) {
|
||||
~
|
||||
!!! protectedfield: write to protected field Kind
|
||||
}
|
||||
var kinds []record.Kind
|
||||
for _, kind := range kinds {
|
||||
_ = kind
|
||||
}
|
||||
}
|
||||
|
||||
func literals() {
|
||||
@@ -43,6 +55,16 @@
|
||||
_ = &record.Alias{Kind: record.KindSmall}
|
||||
~
|
||||
!!! protectedfield: write to protected field Kind
|
||||
_ = []*record.Header{{Kind: record.KindLarge}}
|
||||
~
|
||||
!!! protectedfield: write to protected field Kind
|
||||
_ = []*record.Header{{record.KindLarge, 1}}
|
||||
~
|
||||
!!! protectedfield: write to protected field Kind
|
||||
_ = map[int]*record.Header{0: {Kind: record.KindLarge}}
|
||||
~
|
||||
!!! protectedfield: write to protected field Kind
|
||||
_ = []*record.Header{{Flags: 1}}
|
||||
}
|
||||
|
||||
func copies(h *record.Header, s *record.Small, hs []record.Header) {
|
||||
|
||||
Reference in new issue
Block a user