Skip to content

Commit 769e917

Browse files
committed
Merge branch 'master' into pr/238
2 parents 5965a06 + b93acc2 commit 769e917

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

63 files changed

+4526
-1655
lines changed

context/context.go

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
// cancellation signals, and other request-scoped values across API boundaries
77
// and between processes.
88
// As of Go 1.7 this package is available in the standard library under the
9-
// name [context], and migrating to it can be done automatically with [go fix].
9+
// name [context].
1010
//
1111
// Incoming requests to a server should create a [Context], and outgoing
1212
// calls to servers should accept a Context. The chain of function
@@ -38,8 +38,6 @@
3838
//
3939
// See https://go.dev/blog/context for example code for a server that uses
4040
// Contexts.
41-
//
42-
// [go fix]: https://go.dev/cmd/go#hdr-Update_packages_to_use_new_APIs
4341
package context
4442

4543
import (
@@ -51,36 +49,37 @@ import (
5149
// API boundaries.
5250
//
5351
// Context's methods may be called by multiple goroutines simultaneously.
52+
//
53+
//go:fix inline
5454
type Context = context.Context
5555

5656
// Canceled is the error returned by [Context.Err] when the context is canceled
5757
// for some reason other than its deadline passing.
58+
//
59+
//go:fix inline
5860
var Canceled = context.Canceled
5961

6062
// DeadlineExceeded is the error returned by [Context.Err] when the context is canceled
6163
// due to its deadline passing.
64+
//
65+
//go:fix inline
6266
var DeadlineExceeded = context.DeadlineExceeded
6367

6468
// Background returns a non-nil, empty Context. It is never canceled, has no
6569
// values, and has no deadline. It is typically used by the main function,
6670
// initialization, and tests, and as the top-level Context for incoming
6771
// requests.
68-
func Background() Context {
69-
return background
70-
}
72+
//
73+
//go:fix inline
74+
func Background() Context { return context.Background() }
7175

7276
// TODO returns a non-nil, empty Context. Code should use context.TODO when
7377
// it's unclear which Context to use or it is not yet available (because the
7478
// surrounding function has not yet been extended to accept a Context
7579
// parameter).
76-
func TODO() Context {
77-
return todo
78-
}
79-
80-
var (
81-
background = context.Background()
82-
todo = context.TODO()
83-
)
80+
//
81+
//go:fix inline
82+
func TODO() Context { return context.TODO() }
8483

8584
// A CancelFunc tells an operation to abandon its work.
8685
// A CancelFunc does not wait for the work to stop.
@@ -95,6 +94,8 @@ type CancelFunc = context.CancelFunc
9594
//
9695
// Canceling this context releases resources associated with it, so code should
9796
// call cancel as soon as the operations running in this [Context] complete.
97+
//
98+
//go:fix inline
9899
func WithCancel(parent Context) (ctx Context, cancel CancelFunc) {
99100
return context.WithCancel(parent)
100101
}
@@ -108,6 +109,8 @@ func WithCancel(parent Context) (ctx Context, cancel CancelFunc) {
108109
//
109110
// Canceling this context releases resources associated with it, so code should
110111
// call cancel as soon as the operations running in this [Context] complete.
112+
//
113+
//go:fix inline
111114
func WithDeadline(parent Context, d time.Time) (Context, CancelFunc) {
112115
return context.WithDeadline(parent, d)
113116
}
@@ -122,6 +125,8 @@ func WithDeadline(parent Context, d time.Time) (Context, CancelFunc) {
122125
// defer cancel() // releases resources if slowOperation completes before timeout elapses
123126
// return slowOperation(ctx)
124127
// }
128+
//
129+
//go:fix inline
125130
func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) {
126131
return context.WithTimeout(parent, timeout)
127132
}
@@ -139,6 +144,8 @@ func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) {
139144
// interface{}, context keys often have concrete type
140145
// struct{}. Alternatively, exported context key variables' static
141146
// type should be a pointer or interface.
147+
//
148+
//go:fix inline
142149
func WithValue(parent Context, key, val interface{}) Context {
143150
return context.WithValue(parent, key, val)
144151
}

go.mod

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
module golang.org/x/net
22

3-
go 1.23.0
3+
go 1.24.0
44

55
require (
6-
golang.org/x/crypto v0.38.0
7-
golang.org/x/sys v0.33.0
8-
golang.org/x/term v0.32.0
9-
golang.org/x/text v0.25.0
6+
golang.org/x/crypto v0.43.0
7+
golang.org/x/sys v0.37.0
8+
golang.org/x/term v0.36.0
9+
golang.org/x/text v0.30.0
1010
)

go.sum

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8=
2-
golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw=
3-
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
4-
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
5-
golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg=
6-
golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ=
7-
golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4=
8-
golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA=
1+
golang.org/x/crypto v0.43.0 h1:dduJYIi3A3KOfdGOHX8AVZ/jGiyPa3IbBozJ5kNuE04=
2+
golang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0=
3+
golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ=
4+
golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
5+
golang.org/x/term v0.36.0 h1:zMPR+aF8gfksFprF/Nc/rd1wRS1EI6nDBGyWAvDzx2Q=
6+
golang.org/x/term v0.36.0/go.mod h1:Qu394IJq6V6dCBRgwqshf3mPF85AqzYEzofzRdZkWss=
7+
golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k=
8+
golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM=

html/escape.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,7 @@ func escape(w writer, s string) error {
299299
case '\r':
300300
esc = "
"
301301
default:
302-
panic("unrecognized escape character")
302+
panic("html: unrecognized escape character")
303303
}
304304
s = s[i+1:]
305305
if _, err := w.WriteString(esc); err != nil {

html/parse.go

Lines changed: 41 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ func (p *parser) indexOfElementInScope(s scope, matchTags ...a.Atom) int {
136136
return -1
137137
}
138138
default:
139-
panic("unreachable")
139+
panic(fmt.Sprintf("html: internal error: indexOfElementInScope unknown scope: %d", s))
140140
}
141141
}
142142
switch s {
@@ -179,7 +179,7 @@ func (p *parser) clearStackToContext(s scope) {
179179
return
180180
}
181181
default:
182-
panic("unreachable")
182+
panic(fmt.Sprintf("html: internal error: clearStackToContext unknown scope: %d", s))
183183
}
184184
}
185185
}
@@ -231,7 +231,14 @@ func (p *parser) addChild(n *Node) {
231231
}
232232

