diff options
author | Brad Fitzpatrick <bradfitz@golang.org> | 2018-07-19 18:01:10 +0000 |
---|---|---|
committer | Brad Fitzpatrick <bradfitz@golang.org> | 2018-07-19 18:16:31 +0000 |
commit | 9092511cf795dd82713cd328403a106fc3e6870c (patch) | |
tree | 70b78f31efe95a875f84caa0c604a7159777f3f0 | |
parent | 95c3348344de688bbb9aba5474a612442e7d36ad (diff) | |
download | go-9092511cf795dd82713cd328403a106fc3e6870c.tar.gz go-9092511cf795dd82713cd328403a106fc3e6870c.zip |
net/http: update bundled http2
Updates http2 to x/net/http2 git rev a680a1efc54 for:
http2: reject large SETTINGS frames or those with duplicates
https://golang.org/cl/124735
Change-Id: I2168d1d1eef9c63b1a9c06b514b77fae16f920ed
Reviewed-on: https://go-review.googlesource.com/125036
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
-rw-r--r-- | src/net/http/h2_bundle.go | 69 |
1 files changed, 55 insertions, 14 deletions
diff --git a/src/net/http/h2_bundle.go b/src/net/http/h2_bundle.go index 7fc8937125..463254d96c 100644 --- a/src/net/http/h2_bundle.go +++ b/src/net/http/h2_bundle.go @@ -2044,32 +2044,67 @@ func (f *http2SettingsFrame) IsAck() bool { return f.http2FrameHeader.Flags.Has(http2FlagSettingsAck) } -func (f *http2SettingsFrame) Value(s http2SettingID) (v uint32, ok bool) { +func (f *http2SettingsFrame) Value(id http2SettingID) (v uint32, ok bool) { f.checkValid() - buf := f.p - for len(buf) > 0 { - settingID := http2SettingID(binary.BigEndian.Uint16(buf[:2])) - if settingID == s { - return binary.BigEndian.Uint32(buf[2:6]), true + for i := 0; i < f.NumSettings(); i++ { + if s := f.Setting(i); s.ID == id { + return s.Val, true } - buf = buf[6:] } return 0, false } +// Setting returns the setting from the frame at the given 0-based index. +// The index must be >= 0 and less than f.NumSettings(). +func (f *http2SettingsFrame) Setting(i int) http2Setting { + buf := f.p + return http2Setting{ + ID: http2SettingID(binary.BigEndian.Uint16(buf[i*6 : i*6+2])), + Val: binary.BigEndian.Uint32(buf[i*6+2 : i*6+6]), + } +} + +func (f *http2SettingsFrame) NumSettings() int { return len(f.p) / 6 } + +// HasDuplicates reports whether f contains any duplicate setting IDs. +func (f *http2SettingsFrame) HasDuplicates() bool { + num := f.NumSettings() + if num == 0 { + return false + } + // If it's small enough (the common case), just do the n^2 + // thing and avoid a map allocation. + if num < 10 { + for i := 0; i < num; i++ { + idi := f.Setting(i).ID + for j := i + 1; j < num; j++ { + idj := f.Setting(j).ID + if idi == idj { + return true + } + } + } + return false + } + seen := map[http2SettingID]bool{} + for i := 0; i < num; i++ { + id := f.Setting(i).ID + if seen[id] { + return true + } + seen[id] = true + } + return false +} + // ForeachSetting runs fn for each setting. // It stops and returns the first error. func (f *http2SettingsFrame) ForeachSetting(fn func(http2Setting) error) error { f.checkValid() - buf := f.p - for len(buf) > 0 { - if err := fn(http2Setting{ - http2SettingID(binary.BigEndian.Uint16(buf[:2])), - binary.BigEndian.Uint32(buf[2:6]), - }); err != nil { + for i := 0; i < f.NumSettings(); i++ { + if err := fn(f.Setting(i)); err != nil { return err } - buf = buf[6:] } return nil } @@ -5241,6 +5276,12 @@ func (sc *http2serverConn) processSettings(f *http2SettingsFrame) error { } return nil } + if f.NumSettings() > 100 || f.HasDuplicates() { + // This isn't actually in the spec, but hang up on + // suspiciously large settings frames or those with + // duplicate entries. + return http2ConnectionError(http2ErrCodeProtocol) + } if err := f.ForeachSetting(sc.processSetting); err != nil { return err } |