233233
if n.Type == ElementNode {
234-
p.oe = append(p.oe, n)
234+
p.insertOpenElement(n)
235+
}
236+
}
237+
238+
func (p *parser) insertOpenElement(n *Node) {
239+
p.oe = append(p.oe, n)
240+
if len(p.oe) > 512 {
241+
panic("html: open stack of elements exceeds 512 nodes")
235242
}
236243
}
237244

@@ -810,7 +817,7 @@ func afterHeadIM(p *parser) bool {
810817
p.im = inFramesetIM
811818
return true
812819
case a.Base, a.Basefont, a.Bgsound, a.Link, a.Meta, a.Noframes, a.Script, a.Style, a.Template, a.Title:
813-
p.oe = append(p.oe, p.head)
820+
p.insertOpenElement(p.head)
814821
defer p.oe.remove(p.head)
815822
return inHeadIM(p)
816823
case a.Head:
@@ -1678,7 +1685,7 @@ func inTableBodyIM(p *parser) bool {
16781685
return inTableIM(p)
16791686
}
16801687

1681-
// Section 12.2.6.4.14.
1688+
// Section 13.2.6.4.14.
16821689
func inRowIM(p *parser) bool {
16831690
switch p.tok.Type {
16841691
case StartTagToken:
@@ -1690,7 +1697,9 @@ func inRowIM(p *parser) bool {
16901697
p.im = inCellIM
16911698
return true
16921699
case a.Caption, a.Col, a.Colgroup, a.Tbody, a.Tfoot, a.Thead, a.Tr:
1693-
if p.popUntil(tableScope, a.Tr) {
1700+
if p.elementInScope(tableScope, a.Tr) {
1701+
p.clearStackToContext(tableRowScope)
1702+
p.oe.pop()
16941703
p.im = inTableBodyIM
16951704
return false
16961705
}
@@ -1700,22 +1709,28 @@ func inRowIM(p *parser) bool {
17001709
case EndTagToken:
17011710
switch p.tok.DataAtom {
17021711
case a.Tr:
1703-
if p.popUntil(tableScope, a.Tr) {
1712+
if p.elementInScope(tableScope, a.Tr) {
1713+
p.clearStackToContext(tableRowScope)
1714+
p.oe.pop()
17041715
p.im = inTableBodyIM
17051716
return true
17061717
}
17071718
// Ignore the token.
17081719
return true
17091720
case a.Table:
1710-
if p.popUntil(tableScope, a.Tr) {
1721+
if p.elementInScope(tableScope, a.Tr) {
1722+
p.clearStackToContext(tableRowScope)
1723+
p.oe.pop()
17111724
p.im = inTableBodyIM
17121725
return false
17131726
}
17141727
// Ignore the token.
17151728
return true
17161729
case a.Tbody, a.Tfoot, a.Thead:
1717-
if p.elementInScope(tableScope, p.tok.DataAtom) {
1718-
p.parseImpliedToken(EndTagToken, a.Tr, a.Tr.String())
1730+
if p.elementInScope(tableScope, p.tok.DataAtom) && p.elementInScope(tableScope, a.Tr) {
1731+
p.clearStackToContext(tableRowScope)
1732+
p.oe.pop()
1733+
p.im = inTableBodyIM
17191734
return false
17201735
}
17211736
// Ignore the token.
@@ -2222,16 +2237,20 @@ func parseForeignContent(p *parser) bool {
22222237
p.acknowledgeSelfClosingTag()
22232238
}
22242239
case EndTagToken:
2240+
if strings.EqualFold(p.oe[len(p.oe)-1].Data, p.tok.Data) {
2241+
p.oe = p.oe[:len(p.oe)-1]
2242+
return true
2243+
}
22252244
for i := len(p.oe) - 1; i >= 0; i-- {
2226-
if p.oe[i].Namespace == "" {
2227-
return p.im(p)
2228-
}
22292245
if strings.EqualFold(p.oe[i].Data, p.tok.Data) {
22302246
p.oe = p.oe[:i]
2247+
return true
2248+
}
2249+
if i > 0 && p.oe[i-1].Namespace == "" {
22312250
break
22322251
}
22332252
}
2234-
return true
2253+
return p.im(p)
22352254
default:
22362255
// Ignore the token.
22372256
}
@@ -2312,9 +2331,13 @@ func (p *parser) parseCurrentToken() {
23122331
}
23132332
}
23142333

2315-
func (p *parser) parse() error {
2334+
func (p *parser) parse() (err error) {
2335+
defer func() {
2336+
if panicErr := recover(); panicErr != nil {
2337+
err = fmt.Errorf("%s", panicErr)
2338+
}
2339+
}()
23162340
// Iterate until EOF. Any other error will cause an early return.
2317-
var err error
23182341
for err != io.EOF {
23192342
// CDATA sections are allowed only in foreign content.
23202343
n := p.oe.top()
@@ -2343,6 +2366,8 @@ func (p *parser) parse() error {
23432366
// <tag>s. Conversely, explicit <tag>s in r's data can be silently dropped,
23442367
// with no corresponding node in the resulting tree.
23452368
//
2369+
// Parse will reject HTML that is nested deeper than 512 elements.
2370+
//
23462371
// The input is assumed to be UTF-8 encoded.
23472372
func Parse(r io.Reader) (*Node, error) {
23482373
return ParseWithOptions(r)

html/parse_test.go

Lines changed: 57 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -251,31 +251,35 @@ func TestParser(t *testing.T) {
251251
t.Fatal(err)
252252
}
253253
for _, tf := range testFiles {
254-
f, err := os.Open(tf)
255-
if err != nil {
256-
t.Fatal(err)
257-
}
258-
defer f.Close()
259-
r := bufio.NewReader(f)
260-
261-
for i := 0; ; i++ {
262-
ta, err := readParseTest(r)
263-
if err == io.EOF {
264-
break
265-
}
254+
t.Run(tf, func(t *testing.T) {
255+
f, err := os.Open(tf)
266256
if err != nil {
267257
t.Fatal(err)
268258
}
269-
if parseTestBlacklist[ta.text] {
270-
continue
259+
defer f.Close()
260+
r := bufio.NewReader(f)
261+
262+
for i := 0; ; i++ {
263+
ta, err := readParseTest(r)
264+
if err == io.EOF {
265+
break
266+
}
267+
if err != nil {
268+
t.Fatal(err)
269+
}
270+
if parseTestBlacklist[ta.text] {
271+
continue
272+
}
273+
274+
t.Run(fmt.Sprint(i), func(t *testing.T) {
275+
err = testParseCase(ta.text, ta.want, ta.context, ParseOptionEnableScripting(ta.scripting))
276+
277+
if err != nil {
278+
t.Errorf("%s test #%d %q, %s", tf, i, ta.text, err)
279+
}
280+
})
271281
}
272-
273-
err = testParseCase(ta.text, ta.want, ta.context, ParseOptionEnableScripting(ta.scripting))
274-
275-
if err != nil {
276-
t.Errorf("%s test #%d %q, %s", tf, i, ta.text, err)
277-
}
278-
}
282+
})
279283
}
280284
}
281285
}
@@ -506,3 +510,35 @@ func BenchmarkParser(b *testing.B) {
506510
Parse(bytes.NewBuffer(buf))
507511
}
508512
}
513+
514+
func TestIssue70179(t *testing.T) {
515+
_, err := Parse(strings.NewReader("<table><tbody><svg><td><desc><select></select></tbody>"))
516+
if err != nil {
517+
t.Fatalf("unexpected failure: %v", err)
518+
}
519+
}
520+
521+
func TestDepthLimit(t *testing.T) {
522+
for _, tc := range []struct {
523+
name string
524+
input string
525+
succeed bool
526+
}{
527+
// Not we don't use 512 as the limit here, because the parser will
528+
// insert implied <html> and <body> tags, increasing the size of the
529+
// stack by two before we start parsing the <dl>.
530+
{"above depth limit", strings.Repeat("<dl>", 511), false},
531+
{"below depth limit", strings.Repeat("<dl>", 510), true},
532+
{"above depth limit, interspersed elements", strings.Repeat("<dl><img />", 511), false},
533+
{"closing tags", strings.Repeat("</dl>", 512), true},
534+
} {
535+
t.Run(tc.name, func(t *testing.T) {
536+
_, err := Parse(strings.NewReader(tc.input))
537+
if tc.succeed && err != nil {
538+
t.Errorf("unexpected error: %v", err)
539+
} else if !tc.succeed && err == nil {
540+
t.Errorf("unexpected success")
541+
}
542+
})
543+
}
544+
}

html/render.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ func render1(w writer, n *Node) error {
184184
return err
185185
}
186186

187-
// Add initial newline where there is danger of a newline beging ignored.
187+
// Add initial newline where there is danger of a newline being ignored.
188188
if c := n.FirstChild; c != nil && c.Type == TextNode && strings.HasPrefix(c.Data, "\n") {
189189
switch n.Data {
190190
case "pre", "listing", "textarea":

0 commit comments

Comments
 (0)