1
0
mirror of https://github.com/golang/go synced 2024-09-24 07:10:12 -06:00

[dev.ssa] Merge remote-tracking branch 'origin/master' into mergebranch

Semi-regular merge of tip into dev.ssa.

Change-Id: I855817c4746237792a2dab6eaf471087a3646be4
This commit is contained in:
Keith Randall 2016-07-13 11:03:12 -07:00
commit efefd11725
175 changed files with 4591 additions and 901 deletions

20
AUTHORS
View File

@ -105,6 +105,7 @@ Audrey Lim <audreylh@gmail.com>
Augusto Roman <aroman@gmail.com>
Aulus Egnatius Varialus <varialus@gmail.com>
awaw fumin <awawfumin@gmail.com>
Ayanamist Yang <ayanamist@gmail.com>
Aymerick Jéhanne <aymerick@jehanne.org>
Ben Burkert <ben@benburkert.com>
Ben Olive <sionide21@gmail.com>
@ -147,6 +148,7 @@ Chris Jones <chris@cjones.org>
Chris Kastorff <encryptio@gmail.com>
Chris Lennert <calennert@gmail.com>
Chris McGee <sirnewton_01@yahoo.ca> <newton688@gmail.com>
Christian Couder <chriscool@tuxfamily.org>
Christian Himpel <chressie@googlemail.com>
Christine Hansmann <chhansmann@gmail.com>
Christoffer Buchholz <christoffer.buchholz@gmail.com>
@ -237,8 +239,10 @@ Eivind Uggedal <eivind@uggedal.com>
Elias Naur <elias.naur@gmail.com>
Emil Hessman <c.emil.hessman@gmail.com> <emil@hessman.se>
Emmanuel Odeke <emm.odeke@gmail.com> <odeke@ualberta.ca>
Empirical Interfaces Inc.
Eoghan Sherry <ejsherry@gmail.com>
Eric Clark <zerohp@gmail.com>
Eric Engestrom <eric@engestrom.ch>
Eric Lagergren <ericscottlagergren@gmail.com>
Eric Milliken <emilliken@gmail.com>
Eric Roshan-Eisner <eric.d.eisner@gmail.com>
@ -258,6 +262,7 @@ Fastly, Inc.
Fatih Arslan <fatih@arslan.io>
Fazlul Shahriar <fshahriar@gmail.com>
Felix Geisendörfer <haimuiba@gmail.com>
Filippo Valsorda <hi@filippo.io>
Firmansyah Adiputra <frm.adiputra@gmail.com>
Florian Uekermann <florian@uekermann-online.de>
Florian Weimer <fw@deneb.enyo.de>
@ -290,6 +295,8 @@ Guobiao Mei <meiguobiao@gmail.com>
Gustav Paul <gustav.paul@gmail.com>
Gustavo Niemeyer <gustavo@niemeyer.net>
Gwenael Treguier <gwenn.kahz@gmail.com>
Gyu-Ho Lee <gyuhox@gmail.com>
H. İbrahim Güngör <igungor@gmail.com>
Hajime Hoshi <hajimehoshi@gmail.com>
Hari haran <hariharan.uno@gmail.com>
Hariharan Srinath <srinathh@gmail.com>
@ -321,6 +328,7 @@ Intel Corporation
Irieda Noboru <irieda@gmail.com>
Isaac Wagner <ibw@isaacwagner.me>
Ivan Ukhov <ivan.ukhov@gmail.com>
Jacob Hoffman-Andrews <github@hoffman-andrews.com>
Jae Kwon <jae@tendermint.com>
Jakob Borg <jakob@nym.se>
Jakub Ryszard Czarnowicz <j.czarnowicz@gmail.com>
@ -342,6 +350,7 @@ Jan Newmarch <jan.newmarch@gmail.com>
Jan Ziak <0xe2.0x9a.0x9b@gmail.com>
Jani Monoses <jani.monoses@ubuntu.com>
Jaroslavas Počepko <jp@webmaster.ms>
Jason Barnett <jason.w.barnett@gmail.com>
Jason Del Ponte <delpontej@gmail.com>
Jason Travis <infomaniac7@gmail.com>
Jay Weisskopf <jay@jayschwa.net>
@ -359,6 +368,7 @@ Jingcheng Zhang <diogin@gmail.com>
Jingguo Yao <yaojingguo@gmail.com>
Jiong Du <londevil@gmail.com>
Joakim Sernbrant <serbaut@gmail.com>
Joe Farrell <joe2farrell@gmail.com>
Joe Harrison <joehazzers@gmail.com>
Joe Henke <joed.henke@gmail.com>
Joe Poirier <jdpoirier@gmail.com>
@ -392,6 +402,7 @@ Joshua Chase <jcjoshuachase@gmail.com>
Jostein Stuhaug <js@solidsystem.no>
JT Olds <jtolds@xnet5.com>
Jukka-Pekka Kekkonen <karatepekka@gmail.com>
Julian Kornberger <jk+github@digineo.de>
Julian Phillips <julian@quantumfyre.co.uk>
Julien Schmidt <google@julienschmidt.com>
Justin Nuß <nuss.justin@gmail.com>
@ -502,6 +513,7 @@ Michael Vetter <g.bluehut@gmail.com>
Michal Bohuslávek <mbohuslavek@gmail.com>
Michał Derkacz <ziutek@lnet.pl>
Miek Gieben <miek@miek.nl>
Miguel Mendez <stxmendez@gmail.com>
Mihai Borobocea <MihaiBorobocea@gmail.com>
Mikael Tillenius <mikti42@gmail.com>
Mike Andrews <mra@xoba.com>
@ -530,6 +542,7 @@ Netflix, Inc.
Nevins Bartolomeo <nevins.bartolomeo@gmail.com>
ngmoco, LLC
Niall Sheridan <nsheridan@gmail.com>
Nic Day <nic.day@me.com>
Nicholas Katsaros <nick@nickkatsaros.com>
Nicholas Presta <nick@nickpresta.ca> <nick1presta@gmail.com>
Nicholas Sullivan <nicholas.sullivan@gmail.com>
@ -575,6 +588,7 @@ Paul Rosania <paul.rosania@gmail.com>
Paul Sbarra <Sbarra.Paul@gmail.com>
Paul Smith <paulsmith@pobox.com> <paulsmith@gmail.com>
Paul van Brouwershaven <paul@vanbrouwershaven.com>
Paulo Casaretto <pcasaretto@gmail.com>
Pavel Paulau <pavel.paulau@gmail.com>
Pavel Zinovkin <pavel.zinovkin@gmail.com>
Pawel Knap <pawelknap88@gmail.com>
@ -591,6 +605,7 @@ Péter Szilágyi <peterke@gmail.com>
Peter Waldschmidt <peter@waldschmidt.com>
Peter Waller <peter.waller@gmail.com>
Peter Williams <pwil3058@gmail.com>
Philip Børgesen <philip.borgesen@gmail.com>
Philip Hofer <phofer@umich.edu>
Philip K. Warren <pkwarren@gmail.com>
Pierre Durand <pierredurand@gmail.com>
@ -599,6 +614,7 @@ Pieter Droogendijk <pieter@binky.org.uk>
Pietro Gagliardi <pietro10@mac.com>
Prashant Varanasi <prashant@prashantv.com>
Preetam Jinka <pj@preet.am>
Quan Tran <qeed.quan@gmail.com>
Quan Yong Zhai <qyzhai@gmail.com>
Quentin Perez <qperez@ocs.online.net>
Quoc-Viet Nguyen <afelion@gmail.com>
@ -644,6 +660,7 @@ Salmān Aljammāz <s@0x65.net>
Sam Hug <samuel.b.hug@gmail.com>
Sam Whited <sam@samwhited.com>
Sanjay Menakuru <balasanjay@gmail.com>
Sasha Sobol <sasha@scaledinference.com>
Scott Barron <scott.barron@github.com>
Scott Bell <scott@sctsm.com>
Scott Ferguson <scottwferg@gmail.com>
@ -654,6 +671,7 @@ Sergei Skorobogatov <skorobo@rambler.ru>
Sergey 'SnakE' Gromov <snake.scaly@gmail.com>
Sergio Luis O. B. Correia <sergio@correia.cc>
Seth Hoenig <seth.a.hoenig@gmail.com>
Seth Vargo <sethvargo@gmail.com>
Shahar Kohanim <skohanim@gmail.com>
Shane Hansen <shanemhansen@gmail.com>
Shaozhen Ding <dsz0111@gmail.com>
@ -663,6 +681,7 @@ Shinji Tanaka <shinji.tanaka@gmail.com>
Shivakumar GN <shivakumar.gn@gmail.com>
Silvan Jegen <s.jegen@gmail.com>
Simon Jefford <simon.jefford@gmail.com>
Simon Thulbourn <simon+github@thulbourn.com>
Simon Whitehead <chemnova@gmail.com>
Sokolov Yura <funny.falcon@gmail.com>
Spencer Nelson <s@spenczar.com>
@ -734,6 +753,7 @@ Wei Guangjing <vcc.163@gmail.com>
Willem van der Schyff <willemvds@gmail.com>
William Josephson <wjosephson@gmail.com>
William Orr <will@worrbase.com> <ay1244@gmail.com>
Wisdom Omuya <deafgoat@gmail.com>
Xia Bin <snyh@snyh.org>
Xing Xing <mikespook@gmail.com>
Xudong Zhang <felixmelon@gmail.com>

View File

@ -37,6 +37,7 @@ Aaron France <aaron.l.france@gmail.com>
Aaron Jacobs <jacobsa@google.com>
Aaron Kemp <kemp.aaron@gmail.com>
Aaron Torres <tcboox@gmail.com>
Aaron Zinman <aaron@azinman.com>
Abe Haskins <abeisgreat@abeisgreat.com>
Abhinav Gupta <abhinav.g90@gmail.com>
Adam Langley <agl@golang.org>
@ -141,6 +142,7 @@ Augusto Roman <aroman@gmail.com>
Aulus Egnatius Varialus <varialus@gmail.com>
Austin Clements <austin@google.com> <aclements@csail.mit.edu>
awaw fumin <awawfumin@gmail.com>
Ayanamist Yang <ayanamist@gmail.com>
Aymerick Jéhanne <aymerick@jehanne.org>
Balazs Lecz <leczb@google.com>
Ben Burkert <ben@benburkert.com>
@ -155,6 +157,7 @@ Benny Siegert <bsiegert@gmail.com>
Benoit Sigoure <tsunanet@gmail.com>
Berengar Lehr <Berengar.Lehr@gmx.de>
Bill Neubauer <wcn@golang.org> <wcn@google.com> <bill.neubauer@gmail.com>
Bill O'Farrell <billo@ca.ibm.com>
Bill Thiede <couchmoney@gmail.com>
Billie Harold Cleek <bhcleek@gmail.com>
Bjorn Tillenius <bjorn@tillenius.me>
@ -212,6 +215,7 @@ Chris Lennert <calennert@gmail.com>
Chris Manghane <cmang@golang.org>
Chris McGee <sirnewton_01@yahoo.ca> <newton688@gmail.com>
Chris Zou <chriszou@ca.ibm.com>
Christian Couder <chriscool@tuxfamily.org>
Christian Himpel <chressie@googlemail.com> <chressie@gmail.com>
Christine Hansmann <chhansmann@gmail.com>
Christoffer Buchholz <christoffer.buchholz@gmail.com>
@ -330,6 +334,7 @@ Emil Hessman <c.emil.hessman@gmail.com> <emil@hessman.se>
Emmanuel Odeke <emm.odeke@gmail.com> <odeke@ualberta.ca>
Eoghan Sherry <ejsherry@gmail.com>
Eric Clark <zerohp@gmail.com>
Eric Engestrom <eric@engestrom.ch>
Eric Garrido <ekg@google.com>
Eric Koleda <ekoleda+devrel@google.com>
Eric Lagergren <ericscottlagergren@gmail.com>
@ -356,6 +361,7 @@ Fatih Arslan <fatih@arslan.io>
Fazlul Shahriar <fshahriar@gmail.com>
Federico Simoncelli <fsimonce@redhat.com>
Felix Geisendörfer <haimuiba@gmail.com>
Filippo Valsorda <hi@filippo.io>
Firmansyah Adiputra <frm.adiputra@gmail.com>
Florian Uekermann <florian@uekermann-online.de> <f1@uekermann-online.de>
Florian Weimer <fw@deneb.enyo.de>
@ -397,6 +403,8 @@ Gustav Paul <gustav.paul@gmail.com>
Gustavo Franco <gustavorfranco@gmail.com>
Gustavo Niemeyer <gustavo@niemeyer.net> <n13m3y3r@gmail.com>
Gwenael Treguier <gwenn.kahz@gmail.com>
Gyu-Ho Lee <gyuhox@gmail.com>
H. İbrahim Güngör <igungor@gmail.com>
Hajime Hoshi <hajimehoshi@gmail.com>
Hallgrimur Gunnarsson <halg@google.com>
Han-Wen Nienhuys <hanwen@google.com>
@ -435,6 +443,7 @@ Ivan Ukhov <ivan.ukhov@gmail.com>
Jaana Burcu Dogan <jbd@google.com> <jbd@golang.org> <burcujdogan@gmail.com>
Jacob Baskin <jbaskin@google.com>
Jacob H. Haven <jacob@cloudflare.com>
Jacob Hoffman-Andrews <github@hoffman-andrews.com>
Jae Kwon <jae@tendermint.com>
Jakob Borg <jakob@nym.se>
Jakub Čajka <jcajka@redhat.com>
@ -465,6 +474,7 @@ Jan Newmarch <jan.newmarch@gmail.com>
Jan Ziak <0xe2.0x9a.0x9b@gmail.com>
Jani Monoses <jani.monoses@ubuntu.com> <jani.monoses@gmail.com>
Jaroslavas Počepko <jp@webmaster.ms>
Jason Barnett <jason.w.barnett@gmail.com>
Jason Del Ponte <delpontej@gmail.com>
Jason Hall <jasonhall@google.com>
Jason Travis <infomaniac7@gmail.com>
@ -489,6 +499,7 @@ Jingcheng Zhang <diogin@gmail.com>
Jingguo Yao <yaojingguo@gmail.com>
Jiong Du <londevil@gmail.com>
Joakim Sernbrant <serbaut@gmail.com>
Joe Farrell <joe2farrell@gmail.com>
Joe Harrison <joehazzers@gmail.com>
Joe Henke <joed.henke@gmail.com>
Joe Poirier <jdpoirier@gmail.com>
@ -539,6 +550,7 @@ JP Sugarbroad <jpsugar@google.com>
JT Olds <jtolds@xnet5.com>
Jukka-Pekka Kekkonen <karatepekka@gmail.com>
Julia Hansbrough <flowerhack@google.com>
Julian Kornberger <jk+github@digineo.de>
Julian Phillips <julian@quantumfyre.co.uk>
Julien Schmidt <google@julienschmidt.com>
Jungho Ahn <jhahn@google.com>
@ -548,6 +560,7 @@ Kai Backman <kaib@golang.org>
Kamal Aboul-Hosn <aboulhosn@google.com>
Kamil Kisiel <kamil@kamilkisiel.net> <kamil.kisiel@gmail.com>
Kang Hu <hukangustc@gmail.com>
Karan Dhiman <karandhi@ca.ibm.com>
Kato Kazuyoshi <kato.kazuyoshi@gmail.com>
Katrina Owen <katrina.owen@gmail.com>
Kay Zhu <kayzhu@google.com>
@ -575,6 +588,7 @@ Kim Shrier <kshrier@racktopsystems.com>
Kirklin McDonald <kirklin.mcdonald@gmail.com>
Klaus Post <klauspost@gmail.com>
Konstantin Shaposhnikov <k.shaposhnikov@gmail.com>
Kris Rousey <krousey@google.com>
Kristopher Watts <traetox@gmail.com>
Kun Li <likunarmstrong@gmail.com>
Kyle Consalus <consalus@gmail.com>
@ -686,6 +700,7 @@ Michał Derkacz <ziutek@lnet.pl>
Michalis Kargakis <michaliskargakis@gmail.com>
Michel Lespinasse <walken@google.com>
Miek Gieben <miek@miek.nl> <remigius.gieben@gmail.com>
Miguel Mendez <stxmendez@gmail.com>
Mihai Borobocea <MihaiBorobocea@gmail.com>
Mikael Tillenius <mikti42@gmail.com>
Mike Andrews <mra@xoba.com>
@ -716,6 +731,7 @@ Nathan(yinian) Hu <nathanhu@google.com>
Neelesh Chandola <neelesh.c98@gmail.com>
Nevins Bartolomeo <nevins.bartolomeo@gmail.com>
Niall Sheridan <nsheridan@gmail.com>
Nic Day <nic.day@me.com>
Nicholas Katsaros <nick@nickkatsaros.com>
Nicholas Presta <nick@nickpresta.ca> <nick1presta@gmail.com>
Nicholas Sullivan <nicholas.sullivan@gmail.com>
@ -769,6 +785,7 @@ Paul Sbarra <Sbarra.Paul@gmail.com>
Paul Smith <paulsmith@pobox.com> <paulsmith@gmail.com>
Paul van Brouwershaven <paul@vanbrouwershaven.com>
Paul Wankadia <junyer@google.com>
Paulo Casaretto <pcasaretto@gmail.com>
Pavel Paulau <pavel.paulau@gmail.com>
Pavel Zinovkin <pavel.zinovkin@gmail.com>
Pawel Knap <pawelknap88@gmail.com>
@ -793,6 +810,7 @@ Peter Waller <peter.waller@gmail.com>
Peter Weinberger <pjw@golang.org>
Peter Williams <pwil3058@gmail.com>
Phil Pennock <pdp@golang.org>
Philip Børgesen <philip.borgesen@gmail.com>
Philip Hofer <phofer@umich.edu>
Philip K. Warren <pkwarren@gmail.com>
Pierre Durand <pierredurand@gmail.com>
@ -801,6 +819,7 @@ Pieter Droogendijk <pieter@binky.org.uk>
Pietro Gagliardi <pietro10@mac.com>
Prashant Varanasi <prashant@prashantv.com>
Preetam Jinka <pj@preet.am>
Quan Tran <qeed.quan@gmail.com>
Quan Yong Zhai <qyzhai@gmail.com>
Quentin Perez <qperez@ocs.online.net>
Quentin Smith <quentin@golang.org>
@ -857,7 +876,9 @@ Ryan Lower <rpjlower@gmail.com>
Ryan Seys <ryan@ryanseys.com>
Ryan Slade <ryanslade@gmail.com>
S.Çağlar Onur <caglar@10ur.org>
Sai Cheemalapati <saicheems@google.com>
Salmān Aljammāz <s@0x65.net>
Sam Ding <samding@ca.ibm.com>
Sam Hug <samuel.b.hug@gmail.com>
Sam Thorogood <thorogood@google.com> <sam.thorogood@gmail.com>
Sam Whited <sam@samwhited.com>
@ -865,6 +886,7 @@ Sameer Ajmani <sameer@golang.org> <ajmani@gmail.com>
Sami Commerot <samic@google.com>
Sanjay Menakuru <balasanjay@gmail.com>
Sasha Lionheart <lionhearts@google.com>
Sasha Sobol <sasha@scaledinference.com>
Scott Barron <scott.barron@github.com>
Scott Bell <scott@sctsm.com>
Scott Ferguson <scottwferg@gmail.com>
@ -882,6 +904,7 @@ Sergey 'SnakE' Gromov <snake.scaly@gmail.com>
Sergey Arseev <sergey.arseev@intel.com>
Sergio Luis O. B. Correia <sergio@correia.cc>
Seth Hoenig <seth.a.hoenig@gmail.com>
Seth Vargo <sethvargo@gmail.com>
Shahar Kohanim <skohanim@gmail.com>
Shane Hansen <shanemhansen@gmail.com>
Shaozhen Ding <dsz0111@gmail.com>
@ -894,6 +917,7 @@ Shivakumar GN <shivakumar.gn@gmail.com>
Shun Fan <sfan@google.com>
Silvan Jegen <s.jegen@gmail.com>
Simon Jefford <simon.jefford@gmail.com>
Simon Thulbourn <simon+github@thulbourn.com>
Simon Whitehead <chemnova@gmail.com>
Sokolov Yura <funny.falcon@gmail.com>
Spencer Nelson <s@spenczar.com>
@ -957,6 +981,7 @@ Totoro W <tw19881113@gmail.com>
Travis Cline <travis.cline@gmail.com>
Trevor Strohman <trevor.strohman@gmail.com>
Trey Tacon <ttacon@gmail.com>
Tristan Amini <tamini01@ca.ibm.com>
Tudor Golubenco <tudor.g@gmail.com>
Tyler Bunnell <tylerbunnell@gmail.com>
Tyler Treat <ttreat31@gmail.com>
@ -986,6 +1011,7 @@ Willem van der Schyff <willemvds@gmail.com>
William Chan <willchan@chromium.org>
William Josephson <wjosephson@gmail.com>
William Orr <will@worrbase.com> <ay1244@gmail.com>
Wisdom Omuya <deafgoat@gmail.com>
Xia Bin <snyh@snyh.org>
Xing Xing <mikespook@gmail.com>
Xudong Zhang <felixmelon@gmail.com>
@ -999,6 +1025,8 @@ Yissakhar Z. Beck <yissakhar.beck@gmail.com>
Yo-An Lin <yoanlin93@gmail.com>
Yongjian Xu <i3dmaster@gmail.com>
Yoshiyuki Kanno <nekotaroh@gmail.com> <yoshiyuki.kanno@stoic.co.jp>
Yu Heng Zhang <annita.zhang@cn.ibm.com>
Yu Xuan Zhang <zyxsh@cn.ibm.com>
Yuki Yugui Sonoda <yugui@google.com>
Yusuke Kagiwada <block.rxckin.beats@gmail.com>
Yuusei Kuwana <kuwana@kumama.org>

View File

@ -329,3 +329,4 @@ pkg syscall (netbsd-arm-cgo), const SizeofIfData = 132
pkg syscall (netbsd-arm-cgo), type IfMsghdr struct, Pad_cgo_1 [4]uint8
pkg unicode, const Version = "6.3.0"
pkg unicode, const Version = "7.0.0"
pkg unicode, const Version = "8.0.0"

View File

@ -274,3 +274,12 @@ pkg syscall (linux-arm-cgo), type SysProcAttr struct, Unshareflags uintptr
pkg testing, method (*B) Run(string, func(*B)) bool
pkg testing, method (*T) Run(string, func(*T)) bool
pkg testing, type InternalExample struct, Unordered bool
pkg unicode, const Version = "9.0.0"
pkg unicode, var Adlam *RangeTable
pkg unicode, var Bhaiksuki *RangeTable
pkg unicode, var Marchen *RangeTable
pkg unicode, var Newa *RangeTable
pkg unicode, var Osage *RangeTable
pkg unicode, var Prepended_Concatenation_Mark *RangeTable
pkg unicode, var Sentence_Terminal *RangeTable
pkg unicode, var Tangut *RangeTable

View File

@ -2238,13 +2238,12 @@ if str, ok := value.(string); ok {
<h3 id="generality">Generality</h3>
<p>
If a type exists only to implement an interface
and has no exported methods beyond that interface,
there is no need to export the type itself.
Exporting just the interface makes it clear that
it's the behavior that matters, not the implementation,
and that other implementations with different properties
can mirror the behavior of the original type.
If a type exists only to implement an interface and will
never have exported methods beyond that interface, there is
no need to export the type itself.
Exporting just the interface makes it clear the value has no
interesting behavior beyond what is described in the
interface.
It also avoids the need to repeat the documentation
on every instance of a common method.
</p>
@ -3665,4 +3664,3 @@ var _ image.Color = Black
var _ image.Image = Black
</pre>
-->

View File

@ -288,6 +288,18 @@ To avoid confusion with the new <code>-tests</code> check, the old, unadvertised
<code>-test</code> option has been removed; it was equivalent to <code>-all</code> <code>-shadow</code>.
</p>
<p id="vet_lostcancel">
The <code>vet</code> command also has a new check,
<code>-lostcancel</code>, which detects failure to call the
cancelation function returned by the <code>WithCancel</code>,
<code>WithTimeout</code>, and <code>WithDeadline</code> functions in
Go 1.7's new <code>context</code> package (see <a
href='#context'>below</a>).
Failure to call the function prevents the new <code>Context</code>
from being reclaimed until its parent is cancelled.
(The background context is never cancelled.)
</p>
<h3 id="cmd_dist">Go tool dist</h3>
<p>
@ -770,6 +782,30 @@ package.
</dd>
</dl>
<dl id="math_rand"><dt><a href="/pkg/math/rand/">math/rand</a></dt>
<dd>
<p>
The
<a href="/pkg/math/rand/#Read"><code>Read</code></a> function and
<a href="/pkg/math/rand/#Rand"><code>Rand</code></a>'s
<a href="/pkg/math/rand/#Rand.Read"><code>Read</code></a> method
now produce a pseudo-random stream of bytes that is consistent and not
dependent on the size of the input buffer.
</p>
<p>
The documentation clarifies that
Rand's <a href="/pkg/math/rand/#Rand.Seed"><code>Seed</code></a>
and <a href="/pkg/math/rand/#Rand.Read"><code>Read</code></a> methods
are not safe to call concurrently, though the global
functions <a href="/pkg/math/rand/#Seed"><code>Seed</code></a>
and <a href="/pkg/math/rand/#Read"><code>Read</code></a> are (and have
always been) safe.
</p>
</dd>
</dl>
<dl id="mime_multipart"><dt><a href="/pkg/mime/multipart/">mime/multipart</a></dt>
<dd>
@ -855,6 +891,23 @@ so that <code>w.WriteHeader(5)</code> uses the HTTP response
status <code>005</code>, not just <code>5</code>.
</p>
<p>
The server implementation now correctly sends only one "Transfer-Encoding" header when "chunked"
is set explicitly, following <a href="https://tools.ietf.org/html/rfc7230#section-3.3.1">RFC 7230</a>.
</p>
<p>
The server implementation is now stricter about rejecting requests with invalid HTTP versions.
Invalid requests claiming to be HTTP/0.x are now rejected (HTTP/0.9 was never fully supported),
and plaintext HTTP/2 requests other than the "PRI * HTTP/2.0" upgrade request are now rejected as well.
The server continues to handle encrypted HTTP/2 requests.
</p>
<p>
In the server, a 200 status code is sent back by the timeout handler on an empty
response body, instead of sending back 0 as the status code.
</p>
<p>
In the client, the
<a href="/pkg/net/http/#Transport"><code>Transport</code></a> implementation passes the request context
@ -1026,7 +1079,7 @@ from URLs with empty query strings (like <code>/search?</code>).
<dd>
<p>
<a href="/pkg/os/#IsExists"><code>IsExists</code></a> now returns true for <code>syscall.ENOTEMPTY</code>,
<a href="/pkg/os/#IsExist"><code>IsExist</code></a> now returns true for <code>syscall.ENOTEMPTY</code>,
on systems where that error exists.
</p>
@ -1186,3 +1239,15 @@ system call before executing the new program.
</p>
</dd>
</dl>
<dl id="unicode"><dt><a href="/pkg/unicode/">unicode</a></dt>
<dd>
<p>
The <a href="/pkg/unicode/"><code>unicode</code></a> package and associated
support throughout the system has been upgraded from version 8.0 to
<a href="http://www.unicode.org/versions/Unicode9.0.0/">Unicode 9.0</a>.
</p>
</dd>
</dl>

View File

@ -33,7 +33,7 @@ compiler using the GCC back end, see
</p>
<p>
The Go compilers support six instruction sets.
The Go compilers support seven instruction sets.
There are important differences in the quality of the compilers for the different
architectures.
</p>
@ -43,15 +43,17 @@ architectures.
<code>amd64</code> (also known as <code>x86-64</code>)
</dt>
<dd>
A mature implementation. The compiler has an effective
optimizer (registerizer) and generates good code (although
<code>gccgo</code> can do noticeably better sometimes).
A mature implementation. New in 1.7 is its SSA-based back end
that generates compact, efficient code.
</dd>
<dt>
<code>386</code> (<code>x86</code> or <code>x86-32</code>)
</dt>
<dd>
Comparable to the <code>amd64</code> port.
Comparable to the <code>amd64</code> port, but does
not yet use the SSA-based back end. It has an effective
optimizer (registerizer) and generates good code (although
<code>gccgo</code> can do noticeably better sometimes).
</dd>
<dt>
<code>arm</code> (<code>ARM</code>)
@ -77,6 +79,12 @@ architectures.
<dd>
Supports Linux binaries. New in 1.6 and not as well exercised as other ports.
</dd>
<dt>
<code>s390x</code> (IBM System z)
</dt>
<dd>
Supports Linux binaries. New in 1.7 and not as well exercised as other ports.
</dd>
</dl>
<p>

View File

@ -1,4 +1,4 @@
#!/bin/sh
#!/bin/bash
# Copyright 2012 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.
@ -8,8 +8,8 @@
# Consult http://www.iana.org/time-zones for the latest versions.
# Versions to use.
CODE=2016d
DATA=2016d
CODE=2016f
DATA=2016f
set -e
rm -rf work

Binary file not shown.

View File

@ -0,0 +1,12 @@
// Copyright 2016 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 main
// void f(void *p, int x) {}
import "C"
func main() {
_ = C.f(1) // ERROR HERE
}

View File

@ -45,6 +45,7 @@ expect issue13129.go C.ushort
check issue13423.go
expect issue13635.go C.uchar C.schar C.ushort C.uint C.ulong C.longlong C.ulonglong C.complexfloat C.complexdouble
check issue13830.go
check issue16116.go
if ! go build issue14669.go; then
exit 1

View File

@ -597,13 +597,15 @@ func (p *Package) rewriteCalls(f *File) {
// rewriteCall rewrites one call to add pointer checks. We replace
// each pointer argument x with _cgoCheckPointer(x).(T).
func (p *Package) rewriteCall(f *File, call *Call, name *Name) {
// Avoid a crash if the number of arguments is
// less than the number of parameters.
// This will be caught when the generated file is compiled.
if len(call.Call.Args) < len(name.FuncType.Params) {
return
}
any := false
for i, param := range name.FuncType.Params {
if len(call.Call.Args) <= i {
// Avoid a crash; this will be caught when the
// generated file is compiled.
return
}
if p.needsPointerCheck(f, param.Go, call.Call.Args[i]) {
any = true
break

View File

@ -122,3 +122,38 @@ NextVar:
}
return out
}
// TestLineNumber checks to make sure the generated assembly has line numbers
// see issue #16214
func TestLineNumber(t *testing.T) {
testenv.MustHaveGoBuild(t)
dir, err := ioutil.TempDir("", "TestLineNumber")
if err != nil {
t.Fatalf("could not create directory: %v", err)
}
defer os.RemoveAll(dir)
src := filepath.Join(dir, "x.go")
err = ioutil.WriteFile(src, []byte(issue16214src), 0644)
if err != nil {
t.Fatalf("could not write file: %v", err)
}
cmd := exec.Command("go", "tool", "compile", "-S", "-o", filepath.Join(dir, "out.o"), src)
out, err := cmd.CombinedOutput()
if err != nil {
t.Fatalf("fail to run go tool compile: %v", err)
}
if strings.Contains(string(out), "unknown line number") {
t.Errorf("line number missing in assembly:\n%s", out)
}
}
var issue16214src = `
package main
func Mod32(x uint32) uint32 {
return x % 3 // frontend rewrites it as HMUL with 2863311531, the LITERAL node has Lineno 0
}
`

View File

@ -153,7 +153,13 @@ const debugFormat = false // default: false
// TODO(gri) disable and remove once there is only one export format again
const forceObjFileStability = true
const exportVersion = "v0"
// Supported export format versions.
// TODO(gri) Make this more systematic (issue #16244).
const (
exportVersion0 = "v0"
exportVersion1 = "v1"
exportVersion = exportVersion1
)
// exportInlined enables the export of inlined function bodies and related
// dependencies. The compiler should work w/o any loss of functionality with
@ -727,6 +733,14 @@ func (p *exporter) typ(t *Type) {
p.paramList(sig.Params(), inlineable)
p.paramList(sig.Results(), inlineable)
// for issue #16243
// We make this conditional for 1.7 to avoid consistency problems
// with installed packages compiled with an older version.
// TODO(gri) Clean up after 1.7 is out (issue #16244)
if exportVersion == exportVersion1 {
p.bool(m.Nointerface)
}
var f *Func
if inlineable {
f = mfn.Func

View File

@ -21,8 +21,9 @@ import (
// changes to bimport.go and bexport.go.
type importer struct {
in *bufio.Reader
buf []byte // reused for reading strings
in *bufio.Reader
buf []byte // reused for reading strings
version string
// object lists, in order of deserialization
strList []string
@ -67,8 +68,9 @@ func Import(in *bufio.Reader) {
// --- generic export data ---
if v := p.string(); v != exportVersion {
Fatalf("importer: unknown export data version: %s", v)
p.version = p.string()
if p.version != exportVersion0 && p.version != exportVersion1 {
Fatalf("importer: unknown export data version: %s", p.version)
}
// populate typList with predeclared "known" types
@ -239,14 +241,20 @@ func (p *importer) pkg() *Pkg {
Fatalf("importer: package path %q for pkg index %d", path, len(p.pkgList))
}
// see importimport (export.go)
pkg := importpkg
if path != "" {
pkg = mkpkg(path)
}
if pkg.Name == "" {
pkg.Name = name
numImport[name]++
} else if pkg.Name != name {
Fatalf("importer: conflicting package names %s and %s for path %q", pkg.Name, name, path)
Yyerror("importer: conflicting package names %s and %s for path %q", pkg.Name, name, path)
}
if incannedimport == 0 && myimportpath != "" && path == myimportpath {
Yyerror("import %q: package depends on %q (import cycle)", importpkg.Path, path)
errorexit()
}
p.pkgList = append(p.pkgList, pkg)
@ -426,10 +434,15 @@ func (p *importer) typ() *Type {
params := p.paramList()
result := p.paramList()
nointerface := false
if p.version == exportVersion1 {
nointerface = p.bool()
}
n := methodname1(newname(sym), recv[0].Right)
n.Type = functype(recv[0], params, result)
checkwidth(n.Type)
addmethod(sym, n.Type, tsym.Pkg, false, false)
addmethod(sym, n.Type, tsym.Pkg, false, nointerface)
p.funcList = append(p.funcList, n)
importlist = append(importlist, n)

View File

@ -3,7 +3,7 @@
package gc
const runtimeimport = "" +
"cn\x00\x03v0\x01\rruntime\x00\t\x11newobject\x00\x02\x17\"\vtyp·2\x00\x00" +
"cn\x00\x03v1\x01\rruntime\x00\t\x11newobject\x00\x02\x17\"\vtyp·2\x00\x00" +
"\x01\x17:\x00\t\x13panicindex\x00\x00\x00\t\x13panicslice\x00\x00\x00\t\x15pani" +
"cdivide\x00\x00\x00\t\x15throwreturn\x00\x00\x00\t\x11throwinit\x00\x00\x00" +
"\t\x11panicwrap\x00\x05 \x00 \x00 \x00\x00\t\rgopanic\x00\x01\x1b\x00\x00\x00\x00\t\x11go" +
@ -105,6 +105,6 @@ const runtimeimport = "" +
"\x01\x02\v\x00\x01\x00\n$$\n"
const unsafeimport = "" +
"cn\x00\x03v0\x01\vunsafe\x00\x05\r\rPointer\x00\x16\x00\t\x0fOffsetof\x00\x01" +
"cn\x00\x03v1\x01\vunsafe\x00\x05\r\rPointer\x00\x16\x00\t\x0fOffsetof\x00\x01" +
":\x00\x01\x16\x00\t\vSizeof\x00\x01:\x00\x01\x16\x00\t\rAlignof\x00\x01:\x00\x01\x16\x00\v\b\x00\v" +
"\x00\x01\x00\n$$\n"

View File

@ -166,7 +166,7 @@ func closurename(n *Node) *Sym {
prefix := ""
if n.Func.Outerfunc == nil {
// Global closure.
outer = "glob"
outer = "glob."
prefix = "func"
closurename_closgen++

View File

@ -1551,10 +1551,12 @@ func esccall(e *EscState, n *Node, up *Node) {
}
var src *Node
note := ""
i := 0
lls := ll.Slice()
for t, it := IterFields(fntype.Params()); i < len(lls); i++ {
src = lls[i]
note = t.Note
if t.Isddd && !n.Isddd {
// Introduce ODDDARG node to represent ... allocation.
src = Nod(ODDDARG, nil, nil)
@ -1566,7 +1568,7 @@ func esccall(e *EscState, n *Node, up *Node) {
}
if haspointers(t.Type) {
if escassignfromtag(e, t.Note, nE.Escretval, src) == EscNone && up.Op != ODEFER && up.Op != OPROC {
if escassignfromtag(e, note, nE.Escretval, src) == EscNone && up.Op != ODEFER && up.Op != OPROC {
a := src
for a.Op == OCONVNOP {
a = a.Left
@ -1596,14 +1598,24 @@ func esccall(e *EscState, n *Node, up *Node) {
// This occurs when function parameter type Isddd and n not Isddd
break
}
if note == uintptrEscapesTag {
escassignSinkNilWhy(e, src, src, "escaping uintptr")
}
t = it.Next()
}
// Store arguments into slice for ... arg.
for ; i < len(lls); i++ {
if Debug['m'] > 3 {
fmt.Printf("%v::esccall:: ... <- %v\n", linestr(lineno), Nconv(lls[i], FmtShort))
}
escassignNilWhy(e, src, lls[i], "arg to ...") // args to slice
if note == uintptrEscapesTag {
escassignSinkNilWhy(e, src, lls[i], "arg to uintptrescapes ...")
} else {
escassignNilWhy(e, src, lls[i], "arg to ...")
}
}
}
@ -1963,9 +1975,20 @@ recurse:
// lets us take the address below to get a *string.
var unsafeUintptrTag = "unsafe-uintptr"
// This special tag is applied to uintptr parameters of functions
// marked go:uintptrescapes.
const uintptrEscapesTag = "uintptr-escapes"
func esctag(e *EscState, func_ *Node) {
func_.Esc = EscFuncTagged
name := func(s *Sym, narg int) string {
if s != nil {
return s.Name
}
return fmt.Sprintf("arg#%d", narg)
}
// External functions are assumed unsafe,
// unless //go:noescape is given before the declaration.
if func_.Nbody.Len() == 0 {
@ -1988,13 +2011,7 @@ func esctag(e *EscState, func_ *Node) {
narg++
if t.Type.Etype == TUINTPTR {
if Debug['m'] != 0 {
var name string
if t.Sym != nil {
name = t.Sym.Name
} else {
name = fmt.Sprintf("arg#%d", narg)
}
Warnl(func_.Lineno, "%v assuming %v is unsafe uintptr", funcSym(func_), name)
Warnl(func_.Lineno, "%v assuming %v is unsafe uintptr", funcSym(func_), name(t.Sym, narg))
}
t.Note = unsafeUintptrTag
}
@ -2003,6 +2020,27 @@ func esctag(e *EscState, func_ *Node) {
return
}
if func_.Func.Pragma&UintptrEscapes != 0 {
narg := 0
for _, t := range func_.Type.Params().Fields().Slice() {
narg++
if t.Type.Etype == TUINTPTR {
if Debug['m'] != 0 {
Warnl(func_.Lineno, "%v marking %v as escaping uintptr", funcSym(func_), name(t.Sym, narg))
}
t.Note = uintptrEscapesTag
}
if t.Isddd && t.Type.Elem().Etype == TUINTPTR {
// final argument is ...uintptr.
if Debug['m'] != 0 {
Warnl(func_.Lineno, "%v marking %v as escaping ...uintptr", funcSym(func_), name(t.Sym, narg))
}
t.Note = uintptrEscapesTag
}
}
}
savefn := Curfn
Curfn = func_
@ -2015,7 +2053,9 @@ func esctag(e *EscState, func_ *Node) {
case EscNone, // not touched by escflood
EscReturn:
if haspointers(ln.Type) { // don't bother tagging for scalars
ln.Name.Param.Field.Note = mktag(int(ln.Esc))
if ln.Name.Param.Field.Note != uintptrEscapesTag {
ln.Name.Param.Field.Note = mktag(int(ln.Esc))
}
}
case EscHeap, // touched by escflood, moved to heap

View File

@ -479,6 +479,10 @@ func pkgtype(s *Sym) *Type {
return s.Def.Type
}
// numImport tracks how often a package with a given name is imported.
// It is used to provide a better error message (by using the package
// path to disambiguate) if a package that appears multiple times with
// the same name appears in an error message.
var numImport = make(map[string]int)
func importimport(s *Sym, path string) {

View File

@ -160,6 +160,14 @@ func moveToHeap(n *Node) {
if n.Class == PPARAM {
stackcopy.SetNotLiveAtEnd(true)
}
if n.Class == PPARAMOUT {
// Make sure the pointer to the heap copy is kept live throughout the function.
// The function could panic at any point, and then a defer could recover.
// Thus, we need the pointer to the heap copy always available so the
// post-deferreturn code can copy the return value back to the stack.
// See issue 16095.
heapaddr.setIsOutputParamHeapAddr(true)
}
n.Name.Param.Stackcopy = stackcopy
// Substitute the stackcopy into the function variable list so that

View File

@ -72,6 +72,7 @@ const (
Nowritebarrier // emit compiler error instead of write barrier
Nowritebarrierrec // error on write barrier in this or recursive callees
CgoUnsafeArgs // treat a pointer to one arg as a pointer to them all
UintptrEscapes // pointers converted to uintptr escape
)
type lexer struct {
@ -930,6 +931,19 @@ func (l *lexer) getlinepragma() rune {
l.pragma |= Nowritebarrierrec | Nowritebarrier // implies Nowritebarrier
case "go:cgo_unsafe_args":
l.pragma |= CgoUnsafeArgs
case "go:uintptrescapes":
// For the next function declared in the file
// any uintptr arguments may be pointer values
// converted to uintptr. This directive
// ensures that the referenced allocated
// object, if any, is retained and not moved
// until the call completes, even though from
// the types alone it would appear that the
// object is no longer needed during the
// call. The conversion to uintptr must appear
// in the argument list.
// Used in syscall/dll_windows.go.
l.pragma |= UintptrEscapes
}
return c
}

View File

@ -373,7 +373,7 @@ func ordercall(n *Node, order *Order) {
if t == nil {
break
}
if t.Note == unsafeUintptrTag {
if t.Note == unsafeUintptrTag || t.Note == uintptrEscapesTag {
xp := n.List.Addr(i)
for (*xp).Op == OCONVNOP && !(*xp).Type.IsPtr() {
xp = &(*xp).Left
@ -385,7 +385,11 @@ func ordercall(n *Node, order *Order) {
*xp = x
}
}
t = it.Next()
next := it.Next()
if next == nil && t.Isddd && t.Note == uintptrEscapesTag {
next = t
}
t = next
}
}
}

View File

@ -2006,7 +2006,8 @@ func (p *parser) hidden_fndcl() *Node {
ss.Type = functype(s2[0], s6, s8)
checkwidth(ss.Type)
addmethod(s4, ss.Type, p.structpkg, false, false)
addmethod(s4, ss.Type, p.structpkg, false, p.pragma&Nointerface != 0)
p.pragma = 0
funchdr(ss)
// inl.C's inlnode in on a dotmeth node expects to find the inlineable body as

View File

@ -1175,6 +1175,19 @@ func livenessepilogue(lv *Liveness) {
all := bvalloc(nvars)
ambig := bvalloc(localswords())
// Set ambig bit for the pointers to heap-allocated pparamout variables.
// These are implicitly read by post-deferreturn code and thus must be
// kept live throughout the function (if there is any defer that recovers).
if hasdefer {
for _, n := range lv.vars {
if n.IsOutputParamHeapAddr() {
n.Name.Needzero = true
xoffset := n.Xoffset + stkptrsize
onebitwalktype1(n.Type, &xoffset, ambig)
}
}
}
for _, bb := range lv.cfg {
// Compute avarinitany and avarinitall for entry to block.
// This duplicates information known during livenesssolve

View File

@ -75,7 +75,7 @@ func uncommonSize(t *Type) int { // Sizeof(runtime.uncommontype{})
if t.Sym == nil && len(methods(t)) == 0 {
return 0
}
return 4 + 2 + 2
return 4 + 2 + 2 + 4 + 4
}
func makefield(name string, t *Type) *Field {
@ -604,17 +604,19 @@ func dextratype(s *Sym, ot int, t *Type, dataAdd int) int {
ot = dgopkgpathOffLSym(Linksym(s), ot, typePkg(t))
dataAdd += 4 + 2 + 2
dataAdd += uncommonSize(t)
mcount := len(m)
if mcount != int(uint16(mcount)) {
Fatalf("too many methods on %s: %d", t, mcount)
}
if dataAdd != int(uint16(dataAdd)) {
if dataAdd != int(uint32(dataAdd)) {
Fatalf("methods are too far away on %s: %d", t, dataAdd)
}
ot = duint16(s, ot, uint16(mcount))
ot = duint16(s, ot, uint16(dataAdd))
ot = duint16(s, ot, 0)
ot = duint32(s, ot, uint32(dataAdd))
ot = duint32(s, ot, 0)
return ot
}
@ -797,6 +799,7 @@ func typeptrdata(t *Type) int64 {
const (
tflagUncommon = 1 << 0
tflagExtraStar = 1 << 1
tflagNamed = 1 << 2
)
var dcommontype_algarray *Sym
@ -818,14 +821,10 @@ func dcommontype(s *Sym, ot int, t *Type) int {
algsym = dalgsym(t)
}
var sptr *Sym
tptr := Ptrto(t)
if !t.IsPtr() && (t.Sym != nil || methods(tptr) != nil) {
sptr := dtypesym(tptr)
r := obj.Addrel(Linksym(s))
r.Off = 0
r.Siz = 0
r.Sym = sptr.Lsym
r.Type = obj.R_USETYPE
sptr = dtypesym(tptr)
}
gcsym, useGCProg, ptrdata := dgcsym(t)
@ -843,7 +842,7 @@ func dcommontype(s *Sym, ot int, t *Type) int {
// alg *typeAlg
// gcdata *byte
// str nameOff
// _ int32
// ptrToThis typeOff
// }
ot = duintptr(s, ot, uint64(t.Width))
ot = duintptr(s, ot, uint64(ptrdata))
@ -854,6 +853,9 @@ func dcommontype(s *Sym, ot int, t *Type) int {
if uncommonSize(t) != 0 {
tflag |= tflagUncommon
}
if t.Sym != nil && t.Sym.Name != "" {
tflag |= tflagNamed
}
exported := false
p := Tconv(t, FmtLeft|FmtUnsigned)
@ -907,8 +909,12 @@ func dcommontype(s *Sym, ot int, t *Type) int {
ot = dsymptr(s, ot, gcsym, 0) // gcdata
nsym := dname(p, "", nil, exported)
ot = dsymptrOffLSym(Linksym(s), ot, nsym, 0)
ot = duint32(s, ot, 0)
ot = dsymptrOffLSym(Linksym(s), ot, nsym, 0) // str
if sptr == nil {
ot = duint32(s, ot, 0)
} else {
ot = dsymptrOffLSym(Linksym(s), ot, Linksym(sptr), 0) // ptrToThis
}
return ot
}

View File

@ -389,6 +389,14 @@ func (s *state) endBlock() *ssa.Block {
// pushLine pushes a line number on the line number stack.
func (s *state) pushLine(line int32) {
if line == 0 {
// the frontend may emit node with line number missing,
// use the parent line number in this case.
line = s.peekLine()
if Debug['K'] != 0 {
Warn("buildssa: line 0")
}
}
s.line = append(s.line, line)
}
@ -1752,7 +1760,7 @@ func (s *state) expr(n *Node) *ssa.Value {
addop := ssa.OpAdd64F
subop := ssa.OpSub64F
pt := floatForComplex(n.Type) // Could be Float32 or Float64
wt := Types[TFLOAT64] // Compute in Float64 to minimize cancellation error
wt := Types[TFLOAT64] // Compute in Float64 to minimize cancelation error
areal := s.newValue1(ssa.OpComplexReal, pt, a)
breal := s.newValue1(ssa.OpComplexReal, pt, b)
@ -1790,7 +1798,7 @@ func (s *state) expr(n *Node) *ssa.Value {
subop := ssa.OpSub64F
divop := ssa.OpDiv64F
pt := floatForComplex(n.Type) // Could be Float32 or Float64
wt := Types[TFLOAT64] // Compute in Float64 to minimize cancellation error
wt := Types[TFLOAT64] // Compute in Float64 to minimize cancelation error
areal := s.newValue1(ssa.OpComplexReal, pt, a)
breal := s.newValue1(ssa.OpComplexReal, pt, b)

View File

@ -79,6 +79,7 @@ const (
hasBreak = 1 << iota
notLiveAtEnd
isClosureVar
isOutputParamHeapAddr
)
func (n *Node) HasBreak() bool {
@ -112,6 +113,17 @@ func (n *Node) setIsClosureVar(b bool) {
}
}
func (n *Node) IsOutputParamHeapAddr() bool {
return n.flags&isOutputParamHeapAddr != 0
}
func (n *Node) setIsOutputParamHeapAddr(b bool) {
if b {
n.flags |= isOutputParamHeapAddr
} else {
n.flags &^= isOutputParamHeapAddr
}
}
// Val returns the Val for the node.
func (n *Node) Val() Val {
if n.hasVal != +1 {

View File

@ -441,9 +441,8 @@ func gmove(f *gc.Node, t *gc.Node) {
gc.Regfree(&r3)
return
//warn("gmove: convert int to float not implemented: %N -> %N\n", f, t);
/*
* signed integer to float
* integer to float
*/
case gc.TINT32<<16 | gc.TFLOAT32,
gc.TINT32<<16 | gc.TFLOAT64,
@ -452,10 +451,42 @@ func gmove(f *gc.Node, t *gc.Node) {
gc.TINT16<<16 | gc.TFLOAT32,
gc.TINT16<<16 | gc.TFLOAT64,
gc.TINT8<<16 | gc.TFLOAT32,
gc.TINT8<<16 | gc.TFLOAT64:
gc.TINT8<<16 | gc.TFLOAT64,
gc.TUINT16<<16 | gc.TFLOAT32,
gc.TUINT16<<16 | gc.TFLOAT64,
gc.TUINT8<<16 | gc.TFLOAT32,
gc.TUINT8<<16 | gc.TFLOAT64,
gc.TUINT32<<16 | gc.TFLOAT32,
gc.TUINT32<<16 | gc.TFLOAT64,
gc.TUINT64<<16 | gc.TFLOAT32,
gc.TUINT64<<16 | gc.TFLOAT64:
bignodes()
// The algorithm is:
// if small enough, use native int64 -> float64 conversion,
// otherwise halve (x -> (x>>1)|(x&1)), convert, and double.
// Note: could use FCFIDU instead if target supports it.
var r1 gc.Node
gc.Regalloc(&r1, gc.Types[gc.TINT64], nil)
gmove(f, &r1)
if ft == gc.TUINT64 {
gc.Nodreg(&r2, gc.Types[gc.TUINT64], ppc64.REGTMP)
gmove(&bigi, &r2)
gins(ppc64.ACMPU, &r1, &r2)
p1 := gc.Gbranch(optoas(gc.OLT, gc.Types[gc.TUINT64]), nil, +1)
var r3 gc.Node
gc.Regalloc(&r3, gc.Types[gc.TUINT64], nil)
p2 := gins(ppc64.AANDCC, nil, &r3) // andi.
p2.Reg = r1.Reg
p2.From.Type = obj.TYPE_CONST
p2.From.Offset = 1
p3 := gins(ppc64.ASRD, nil, &r1)
p3.From.Type = obj.TYPE_CONST
p3.From.Offset = 1
gins(ppc64.AOR, &r3, &r1)
gc.Regfree(&r3)
gc.Patch(p1, gc.Pc)
}
gc.Regalloc(&r2, gc.Types[gc.TFLOAT64], t)
p1 := gins(ppc64.AMOVD, &r1, nil)
p1.To.Type = obj.TYPE_MEM
@ -467,36 +498,12 @@ func gmove(f *gc.Node, t *gc.Node) {
p1.From.Offset = -8
gins(ppc64.AFCFID, &r2, &r2)
gc.Regfree(&r1)
gmove(&r2, t)
gc.Regfree(&r2)
return
/*
* unsigned integer to float
*/
case gc.TUINT16<<16 | gc.TFLOAT32,
gc.TUINT16<<16 | gc.TFLOAT64,
gc.TUINT8<<16 | gc.TFLOAT32,
gc.TUINT8<<16 | gc.TFLOAT64,
gc.TUINT32<<16 | gc.TFLOAT32,
gc.TUINT32<<16 | gc.TFLOAT64,
gc.TUINT64<<16 | gc.TFLOAT32,
gc.TUINT64<<16 | gc.TFLOAT64:
var r1 gc.Node
gc.Regalloc(&r1, gc.Types[gc.TUINT64], nil)
gmove(f, &r1)
gc.Regalloc(&r2, gc.Types[gc.TFLOAT64], t)
p1 := gins(ppc64.AMOVD, &r1, nil)
p1.To.Type = obj.TYPE_MEM
p1.To.Reg = ppc64.REGSP
p1.To.Offset = -8
p1 = gins(ppc64.AFMOVD, nil, &r2)
p1.From.Type = obj.TYPE_MEM
p1.From.Reg = ppc64.REGSP
p1.From.Offset = -8
gins(ppc64.AFCFIDU, &r2, &r2)
gc.Regfree(&r1)
if ft == gc.TUINT64 {
p1 := gc.Gbranch(optoas(gc.OLT, gc.Types[gc.TUINT64]), nil, +1) // use CR0 here again
gc.Nodreg(&r1, gc.Types[gc.TFLOAT64], ppc64.FREGTWO)
gins(ppc64.AFMUL, &r1, &r2)
gc.Patch(p1, gc.Pc)
}
gmove(&r2, t)
gc.Regfree(&r2)
return

View File

@ -42,10 +42,21 @@ func mkzdefaultcc(dir, file string) {
// mkzcgo writes zosarch.go for cmd/go.
func mkzosarch(dir, file string) {
// sort for deterministic zosarch.go file
var list []string
for plat := range cgoEnabled {
list = append(list, plat)
}
sort.Strings(list)
var buf bytes.Buffer
buf.WriteString("// auto generated by go tool dist\n\n")
buf.WriteString("package main\n\n")
fmt.Fprintf(&buf, "var osArchSupportsCgo = %#v", cgoEnabled)
fmt.Fprintf(&buf, "var osArchSupportsCgo = map[string]bool{\n")
for _, plat := range list {
fmt.Fprintf(&buf, "\t%q: %v,\n", plat, cgoEnabled[plat])
}
fmt.Fprintf(&buf, "}\n")
writefile(buf.String(), file, writeSkipSame)
}

View File

@ -508,8 +508,7 @@
// searches for a branch or tag named "go1". If no such version exists it
// retrieves the most recent version of the package.
//
// Unless vendoring support is disabled (see 'go help gopath'),
// when go get checks out or updates a Git repository,
// When go get checks out or updates a Git repository,
// it also updates any git submodules referenced by the repository.
//
// Get never checks out or updates code stored in vendor directories.
@ -1271,10 +1270,9 @@
// let package authors make sure the custom import path is used and not a
// direct path to the underlying code hosting site.
//
// If vendoring is enabled (see 'go help gopath'), then import path checking is
// disabled for code found within vendor trees. This makes it possible to copy
// code into alternate locations in vendor trees without needing to update import
// comments.
// Import path checking is disabled for code found within vendor trees.
// This makes it possible to copy code into alternate locations in vendor trees
// without needing to update import comments.
//
// See https://golang.org/s/go14customimport for details.
//

View File

@ -673,11 +673,6 @@ func init() {
goarch = buildContext.GOARCH
goos = buildContext.GOOS
if _, ok := osArchSupportsCgo[goos+"/"+goarch]; !ok {
fmt.Fprintf(os.Stderr, "cmd/go: unsupported GOOS/GOARCH pair %s/%s\n", goos, goarch)
os.Exit(2)
}
if goos == "windows" {
exeSuffix = ".exe"
}
@ -1226,6 +1221,11 @@ func allArchiveActions(root *action) []*action {
// do runs the action graph rooted at root.
func (b *builder) do(root *action) {
if _, ok := osArchSupportsCgo[goos+"/"+goarch]; !ok && buildContext.Compiler == "gc" {
fmt.Fprintf(os.Stderr, "cmd/go: unsupported GOOS/GOARCH pair %s/%s\n", goos, goarch)
os.Exit(2)
}
// Build list of all actions, assigning depth-first post-order priority.
// The original implementation here was a true queue
// (using a channel) but it had the effect of getting

View File

@ -14,7 +14,6 @@ import (
"os/exec"
"path/filepath"
"regexp"
"runtime"
"strconv"
"strings"
)
@ -276,8 +275,8 @@ func isGoGenerate(buf []byte) bool {
// single go:generate command.
func (g *Generator) setEnv() {
g.env = []string{
"GOARCH=" + runtime.GOARCH,
"GOOS=" + runtime.GOOS,
"GOARCH=" + buildContext.GOARCH,
"GOOS=" + buildContext.GOOS,
"GOFILE=" + g.file,
"GOLINE=" + strconv.Itoa(g.lineNum),
"GOPACKAGE=" + g.pkg,

View File

@ -55,8 +55,7 @@ rule is that if the local installation is running version "go1", get
searches for a branch or tag named "go1". If no such version exists it
retrieves the most recent version of the package.
Unless vendoring support is disabled (see 'go help gopath'),
when go get checks out or updates a Git repository,
When go get checks out or updates a Git repository,
it also updates any git submodules referenced by the repository.
Get never checks out or updates code stored in vendor directories.

View File

@ -489,6 +489,16 @@ func (tg *testgoData) path(name string) string {
return filepath.Join(tg.tempdir, name)
}
// mustExist fails if path does not exist.
func (tg *testgoData) mustExist(path string) {
if _, err := os.Stat(path); err != nil {
if os.IsNotExist(err) {
tg.t.Fatalf("%s does not exist but should", path)
}
tg.t.Fatalf("%s stat failed: %v", path, err)
}
}
// mustNotExist fails if path exists.
func (tg *testgoData) mustNotExist(path string) {
if _, err := os.Stat(path); err == nil || !os.IsNotExist(err) {
@ -2920,3 +2930,27 @@ func TestAlwaysLinkSysoFiles(t *testing.T) {
tg.run("list", "-f", "{{.SysoFiles}}", "syso")
tg.grepStdout("a.syso", "missing syso file with CGO_ENABLED=0")
}
// Issue 16120.
func TestGenerateUsesBuildContext(t *testing.T) {
if runtime.GOOS == "windows" {
t.Skip("this test won't run under Windows")
}
tg := testgo(t)
defer tg.cleanup()
tg.parallel()
tg.tempDir("src/gen")
tg.tempFile("src/gen/gen.go", "package gen\n//go:generate echo $GOOS $GOARCH\n")
tg.setenv("GOPATH", tg.path("."))
tg.setenv("GOOS", "linux")
tg.setenv("GOARCH", "amd64")
tg.run("generate", "gen")
tg.grepStdout("linux amd64", "unexpected GOOS/GOARCH combination")
tg.setenv("GOOS", "darwin")
tg.setenv("GOARCH", "386")
tg.run("generate", "gen")
tg.grepStdout("darwin 386", "unexpected GOOS/GOARCH combination")
}

View File

@ -261,10 +261,9 @@ unless it is being referred to by that import path. In this way, import comments
let package authors make sure the custom import path is used and not a
direct path to the underlying code hosting site.
If vendoring is enabled (see 'go help gopath'), then import path checking is
disabled for code found within vendor trees. This makes it possible to copy
code into alternate locations in vendor trees without needing to update import
comments.
Import path checking is disabled for code found within vendor trees.
This makes it possible to copy code into alternate locations in vendor trees
without needing to update import comments.
See https://golang.org/s/go14customimport for details.
`,

View File

@ -383,9 +383,6 @@ func (v *vcsCmd) ping(scheme, repo string) error {
// The parent of dir must exist; dir must not.
func (v *vcsCmd) create(dir, repo string) error {
for _, cmd := range v.createCmd {
if strings.Contains(cmd, "submodule") {
continue
}
if err := v.run(".", cmd, "dir", dir, "repo", repo); err != nil {
return err
}
@ -396,9 +393,6 @@ func (v *vcsCmd) create(dir, repo string) error {
// download downloads any new changes for the repo in dir.
func (v *vcsCmd) download(dir string) error {
for _, cmd := range v.downloadCmd {
if strings.Contains(cmd, "submodule") {
continue
}
if err := v.run(dir, cmd); err != nil {
return err
}
@ -445,9 +439,6 @@ func (v *vcsCmd) tagSync(dir, tag string) error {
if tag == "" && v.tagSyncDefault != nil {
for _, cmd := range v.tagSyncDefault {
if strings.Contains(cmd, "submodule") {
continue
}
if err := v.run(dir, cmd); err != nil {
return err
}
@ -456,9 +447,6 @@ func (v *vcsCmd) tagSync(dir, tag string) error {
}
for _, cmd := range v.tagSyncCmd {
if strings.Contains(cmd, "submodule") {
continue
}
if err := v.run(dir, cmd, "tag", tag); err != nil {
return err
}
@ -870,7 +858,6 @@ var vcsPaths = []*vcsPath{
re: `^(?P<root>git\.openstack\.org/[A-Za-z0-9_.\-]+/[A-Za-z0-9_.\-]+)(\.git)?(/[A-Za-z0-9_.\-]+)*$`,
vcs: "git",
repo: "https://{root}",
check: noVCSSuffix,
},
// General syntax for any server.

View File

@ -197,6 +197,7 @@ func TestGetSubmodules(t *testing.T) {
tg.setenv("GOPATH", tg.path("."))
tg.run("get", "-d", "github.com/rsc/go-get-issue-12612")
tg.run("get", "-u", "-d", "github.com/rsc/go-get-issue-12612")
tg.mustExist(tg.path("src/github.com/rsc/go-get-issue-12612/vendor/golang.org/x/crypto/.git"))
}
func TestVendorCache(t *testing.T) {

View File

@ -55,7 +55,6 @@ func report(err error) {
func usage() {
fmt.Fprintf(os.Stderr, "usage: gofmt [flags] [path ...]\n")
flag.PrintDefaults()
os.Exit(2)
}
func initParserMode() {

View File

@ -61,7 +61,7 @@ func decode_inuxi(p []byte, sz int) uint64 {
func commonsize() int { return 4*SysArch.PtrSize + 8 + 8 } // runtime._type
func structfieldSize() int { return 3 * SysArch.PtrSize } // runtime.structfield
func uncommonSize() int { return 4 + 2 + 2 } // runtime.uncommontype
func uncommonSize() int { return 4 + 2 + 2 + 4 + 4 } // runtime.uncommontype
// Type.commonType.kind
func decodetype_kind(s *LSym) uint8 {
@ -362,7 +362,7 @@ func decodetype_methods(s *LSym) []methodsig {
}
mcount := int(decode_inuxi(s.P[off+4:], 2))
moff := int(decode_inuxi(s.P[off+4+2:], 2))
moff := int(decode_inuxi(s.P[off+4+2+2:], 4))
off += moff // offset to array of reflect.method values
const sizeofMethod = 4 * 4 // sizeof reflect.method in program
return decode_methodsig(s, off, sizeofMethod, mcount)

View File

@ -9,6 +9,7 @@ import (
"debug/gosym"
"flag"
"fmt"
"net/url"
"os"
"regexp"
"strings"
@ -50,7 +51,16 @@ func symbolize(mode, source string, p *profile.Profile, obj plugin.ObjTool, ui p
ui.PrintErr("expecting -symbolize=[local|remote|none][:force]")
fallthrough
case "", "force":
// Ignore these options, -force is recognized by symbolizer.Symbolize
// -force is recognized by symbolizer.Symbolize.
// If the source is remote, and the mapping file
// does not exist, don't use local symbolization.
if isRemote(source) {
if len(p.Mapping) == 0 {
local = false
} else if _, err := os.Stat(p.Mapping[0].File); err != nil {
local = false
}
}
}
}
@ -67,6 +77,21 @@ func symbolize(mode, source string, p *profile.Profile, obj plugin.ObjTool, ui p
return err
}
// isRemote returns whether source is a URL for a remote source.
func isRemote(source string) bool {
url, err := url.Parse(source)
if err != nil {
url, err = url.Parse("http://" + source)
if err != nil {
return false
}
}
if scheme := strings.ToLower(url.Scheme); scheme == "" || scheme == "file" {
return false
}
return true
}
// flags implements the driver.FlagPackage interface using the builtin flag package.
type flags struct {
}
@ -117,8 +142,10 @@ func (*objTool) Open(name string, start uint64) (plugin.ObjFile, error) {
name: name,
file: of,
}
if load, err := of.LoadAddress(); err == nil {
f.offset = start - load
if start != 0 {
if load, err := of.LoadAddress(); err == nil {
f.offset = start - load
}
}
return f, nil
}
@ -306,6 +333,11 @@ func (f *file) Symbols(r *regexp.Regexp, addr uint64) ([]*plugin.Sym, error) {
}
var out []*plugin.Sym
for _, s := range f.sym {
// Ignore a symbol with address 0 and size 0.
// An ELF STT_FILE symbol will look like that.
if s.Addr == 0 && s.Size == 0 {
continue
}
if (r == nil || r.MatchString(s.Name)) && (addr == 0 || s.Addr <= addr && addr < s.Addr+uint64(s.Size)) {
out = append(out, &plugin.Sym{
Name: []string{s.Name},

View File

@ -49,7 +49,11 @@ func GoSyntax(inst Inst, pc uint64, symname func(uint64) (string, uint64)) strin
op := inst.Op.String()
if plan9Suffix[inst.Op] {
switch inst.DataSize {
s := inst.DataSize
if inst.MemBytes != 0 {
s = inst.MemBytes * 8
}
switch s {
case 8:
op += "B"
case 16:

View File

@ -7,10 +7,10 @@
0100|11223344556677885f5f5f5f5f5f 64 intel add dword ptr [rax], eax
0100|11223344556677885f5f5f5f5f5f 64 plan9 ADDL AX, 0(AX)
0211|223344556677885f5f5f5f5f5f5f 32 intel add dl, byte ptr [ecx]
0211|223344556677885f5f5f5f5f5f5f 32 plan9 ADDL 0(CX), DL
0211|223344556677885f5f5f5f5f5f5f 32 plan9 ADDB 0(CX), DL
0211|223344556677885f5f5f5f5f5f5f 64 gnu add (%rcx),%dl
0211|223344556677885f5f5f5f5f5f5f 64 intel add dl, byte ptr [rcx]
0211|223344556677885f5f5f5f5f5f5f 64 plan9 ADDL 0(CX), DL
0211|223344556677885f5f5f5f5f5f5f 64 plan9 ADDB 0(CX), DL
0311|223344556677885f5f5f5f5f5f5f 32 intel add edx, dword ptr [ecx]
0311|223344556677885f5f5f5f5f5f5f 32 plan9 ADDL 0(CX), DX
0311|223344556677885f5f5f5f5f5f5f 64 gnu add (%rcx),%edx
@ -37,20 +37,20 @@
07|11223344556677885f5f5f5f5f5f5f 64 intel error: unrecognized instruction
07|11223344556677885f5f5f5f5f5f5f 64 plan9 error: unrecognized instruction
0811|223344556677885f5f5f5f5f5f5f 32 intel or byte ptr [ecx], dl
0811|223344556677885f5f5f5f5f5f5f 32 plan9 ORL DL, 0(CX)
0811|223344556677885f5f5f5f5f5f5f 32 plan9 ORB DL, 0(CX)
0811|223344556677885f5f5f5f5f5f5f 64 gnu or %dl,(%rcx)
0811|223344556677885f5f5f5f5f5f5f 64 intel or byte ptr [rcx], dl
0811|223344556677885f5f5f5f5f5f5f 64 plan9 ORL DL, 0(CX)
0811|223344556677885f5f5f5f5f5f5f 64 plan9 ORB DL, 0(CX)
0911|223344556677885f5f5f5f5f5f5f 32 intel or dword ptr [ecx], edx
0911|223344556677885f5f5f5f5f5f5f 32 plan9 ORL DX, 0(CX)
0911|223344556677885f5f5f5f5f5f5f 64 gnu or %edx,(%rcx)
0911|223344556677885f5f5f5f5f5f5f 64 intel or dword ptr [rcx], edx
0911|223344556677885f5f5f5f5f5f5f 64 plan9 ORL DX, 0(CX)
0a11|223344556677885f5f5f5f5f5f5f 32 intel or dl, byte ptr [ecx]
0a11|223344556677885f5f5f5f5f5f5f 32 plan9 ORL 0(CX), DL
0a11|223344556677885f5f5f5f5f5f5f 32 plan9 ORB 0(CX), DL
0a11|223344556677885f5f5f5f5f5f5f 64 gnu or (%rcx),%dl
0a11|223344556677885f5f5f5f5f5f5f 64 intel or dl, byte ptr [rcx]
0a11|223344556677885f5f5f5f5f5f5f 64 plan9 ORL 0(CX), DL
0a11|223344556677885f5f5f5f5f5f5f 64 plan9 ORB 0(CX), DL
0b11|223344556677885f5f5f5f5f5f5f 32 intel or edx, dword ptr [ecx]
0b11|223344556677885f5f5f5f5f5f5f 32 plan9 ORL 0(CX), DX
0b11|223344556677885f5f5f5f5f5f5f 64 gnu or (%rcx),%edx
@ -1479,10 +1479,10 @@
0faf11|223344556677885f5f5f5f5f5f 64 intel imul edx, dword ptr [rcx]
0faf11|223344556677885f5f5f5f5f5f 64 plan9 IMULL 0(CX), DX
0fb011|223344556677885f5f5f5f5f5f 32 intel cmpxchg byte ptr [ecx], dl
0fb011|223344556677885f5f5f5f5f5f 32 plan9 CMPXCHGL DL, 0(CX)
0fb011|223344556677885f5f5f5f5f5f 32 plan9 CMPXCHGB DL, 0(CX)
0fb011|223344556677885f5f5f5f5f5f 64 gnu cmpxchg %dl,(%rcx)
0fb011|223344556677885f5f5f5f5f5f 64 intel cmpxchg byte ptr [rcx], dl
0fb011|223344556677885f5f5f5f5f5f 64 plan9 CMPXCHGL DL, 0(CX)
0fb011|223344556677885f5f5f5f5f5f 64 plan9 CMPXCHGB DL, 0(CX)
0fb111|223344556677885f5f5f5f5f5f 32 intel cmpxchg dword ptr [ecx], edx
0fb111|223344556677885f5f5f5f5f5f 32 plan9 CMPXCHGL DX, 0(CX)
0fb111|223344556677885f5f5f5f5f5f 64 gnu cmpxchg %edx,(%rcx)
@ -1579,10 +1579,10 @@
0fbf11|223344556677885f5f5f5f5f5f 64 intel movsx edx, word ptr [rcx]
0fbf11|223344556677885f5f5f5f5f5f 64 plan9 MOVSX 0(CX), DX
0fc011|223344556677885f5f5f5f5f5f 32 intel xadd byte ptr [ecx], dl
0fc011|223344556677885f5f5f5f5f5f 32 plan9 XADDL DL, 0(CX)
0fc011|223344556677885f5f5f5f5f5f 32 plan9 XADDB DL, 0(CX)
0fc011|223344556677885f5f5f5f5f5f 64 gnu xadd %dl,(%rcx)
0fc011|223344556677885f5f5f5f5f5f 64 intel xadd byte ptr [rcx], dl
0fc011|223344556677885f5f5f5f5f5f 64 plan9 XADDL DL, 0(CX)
0fc011|223344556677885f5f5f5f5f5f 64 plan9 XADDB DL, 0(CX)
0fc111|223344556677885f5f5f5f5f5f 32 intel xadd dword ptr [ecx], edx
0fc111|223344556677885f5f5f5f5f5f 32 plan9 XADDL DX, 0(CX)
0fc111|223344556677885f5f5f5f5f5f 64 gnu xadd %edx,(%rcx)
@ -1899,20 +1899,20 @@
0ffe11|223344556677885f5f5f5f5f5f 64 intel paddd mmx2, qword ptr [rcx]
0ffe11|223344556677885f5f5f5f5f5f 64 plan9 PADDD 0(CX), M2
1011|223344556677885f5f5f5f5f5f5f 32 intel adc byte ptr [ecx], dl
1011|223344556677885f5f5f5f5f5f5f 32 plan9 ADCL DL, 0(CX)
1011|223344556677885f5f5f5f5f5f5f 32 plan9 ADCB DL, 0(CX)
1011|223344556677885f5f5f5f5f5f5f 64 gnu adc %dl,(%rcx)
1011|223344556677885f5f5f5f5f5f5f 64 intel adc byte ptr [rcx], dl
1011|223344556677885f5f5f5f5f5f5f 64 plan9 ADCL DL, 0(CX)
1011|223344556677885f5f5f5f5f5f5f 64 plan9 ADCB DL, 0(CX)
1111|223344556677885f5f5f5f5f5f5f 32 intel adc dword ptr [ecx], edx
1111|223344556677885f5f5f5f5f5f5f 32 plan9 ADCL DX, 0(CX)
1111|223344556677885f5f5f5f5f5f5f 64 gnu adc %edx,(%rcx)
1111|223344556677885f5f5f5f5f5f5f 64 intel adc dword ptr [rcx], edx
1111|223344556677885f5f5f5f5f5f5f 64 plan9 ADCL DX, 0(CX)
1211|223344556677885f5f5f5f5f5f5f 32 intel adc dl, byte ptr [ecx]
1211|223344556677885f5f5f5f5f5f5f 32 plan9 ADCL 0(CX), DL
1211|223344556677885f5f5f5f5f5f5f 32 plan9 ADCB 0(CX), DL
1211|223344556677885f5f5f5f5f5f5f 64 gnu adc (%rcx),%dl
1211|223344556677885f5f5f5f5f5f5f 64 intel adc dl, byte ptr [rcx]
1211|223344556677885f5f5f5f5f5f5f 64 plan9 ADCL 0(CX), DL
1211|223344556677885f5f5f5f5f5f5f 64 plan9 ADCB 0(CX), DL
1311|223344556677885f5f5f5f5f5f5f 32 intel adc edx, dword ptr [ecx]
1311|223344556677885f5f5f5f5f5f5f 32 plan9 ADCL 0(CX), DX
1311|223344556677885f5f5f5f5f5f5f 64 gnu adc (%rcx),%edx
@ -1939,20 +1939,20 @@
17|11223344556677885f5f5f5f5f5f5f 64 intel error: unrecognized instruction
17|11223344556677885f5f5f5f5f5f5f 64 plan9 error: unrecognized instruction
1811|223344556677885f5f5f5f5f5f5f 32 intel sbb byte ptr [ecx], dl
1811|223344556677885f5f5f5f5f5f5f 32 plan9 SBBL DL, 0(CX)
1811|223344556677885f5f5f5f5f5f5f 32 plan9 SBBB DL, 0(CX)
1811|223344556677885f5f5f5f5f5f5f 64 gnu sbb %dl,(%rcx)
1811|223344556677885f5f5f5f5f5f5f 64 intel sbb byte ptr [rcx], dl
1811|223344556677885f5f5f5f5f5f5f 64 plan9 SBBL DL, 0(CX)
1811|223344556677885f5f5f5f5f5f5f 64 plan9 SBBB DL, 0(CX)
1911|223344556677885f5f5f5f5f5f5f 32 intel sbb dword ptr [ecx], edx
1911|223344556677885f5f5f5f5f5f5f 32 plan9 SBBL DX, 0(CX)
1911|223344556677885f5f5f5f5f5f5f 64 gnu sbb %edx,(%rcx)
1911|223344556677885f5f5f5f5f5f5f 64 intel sbb dword ptr [rcx], edx
1911|223344556677885f5f5f5f5f5f5f 64 plan9 SBBL DX, 0(CX)
1a11|223344556677885f5f5f5f5f5f5f 32 intel sbb dl, byte ptr [ecx]
1a11|223344556677885f5f5f5f5f5f5f 32 plan9 SBBL 0(CX), DL
1a11|223344556677885f5f5f5f5f5f5f 32 plan9 SBBB 0(CX), DL
1a11|223344556677885f5f5f5f5f5f5f 64 gnu sbb (%rcx),%dl
1a11|223344556677885f5f5f5f5f5f5f 64 intel sbb dl, byte ptr [rcx]
1a11|223344556677885f5f5f5f5f5f5f 64 plan9 SBBL 0(CX), DL
1a11|223344556677885f5f5f5f5f5f5f 64 plan9 SBBB 0(CX), DL
1b11|223344556677885f5f5f5f5f5f5f 32 intel sbb edx, dword ptr [ecx]
1b11|223344556677885f5f5f5f5f5f5f 32 plan9 SBBL 0(CX), DX
1b11|223344556677885f5f5f5f5f5f5f 64 gnu sbb (%rcx),%edx
@ -1979,20 +1979,20 @@
1f|11223344556677885f5f5f5f5f5f5f 64 intel error: unrecognized instruction
1f|11223344556677885f5f5f5f5f5f5f 64 plan9 error: unrecognized instruction
2011|223344556677885f5f5f5f5f5f5f 32 intel and byte ptr [ecx], dl
2011|223344556677885f5f5f5f5f5f5f 32 plan9 ANDL DL, 0(CX)
2011|223344556677885f5f5f5f5f5f5f 32 plan9 ANDB DL, 0(CX)
2011|223344556677885f5f5f5f5f5f5f 64 gnu and %dl,(%rcx)
2011|223344556677885f5f5f5f5f5f5f 64 intel and byte ptr [rcx], dl
2011|223344556677885f5f5f5f5f5f5f 64 plan9 ANDL DL, 0(CX)
2011|223344556677885f5f5f5f5f5f5f 64 plan9 ANDB DL, 0(CX)
2111|223344556677885f5f5f5f5f5f5f 32 intel and dword ptr [ecx], edx
2111|223344556677885f5f5f5f5f5f5f 32 plan9 ANDL DX, 0(CX)
2111|223344556677885f5f5f5f5f5f5f 64 gnu and %edx,(%rcx)
2111|223344556677885f5f5f5f5f5f5f 64 intel and dword ptr [rcx], edx
2111|223344556677885f5f5f5f5f5f5f 64 plan9 ANDL DX, 0(CX)
2211|223344556677885f5f5f5f5f5f5f 32 intel and dl, byte ptr [ecx]
2211|223344556677885f5f5f5f5f5f5f 32 plan9 ANDL 0(CX), DL
2211|223344556677885f5f5f5f5f5f5f 32 plan9 ANDB 0(CX), DL
2211|223344556677885f5f5f5f5f5f5f 64 gnu and (%rcx),%dl
2211|223344556677885f5f5f5f5f5f5f 64 intel and dl, byte ptr [rcx]
2211|223344556677885f5f5f5f5f5f5f 64 plan9 ANDL 0(CX), DL
2211|223344556677885f5f5f5f5f5f5f 64 plan9 ANDB 0(CX), DL
2311|223344556677885f5f5f5f5f5f5f 32 intel and edx, dword ptr [ecx]
2311|223344556677885f5f5f5f5f5f5f 32 plan9 ANDL 0(CX), DX
2311|223344556677885f5f5f5f5f5f5f 64 gnu and (%rcx),%edx
@ -2020,9 +2020,9 @@
267011|223344556677885f5f5f5f5f5f 64 plan9 ES JO .+17
26a01122334455667788|5f5f5f5f5f5f 64 gnu mov %es:-0x778899aabbccddef,%al
26a01122334455667788|5f5f5f5f5f5f 64 intel mov al, byte ptr [0x8877665544332211]
26a01122334455667788|5f5f5f5f5f5f 64 plan9 ES MOVL -0x778899aabbccddef, AL
26a01122334455667788|5f5f5f5f5f5f 64 plan9 ES MOVB -0x778899aabbccddef, AL
26a011223344|556677885f5f5f5f5f5f 32 intel mov al, byte ptr es:[0x44332211]
26a011223344|556677885f5f5f5f5f5f 32 plan9 ES MOVL ES:0x44332211, AL
26a011223344|556677885f5f5f5f5f5f 32 plan9 ES MOVB ES:0x44332211, AL
26|8211223344556677885f5f5f5f5f5f 32 intel es
26|8211223344556677885f5f5f5f5f5f 32 plan9 ES Op(0)
26|8211223344556677885f5f5f5f5f5f 64 gnu es
@ -2034,20 +2034,20 @@
27|11223344556677885f5f5f5f5f5f5f 64 intel error: unrecognized instruction
27|11223344556677885f5f5f5f5f5f5f 64 plan9 error: unrecognized instruction
2811|223344556677885f5f5f5f5f5f5f 32 intel sub byte ptr [ecx], dl
2811|223344556677885f5f5f5f5f5f5f 32 plan9 SUBL DL, 0(CX)
2811|223344556677885f5f5f5f5f5f5f 32 plan9 SUBB DL, 0(CX)
2811|223344556677885f5f5f5f5f5f5f 64 gnu sub %dl,(%rcx)
2811|223344556677885f5f5f5f5f5f5f 64 intel sub byte ptr [rcx], dl
2811|223344556677885f5f5f5f5f5f5f 64 plan9 SUBL DL, 0(CX)
2811|223344556677885f5f5f5f5f5f5f 64 plan9 SUBB DL, 0(CX)
2911|223344556677885f5f5f5f5f5f5f 32 intel sub dword ptr [ecx], edx
2911|223344556677885f5f5f5f5f5f5f 32 plan9 SUBL DX, 0(CX)
2911|223344556677885f5f5f5f5f5f5f 64 gnu sub %edx,(%rcx)
2911|223344556677885f5f5f5f5f5f5f 64 intel sub dword ptr [rcx], edx
2911|223344556677885f5f5f5f5f5f5f 64 plan9 SUBL DX, 0(CX)
2a11|223344556677885f5f5f5f5f5f5f 32 intel sub dl, byte ptr [ecx]
2a11|223344556677885f5f5f5f5f5f5f 32 plan9 SUBL 0(CX), DL
2a11|223344556677885f5f5f5f5f5f5f 32 plan9 SUBB 0(CX), DL
2a11|223344556677885f5f5f5f5f5f5f 64 gnu sub (%rcx),%dl
2a11|223344556677885f5f5f5f5f5f5f 64 intel sub dl, byte ptr [rcx]
2a11|223344556677885f5f5f5f5f5f5f 64 plan9 SUBL 0(CX), DL
2a11|223344556677885f5f5f5f5f5f5f 64 plan9 SUBB 0(CX), DL
2b11|223344556677885f5f5f5f5f5f5f 32 intel sub edx, dword ptr [ecx]
2b11|223344556677885f5f5f5f5f5f5f 32 plan9 SUBL 0(CX), DX
2b11|223344556677885f5f5f5f5f5f5f 64 gnu sub (%rcx),%edx
@ -2069,20 +2069,20 @@
2f|11223344556677885f5f5f5f5f5f5f 64 intel error: unrecognized instruction
2f|11223344556677885f5f5f5f5f5f5f 64 plan9 error: unrecognized instruction
3011|223344556677885f5f5f5f5f5f5f 32 intel xor byte ptr [ecx], dl
3011|223344556677885f5f5f5f5f5f5f 32 plan9 XORL DL, 0(CX)
3011|223344556677885f5f5f5f5f5f5f 32 plan9 XORB DL, 0(CX)
3011|223344556677885f5f5f5f5f5f5f 64 gnu xor %dl,(%rcx)
3011|223344556677885f5f5f5f5f5f5f 64 intel xor byte ptr [rcx], dl
3011|223344556677885f5f5f5f5f5f5f 64 plan9 XORL DL, 0(CX)
3011|223344556677885f5f5f5f5f5f5f 64 plan9 XORB DL, 0(CX)
3111|223344556677885f5f5f5f5f5f5f 32 intel xor dword ptr [ecx], edx
3111|223344556677885f5f5f5f5f5f5f 32 plan9 XORL DX, 0(CX)
3111|223344556677885f5f5f5f5f5f5f 64 gnu xor %edx,(%rcx)
3111|223344556677885f5f5f5f5f5f5f 64 intel xor dword ptr [rcx], edx
3111|223344556677885f5f5f5f5f5f5f 64 plan9 XORL DX, 0(CX)
3211|223344556677885f5f5f5f5f5f5f 32 intel xor dl, byte ptr [ecx]
3211|223344556677885f5f5f5f5f5f5f 32 plan9 XORL 0(CX), DL
3211|223344556677885f5f5f5f5f5f5f 32 plan9 XORB 0(CX), DL
3211|223344556677885f5f5f5f5f5f5f 64 gnu xor (%rcx),%dl
3211|223344556677885f5f5f5f5f5f5f 64 intel xor dl, byte ptr [rcx]
3211|223344556677885f5f5f5f5f5f5f 64 plan9 XORL 0(CX), DL
3211|223344556677885f5f5f5f5f5f5f 64 plan9 XORB 0(CX), DL
3311|223344556677885f5f5f5f5f5f5f 32 intel xor edx, dword ptr [ecx]
3311|223344556677885f5f5f5f5f5f5f 32 plan9 XORL 0(CX), DX
3311|223344556677885f5f5f5f5f5f5f 64 gnu xor (%rcx),%edx
@ -2120,20 +2120,20 @@
37|11223344556677885f5f5f5f5f5f5f 64 intel error: unrecognized instruction
37|11223344556677885f5f5f5f5f5f5f 64 plan9 error: unrecognized instruction
3811|223344556677885f5f5f5f5f5f5f 32 intel cmp byte ptr [ecx], dl
3811|223344556677885f5f5f5f5f5f5f 32 plan9 CMPL DL, 0(CX)
3811|223344556677885f5f5f5f5f5f5f 32 plan9 CMPB DL, 0(CX)
3811|223344556677885f5f5f5f5f5f5f 64 gnu cmp %dl,(%rcx)
3811|223344556677885f5f5f5f5f5f5f 64 intel cmp byte ptr [rcx], dl
3811|223344556677885f5f5f5f5f5f5f 64 plan9 CMPL DL, 0(CX)
3811|223344556677885f5f5f5f5f5f5f 64 plan9 CMPB DL, 0(CX)
3911|223344556677885f5f5f5f5f5f5f 32 intel cmp dword ptr [ecx], edx
3911|223344556677885f5f5f5f5f5f5f 32 plan9 CMPL DX, 0(CX)
3911|223344556677885f5f5f5f5f5f5f 64 gnu cmp %edx,(%rcx)
3911|223344556677885f5f5f5f5f5f5f 64 intel cmp dword ptr [rcx], edx
3911|223344556677885f5f5f5f5f5f5f 64 plan9 CMPL DX, 0(CX)
3a11|223344556677885f5f5f5f5f5f5f 32 intel cmp dl, byte ptr [ecx]
3a11|223344556677885f5f5f5f5f5f5f 32 plan9 CMPL 0(CX), DL
3a11|223344556677885f5f5f5f5f5f5f 32 plan9 CMPB 0(CX), DL
3a11|223344556677885f5f5f5f5f5f5f 64 gnu cmp (%rcx),%dl
3a11|223344556677885f5f5f5f5f5f5f 64 intel cmp dl, byte ptr [rcx]
3a11|223344556677885f5f5f5f5f5f5f 64 plan9 CMPL 0(CX), DL
3a11|223344556677885f5f5f5f5f5f5f 64 plan9 CMPB 0(CX), DL
3b11|223344556677885f5f5f5f5f5f5f 32 intel cmp edx, dword ptr [ecx]
3b11|223344556677885f5f5f5f5f5f5f 32 plan9 CMPL 0(CX), DX
3b11|223344556677885f5f5f5f5f5f5f 64 gnu cmp (%rcx),%edx
@ -2570,13 +2570,14 @@
488b11|223344556677885f5f5f5f5f5f 64 plan9 MOVQ 0(CX), DX
488c11|223344556677885f5f5f5f5f5f 64 gnu mov %ss,(%rcx)
488c11|223344556677885f5f5f5f5f5f 64 intel mov word ptr [rcx], ss
488c11|223344556677885f5f5f5f5f5f 64 plan9 MOVQ SS, 0(CX)
# MOVQ is probably more correct here (reads 16 bits of segment register, zero extends, writes 64 bits at CX)
488c11|223344556677885f5f5f5f5f5f 64 plan9 MOVW SS, 0(CX)
488d11|223344556677885f5f5f5f5f5f 64 gnu lea (%rcx),%rdx
488d11|223344556677885f5f5f5f5f5f 64 intel lea rdx, ptr [rcx]
488d11|223344556677885f5f5f5f5f5f 64 plan9 LEAQ 0(CX), DX
488e11|223344556677885f5f5f5f5f5f 64 gnu mov (%rcx),%ss
488e11|223344556677885f5f5f5f5f5f 64 intel mov ss, word ptr [rcx]
488e11|223344556677885f5f5f5f5f5f 64 plan9 MOVQ 0(CX), SS
488e11|223344556677885f5f5f5f5f5f 64 plan9 MOVW 0(CX), SS
488f00|11223344556677885f5f5f5f5f 64 gnu popq (%rax)
488f00|11223344556677885f5f5f5f5f 64 intel pop qword ptr [rax]
488f00|11223344556677885f5f5f5f5f 64 plan9 POPQ 0(AX)
@ -2597,13 +2598,13 @@
489d|11223344556677885f5f5f5f5f5f 64 plan9 POPFQ
48a01122334455667788|5f5f5f5f5f5f 64 gnu mov -0x778899aabbccddef,%al
48a01122334455667788|5f5f5f5f5f5f 64 intel mov al, byte ptr [0x8877665544332211]
48a01122334455667788|5f5f5f5f5f5f 64 plan9 MOVQ -0x778899aabbccddef, AL
48a01122334455667788|5f5f5f5f5f5f 64 plan9 MOVB -0x778899aabbccddef, AL
48a11122334455667788|5f5f5f5f5f5f 64 gnu mov -0x778899aabbccddef,%rax
48a11122334455667788|5f5f5f5f5f5f 64 intel mov rax, qword ptr [0x8877665544332211]
48a11122334455667788|5f5f5f5f5f5f 64 plan9 MOVQ -0x778899aabbccddef, AX
48a21122334455667788|5f5f5f5f5f5f 64 gnu mov %al,-0x778899aabbccddef
48a21122334455667788|5f5f5f5f5f5f 64 intel mov byte ptr [0x8877665544332211], al
48a21122334455667788|5f5f5f5f5f5f 64 plan9 MOVQ AL, -0x778899aabbccddef
48a21122334455667788|5f5f5f5f5f5f 64 plan9 MOVB AL, -0x778899aabbccddef
48a31122334455667788|5f5f5f5f5f5f 64 gnu mov %rax,-0x778899aabbccddef
48a31122334455667788|5f5f5f5f5f5f 64 intel mov qword ptr [0x8877665544332211], rax
48a31122334455667788|5f5f5f5f5f5f 64 plan9 MOVQ AX, -0x778899aabbccddef
@ -3873,10 +3874,10 @@
660fc21122|3344556677885f5f5f5f5f 64 intel cmppd xmm2, xmmword ptr [rcx], 0x22
660fc21122|3344556677885f5f5f5f5f 64 plan9 CMPPD $0x22, 0(CX), X2
660fc311|223344556677885f5f5f5f5f 32 intel movnti dword ptr [ecx], edx
660fc311|223344556677885f5f5f5f5f 32 plan9 MOVNTIW DX, 0(CX)
660fc311|223344556677885f5f5f5f5f 32 plan9 MOVNTIL DX, 0(CX)
660fc311|223344556677885f5f5f5f5f 64 gnu movnti %edx,(%rcx)
660fc311|223344556677885f5f5f5f5f 64 intel movnti dword ptr [rcx], edx
660fc311|223344556677885f5f5f5f5f 64 plan9 MOVNTIW DX, 0(CX)
660fc311|223344556677885f5f5f5f5f 64 plan9 MOVNTIL DX, 0(CX)
660fc41122|3344556677885f5f5f5f5f 32 intel pinsrw xmm2, word ptr [ecx], 0x22
660fc41122|3344556677885f5f5f5f5f 32 plan9 PINSRW $0x22, 0(CX), X2
660fc41122|3344556677885f5f5f5f5f 64 gnu pinsrw $0x22,(%rcx),%xmm2
@ -4665,35 +4666,36 @@
66ef|11223344556677885f5f5f5f5f5f 64 intel out dx, ax
66ef|11223344556677885f5f5f5f5f5f 64 plan9 OUTW AX, DX
66f20f2a11|223344556677885f5f5f5f 32 intel cvtsi2sd xmm2, dword ptr [ecx]
66f20f2a11|223344556677885f5f5f5f 32 plan9 REPNE CVTSI2SDW 0(CX), X2
66f20f2a11|223344556677885f5f5f5f 32 plan9 REPNE CVTSI2SDL 0(CX), X2
66f20f2a11|223344556677885f5f5f5f 64 gnu cvtsi2sdl (%rcx),%xmm2
66f20f2a11|223344556677885f5f5f5f 64 intel cvtsi2sd xmm2, dword ptr [rcx]
66f20f2a11|223344556677885f5f5f5f 64 plan9 REPNE CVTSI2SDW 0(CX), X2
66f20f2a11|223344556677885f5f5f5f 64 plan9 REPNE CVTSI2SDL 0(CX), X2
# the Q extension is the size of the source float64 in memory. The destination is L.
66f20f2c11|223344556677885f5f5f5f 32 intel cvttsd2si edx, qword ptr [ecx]
66f20f2c11|223344556677885f5f5f5f 32 plan9 REPNE CVTTSD2SIW 0(CX), DX
66f20f2c11|223344556677885f5f5f5f 32 plan9 REPNE CVTTSD2SIQ 0(CX), DX
66f20f2c11|223344556677885f5f5f5f 64 gnu cvttsd2si (%rcx),%dx
66f20f2c11|223344556677885f5f5f5f 64 intel cvttsd2si edx, qword ptr [rcx]
66f20f2c11|223344556677885f5f5f5f 64 plan9 REPNE CVTTSD2SIW 0(CX), DX
66f20f2c11|223344556677885f5f5f5f 64 plan9 REPNE CVTTSD2SIQ 0(CX), DX
66f20f2d11|223344556677885f5f5f5f 32 intel cvtsd2si edx, qword ptr [ecx]
66f20f2d11|223344556677885f5f5f5f 32 plan9 REPNE CVTSD2SIW 0(CX), DX
66f20f2d11|223344556677885f5f5f5f 32 plan9 REPNE CVTSD2SIQ 0(CX), DX
66f20f2d11|223344556677885f5f5f5f 64 gnu cvtsd2si (%rcx),%dx
66f20f2d11|223344556677885f5f5f5f 64 intel cvtsd2si edx, qword ptr [rcx]
66f20f2d11|223344556677885f5f5f5f 64 plan9 REPNE CVTSD2SIW 0(CX), DX
66f20f2d11|223344556677885f5f5f5f 64 plan9 REPNE CVTSD2SIQ 0(CX), DX
66f20f38f011|223344556677885f5f5f 32 intel crc32 edx, byte ptr [ecx]
66f20f38f011|223344556677885f5f5f 32 plan9 REPNE CRC32 0(CX), DX
66f20f38f011|223344556677885f5f5f 64 gnu crc32b (%rcx),%edx
66f20f38f011|223344556677885f5f5f 64 intel crc32 edx, byte ptr [rcx]
66f20f38f011|223344556677885f5f5f 64 plan9 REPNE CRC32 0(CX), DX
66f30f2c11|223344556677885f5f5f5f 32 intel cvttss2si edx, dword ptr [ecx]
66f30f2c11|223344556677885f5f5f5f 32 plan9 REP CVTTSS2SIW 0(CX), DX
66f30f2c11|223344556677885f5f5f5f 32 plan9 REP CVTTSS2SIL 0(CX), DX
66f30f2c11|223344556677885f5f5f5f 64 gnu cvttss2si (%rcx),%dx
66f30f2c11|223344556677885f5f5f5f 64 intel cvttss2si edx, dword ptr [rcx]
66f30f2c11|223344556677885f5f5f5f 64 plan9 REP CVTTSS2SIW 0(CX), DX
66f30f2c11|223344556677885f5f5f5f 64 plan9 REP CVTTSS2SIL 0(CX), DX
66f30f2d11|223344556677885f5f5f5f 32 intel cvtss2si edx, dword ptr [ecx]
66f30f2d11|223344556677885f5f5f5f 32 plan9 REP CVTSS2SIW 0(CX), DX
66f30f2d11|223344556677885f5f5f5f 32 plan9 REP CVTSS2SIL 0(CX), DX
66f30f2d11|223344556677885f5f5f5f 64 gnu cvtss2si (%rcx),%dx
66f30f2d11|223344556677885f5f5f5f 64 intel cvtss2si edx, dword ptr [rcx]
66f30f2d11|223344556677885f5f5f5f 64 plan9 REP CVTSS2SIW 0(CX), DX
66f30f2d11|223344556677885f5f5f5f 64 plan9 REP CVTSS2SIL 0(CX), DX
66f30fae11|223344556677885f5f5f5f 64 gnu wrfsbasel (%rcx)
66f30fae11|223344556677885f5f5f5f 64 intel wrfsbase dword ptr [rcx]
66f30fae11|223344556677885f5f5f5f 64 plan9 REP WRFSBASE 0(CX)
@ -4917,45 +4919,45 @@
7f11|223344556677885f5f5f5f5f5f5f 64 intel jnle .+0x11
7f11|223344556677885f5f5f5f5f5f5f 64 plan9 JG .+17
800011|223344556677885f5f5f5f5f5f 32 intel add byte ptr [eax], 0x11
800011|223344556677885f5f5f5f5f5f 32 plan9 ADDL $0x11, 0(AX)
800011|223344556677885f5f5f5f5f5f 32 plan9 ADDB $0x11, 0(AX)
800011|223344556677885f5f5f5f5f5f 64 gnu addb $0x11,(%rax)
800011|223344556677885f5f5f5f5f5f 64 intel add byte ptr [rax], 0x11
800011|223344556677885f5f5f5f5f5f 64 plan9 ADDL $0x11, 0(AX)
800011|223344556677885f5f5f5f5f5f 64 plan9 ADDB $0x11, 0(AX)
800811|223344556677885f5f5f5f5f5f 32 intel or byte ptr [eax], 0x11
800811|223344556677885f5f5f5f5f5f 32 plan9 ORL $0x11, 0(AX)
800811|223344556677885f5f5f5f5f5f 32 plan9 ORB $0x11, 0(AX)
800811|223344556677885f5f5f5f5f5f 64 gnu orb $0x11,(%rax)
800811|223344556677885f5f5f5f5f5f 64 intel or byte ptr [rax], 0x11
800811|223344556677885f5f5f5f5f5f 64 plan9 ORL $0x11, 0(AX)
800811|223344556677885f5f5f5f5f5f 64 plan9 ORB $0x11, 0(AX)
801122|3344556677885f5f5f5f5f5f5f 32 intel adc byte ptr [ecx], 0x22
801122|3344556677885f5f5f5f5f5f5f 32 plan9 ADCL $0x22, 0(CX)
801122|3344556677885f5f5f5f5f5f5f 32 plan9 ADCB $0x22, 0(CX)
801122|3344556677885f5f5f5f5f5f5f 64 gnu adcb $0x22,(%rcx)
801122|3344556677885f5f5f5f5f5f5f 64 intel adc byte ptr [rcx], 0x22
801122|3344556677885f5f5f5f5f5f5f 64 plan9 ADCL $0x22, 0(CX)
801122|3344556677885f5f5f5f5f5f5f 64 plan9 ADCB $0x22, 0(CX)
801811|223344556677885f5f5f5f5f5f 32 intel sbb byte ptr [eax], 0x11
801811|223344556677885f5f5f5f5f5f 32 plan9 SBBL $0x11, 0(AX)
801811|223344556677885f5f5f5f5f5f 32 plan9 SBBB $0x11, 0(AX)
801811|223344556677885f5f5f5f5f5f 64 gnu sbbb $0x11,(%rax)
801811|223344556677885f5f5f5f5f5f 64 intel sbb byte ptr [rax], 0x11
801811|223344556677885f5f5f5f5f5f 64 plan9 SBBL $0x11, 0(AX)
801811|223344556677885f5f5f5f5f5f 64 plan9 SBBB $0x11, 0(AX)
802011|223344556677885f5f5f5f5f5f 32 intel and byte ptr [eax], 0x11
802011|223344556677885f5f5f5f5f5f 32 plan9 ANDL $0x11, 0(AX)
802011|223344556677885f5f5f5f5f5f 32 plan9 ANDB $0x11, 0(AX)
802011|223344556677885f5f5f5f5f5f 64 gnu andb $0x11,(%rax)
802011|223344556677885f5f5f5f5f5f 64 intel and byte ptr [rax], 0x11
802011|223344556677885f5f5f5f5f5f 64 plan9 ANDL $0x11, 0(AX)
802011|223344556677885f5f5f5f5f5f 64 plan9 ANDB $0x11, 0(AX)
802811|223344556677885f5f5f5f5f5f 32 intel sub byte ptr [eax], 0x11
802811|223344556677885f5f5f5f5f5f 32 plan9 SUBL $0x11, 0(AX)
802811|223344556677885f5f5f5f5f5f 32 plan9 SUBB $0x11, 0(AX)
802811|223344556677885f5f5f5f5f5f 64 gnu subb $0x11,(%rax)
802811|223344556677885f5f5f5f5f5f 64 intel sub byte ptr [rax], 0x11
802811|223344556677885f5f5f5f5f5f 64 plan9 SUBL $0x11, 0(AX)
802811|223344556677885f5f5f5f5f5f 64 plan9 SUBB $0x11, 0(AX)
803011|223344556677885f5f5f5f5f5f 32 intel xor byte ptr [eax], 0x11
803011|223344556677885f5f5f5f5f5f 32 plan9 XORL $0x11, 0(AX)
803011|223344556677885f5f5f5f5f5f 32 plan9 XORB $0x11, 0(AX)
803011|223344556677885f5f5f5f5f5f 64 gnu xorb $0x11,(%rax)
803011|223344556677885f5f5f5f5f5f 64 intel xor byte ptr [rax], 0x11
803011|223344556677885f5f5f5f5f5f 64 plan9 XORL $0x11, 0(AX)
803011|223344556677885f5f5f5f5f5f 64 plan9 XORB $0x11, 0(AX)
803811|223344556677885f5f5f5f5f5f 32 intel cmp byte ptr [eax], 0x11
803811|223344556677885f5f5f5f5f5f 32 plan9 CMPL $0x11, 0(AX)
803811|223344556677885f5f5f5f5f5f 32 plan9 CMPB $0x11, 0(AX)
803811|223344556677885f5f5f5f5f5f 64 gnu cmpb $0x11,(%rax)
803811|223344556677885f5f5f5f5f5f 64 intel cmp byte ptr [rax], 0x11
803811|223344556677885f5f5f5f5f5f 64 plan9 CMPL $0x11, 0(AX)
803811|223344556677885f5f5f5f5f5f 64 plan9 CMPB $0x11, 0(AX)
810011223344|556677885f5f5f5f5f5f 32 intel add dword ptr [eax], 0x44332211
810011223344|556677885f5f5f5f5f5f 32 plan9 ADDL $0x44332211, 0(AX)
810011223344|556677885f5f5f5f5f5f 64 gnu addl $0x44332211,(%rax)
@ -5037,65 +5039,65 @@
833811|223344556677885f5f5f5f5f5f 64 intel cmp dword ptr [rax], 0x11
833811|223344556677885f5f5f5f5f5f 64 plan9 CMPL $0x11, 0(AX)
8411|223344556677885f5f5f5f5f5f5f 32 intel test byte ptr [ecx], dl
8411|223344556677885f5f5f5f5f5f5f 32 plan9 TESTL DL, 0(CX)
8411|223344556677885f5f5f5f5f5f5f 32 plan9 TESTB DL, 0(CX)
8411|223344556677885f5f5f5f5f5f5f 64 gnu test %dl,(%rcx)
8411|223344556677885f5f5f5f5f5f5f 64 intel test byte ptr [rcx], dl
8411|223344556677885f5f5f5f5f5f5f 64 plan9 TESTL DL, 0(CX)
8411|223344556677885f5f5f5f5f5f5f 64 plan9 TESTB DL, 0(CX)
8511|223344556677885f5f5f5f5f5f5f 32 intel test dword ptr [ecx], edx
8511|223344556677885f5f5f5f5f5f5f 32 plan9 TESTL DX, 0(CX)
8511|223344556677885f5f5f5f5f5f5f 64 gnu test %edx,(%rcx)
8511|223344556677885f5f5f5f5f5f5f 64 intel test dword ptr [rcx], edx
8511|223344556677885f5f5f5f5f5f5f 64 plan9 TESTL DX, 0(CX)
8611|223344556677885f5f5f5f5f5f5f 32 intel xchg byte ptr [ecx], dl
8611|223344556677885f5f5f5f5f5f5f 32 plan9 XCHGL DL, 0(CX)
8611|223344556677885f5f5f5f5f5f5f 32 plan9 XCHGB DL, 0(CX)
8611|223344556677885f5f5f5f5f5f5f 64 gnu xchg %dl,(%rcx)
8611|223344556677885f5f5f5f5f5f5f 64 intel xchg byte ptr [rcx], dl
8611|223344556677885f5f5f5f5f5f5f 64 plan9 XCHGL DL, 0(CX)
8611|223344556677885f5f5f5f5f5f5f 64 plan9 XCHGB DL, 0(CX)
8711|223344556677885f5f5f5f5f5f5f 32 intel xchg dword ptr [ecx], edx
8711|223344556677885f5f5f5f5f5f5f 32 plan9 XCHGL DX, 0(CX)
8711|223344556677885f5f5f5f5f5f5f 64 gnu xchg %edx,(%rcx)
8711|223344556677885f5f5f5f5f5f5f 64 intel xchg dword ptr [rcx], edx
8711|223344556677885f5f5f5f5f5f5f 64 plan9 XCHGL DX, 0(CX)
8811|223344556677885f5f5f5f5f5f5f 32 intel mov byte ptr [ecx], dl
8811|223344556677885f5f5f5f5f5f5f 32 plan9 MOVL DL, 0(CX)
8811|223344556677885f5f5f5f5f5f5f 32 plan9 MOVB DL, 0(CX)
8811|223344556677885f5f5f5f5f5f5f 64 gnu mov %dl,(%rcx)
8811|223344556677885f5f5f5f5f5f5f 64 intel mov byte ptr [rcx], dl
8811|223344556677885f5f5f5f5f5f5f 64 plan9 MOVL DL, 0(CX)
8811|223344556677885f5f5f5f5f5f5f 64 plan9 MOVB DL, 0(CX)
8911|223344556677885f5f5f5f5f5f5f 32 intel mov dword ptr [ecx], edx
8911|223344556677885f5f5f5f5f5f5f 32 plan9 MOVL DX, 0(CX)
8911|223344556677885f5f5f5f5f5f5f 64 gnu mov %edx,(%rcx)
8911|223344556677885f5f5f5f5f5f5f 64 intel mov dword ptr [rcx], edx
8911|223344556677885f5f5f5f5f5f5f 64 plan9 MOVL DX, 0(CX)
8a11|223344556677885f5f5f5f5f5f5f 32 intel mov dl, byte ptr [ecx]
8a11|223344556677885f5f5f5f5f5f5f 32 plan9 MOVL 0(CX), DL
8a11|223344556677885f5f5f5f5f5f5f 32 plan9 MOVB 0(CX), DL
8a11|223344556677885f5f5f5f5f5f5f 64 gnu mov (%rcx),%dl
8a11|223344556677885f5f5f5f5f5f5f 64 intel mov dl, byte ptr [rcx]
8a11|223344556677885f5f5f5f5f5f5f 64 plan9 MOVL 0(CX), DL
8a11|223344556677885f5f5f5f5f5f5f 64 plan9 MOVB 0(CX), DL
8b11|223344556677885f5f5f5f5f5f5f 32 intel mov edx, dword ptr [ecx]
8b11|223344556677885f5f5f5f5f5f5f 32 plan9 MOVL 0(CX), DX
8b11|223344556677885f5f5f5f5f5f5f 64 gnu mov (%rcx),%edx
8b11|223344556677885f5f5f5f5f5f5f 64 intel mov edx, dword ptr [rcx]
8b11|223344556677885f5f5f5f5f5f5f 64 plan9 MOVL 0(CX), DX
8c11|223344556677885f5f5f5f5f5f5f 32 intel mov word ptr [ecx], ss
8c11|223344556677885f5f5f5f5f5f5f 32 plan9 MOVL SS, 0(CX)
8c11|223344556677885f5f5f5f5f5f5f 32 plan9 MOVW SS, 0(CX)
8c11|223344556677885f5f5f5f5f5f5f 64 gnu mov %ss,(%rcx)
8c11|223344556677885f5f5f5f5f5f5f 64 intel mov word ptr [rcx], ss
8c11|223344556677885f5f5f5f5f5f5f 64 plan9 MOVL SS, 0(CX)
8c11|223344556677885f5f5f5f5f5f5f 64 plan9 MOVW SS, 0(CX)
8d11|223344556677885f5f5f5f5f5f5f 32 intel lea edx, ptr [ecx]
8d11|223344556677885f5f5f5f5f5f5f 32 plan9 LEAL 0(CX), DX
8d11|223344556677885f5f5f5f5f5f5f 64 gnu lea (%rcx),%edx
8d11|223344556677885f5f5f5f5f5f5f 64 intel lea edx, ptr [rcx]
8d11|223344556677885f5f5f5f5f5f5f 64 plan9 LEAL 0(CX), DX
8e11|223344556677885f5f5f5f5f5f5f 32 intel mov ss, word ptr [ecx]
8e11|223344556677885f5f5f5f5f5f5f 32 plan9 MOVL 0(CX), SS
8e11|223344556677885f5f5f5f5f5f5f 32 plan9 MOVW 0(CX), SS
8e11|223344556677885f5f5f5f5f5f5f 64 gnu mov (%rcx),%ss
8e11|223344556677885f5f5f5f5f5f5f 64 intel mov ss, word ptr [rcx]
8e11|223344556677885f5f5f5f5f5f5f 64 plan9 MOVL 0(CX), SS
8e11|223344556677885f5f5f5f5f5f5f 64 plan9 MOVW 0(CX), SS
8f00|11223344556677885f5f5f5f5f5f 32 intel pop dword ptr [eax]
8f00|11223344556677885f5f5f5f5f5f 32 plan9 POPL 0(AX)
8f00|11223344556677885f5f5f5f5f5f 64 gnu popq (%rax)
8f00|11223344556677885f5f5f5f5f5f 64 intel pop qword ptr [rax]
8f00|11223344556677885f5f5f5f5f5f 64 plan9 POPL 0(AX)
8f00|11223344556677885f5f5f5f5f5f 64 plan9 POPQ 0(AX)
91|11223344556677885f5f5f5f5f5f5f 32 intel xchg ecx, eax
91|11223344556677885f5f5f5f5f5f5f 32 plan9 XCHGL AX, CX
91|11223344556677885f5f5f5f5f5f5f 64 intel xchg ecx, eax
@ -5144,9 +5146,9 @@ a111223344|556677885f5f5f5f5f5f5f 32 intel mov eax, dword ptr [0x44332211]
a111223344|556677885f5f5f5f5f5f5f 32 plan9 MOVL 0x44332211, AX
a21122334455667788|5f5f5f5f5f5f5f 64 gnu mov %al,-0x778899aabbccddef
a21122334455667788|5f5f5f5f5f5f5f 64 intel mov byte ptr [0x8877665544332211], al
a21122334455667788|5f5f5f5f5f5f5f 64 plan9 MOVL AL, -0x778899aabbccddef
a21122334455667788|5f5f5f5f5f5f5f 64 plan9 MOVB AL, -0x778899aabbccddef
a211223344|556677885f5f5f5f5f5f5f 32 intel mov byte ptr [0x44332211], al
a211223344|556677885f5f5f5f5f5f5f 32 plan9 MOVL AL, 0x44332211
a211223344|556677885f5f5f5f5f5f5f 32 plan9 MOVB AL, 0x44332211
a31122334455667788|5f5f5f5f5f5f5f 64 gnu mov %eax,-0x778899aabbccddef
a31122334455667788|5f5f5f5f5f5f5f 64 intel mov dword ptr [0x8877665544332211], eax
a31122334455667788|5f5f5f5f5f5f5f 64 plan9 MOVL AX, -0x778899aabbccddef
@ -5223,40 +5225,40 @@ b811223344|556677885f5f5f5f5f5f5f 64 gnu mov $0x44332211,%eax
b811223344|556677885f5f5f5f5f5f5f 64 intel mov eax, 0x44332211
b811223344|556677885f5f5f5f5f5f5f 64 plan9 MOVL $0x44332211, AX
c00011|223344556677885f5f5f5f5f5f 32 intel rol byte ptr [eax], 0x11
c00011|223344556677885f5f5f5f5f5f 32 plan9 ROLL $0x11, 0(AX)
c00011|223344556677885f5f5f5f5f5f 32 plan9 ROLB $0x11, 0(AX)
c00011|223344556677885f5f5f5f5f5f 64 gnu rolb $0x11,(%rax)
c00011|223344556677885f5f5f5f5f5f 64 intel rol byte ptr [rax], 0x11
c00011|223344556677885f5f5f5f5f5f 64 plan9 ROLL $0x11, 0(AX)
c00011|223344556677885f5f5f5f5f5f 64 plan9 ROLB $0x11, 0(AX)
c00811|223344556677885f5f5f5f5f5f 32 intel ror byte ptr [eax], 0x11
c00811|223344556677885f5f5f5f5f5f 32 plan9 RORL $0x11, 0(AX)
c00811|223344556677885f5f5f5f5f5f 32 plan9 RORB $0x11, 0(AX)
c00811|223344556677885f5f5f5f5f5f 64 gnu rorb $0x11,(%rax)
c00811|223344556677885f5f5f5f5f5f 64 intel ror byte ptr [rax], 0x11
c00811|223344556677885f5f5f5f5f5f 64 plan9 RORL $0x11, 0(AX)
c00811|223344556677885f5f5f5f5f5f 64 plan9 RORB $0x11, 0(AX)
c01122|3344556677885f5f5f5f5f5f5f 32 intel rcl byte ptr [ecx], 0x22
c01122|3344556677885f5f5f5f5f5f5f 32 plan9 RCLL $0x22, 0(CX)
c01122|3344556677885f5f5f5f5f5f5f 32 plan9 RCLB $0x22, 0(CX)
c01122|3344556677885f5f5f5f5f5f5f 64 gnu rclb $0x22,(%rcx)
c01122|3344556677885f5f5f5f5f5f5f 64 intel rcl byte ptr [rcx], 0x22
c01122|3344556677885f5f5f5f5f5f5f 64 plan9 RCLL $0x22, 0(CX)
c01122|3344556677885f5f5f5f5f5f5f 64 plan9 RCLB $0x22, 0(CX)
c01811|223344556677885f5f5f5f5f5f 32 intel rcr byte ptr [eax], 0x11
c01811|223344556677885f5f5f5f5f5f 32 plan9 RCRL $0x11, 0(AX)
c01811|223344556677885f5f5f5f5f5f 32 plan9 RCRB $0x11, 0(AX)
c01811|223344556677885f5f5f5f5f5f 64 gnu rcrb $0x11,(%rax)
c01811|223344556677885f5f5f5f5f5f 64 intel rcr byte ptr [rax], 0x11
c01811|223344556677885f5f5f5f5f5f 64 plan9 RCRL $0x11, 0(AX)
c01811|223344556677885f5f5f5f5f5f 64 plan9 RCRB $0x11, 0(AX)
c02011|223344556677885f5f5f5f5f5f 32 intel shl byte ptr [eax], 0x11
c02011|223344556677885f5f5f5f5f5f 32 plan9 SHLL $0x11, 0(AX)
c02011|223344556677885f5f5f5f5f5f 32 plan9 SHLB $0x11, 0(AX)
c02011|223344556677885f5f5f5f5f5f 64 gnu shlb $0x11,(%rax)
c02011|223344556677885f5f5f5f5f5f 64 intel shl byte ptr [rax], 0x11
c02011|223344556677885f5f5f5f5f5f 64 plan9 SHLL $0x11, 0(AX)
c02011|223344556677885f5f5f5f5f5f 64 plan9 SHLB $0x11, 0(AX)
c02811|223344556677885f5f5f5f5f5f 32 intel shr byte ptr [eax], 0x11
c02811|223344556677885f5f5f5f5f5f 32 plan9 SHRL $0x11, 0(AX)
c02811|223344556677885f5f5f5f5f5f 32 plan9 SHRB $0x11, 0(AX)
c02811|223344556677885f5f5f5f5f5f 64 gnu shrb $0x11,(%rax)
c02811|223344556677885f5f5f5f5f5f 64 intel shr byte ptr [rax], 0x11
c02811|223344556677885f5f5f5f5f5f 64 plan9 SHRL $0x11, 0(AX)
c02811|223344556677885f5f5f5f5f5f 64 plan9 SHRB $0x11, 0(AX)
c03811|223344556677885f5f5f5f5f5f 32 intel sar byte ptr [eax], 0x11
c03811|223344556677885f5f5f5f5f5f 32 plan9 SARL $0x11, 0(AX)
c03811|223344556677885f5f5f5f5f5f 32 plan9 SARB $0x11, 0(AX)
c03811|223344556677885f5f5f5f5f5f 64 gnu sarb $0x11,(%rax)
c03811|223344556677885f5f5f5f5f5f 64 intel sar byte ptr [rax], 0x11
c03811|223344556677885f5f5f5f5f5f 64 plan9 SARL $0x11, 0(AX)
c03811|223344556677885f5f5f5f5f5f 64 plan9 SARB $0x11, 0(AX)
c10011|223344556677885f5f5f5f5f5f 32 intel rol dword ptr [eax], 0x11
c10011|223344556677885f5f5f5f5f5f 32 plan9 ROLL $0x11, 0(AX)
c10011|223344556677885f5f5f5f5f5f 64 gnu roll $0x11,(%rax)
@ -5302,10 +5304,10 @@ c411|223344556677885f5f5f5f5f5f5f 32 plan9 LES 0(CX), DX
c511|223344556677885f5f5f5f5f5f5f 32 intel lds edx, ptr [ecx]
c511|223344556677885f5f5f5f5f5f5f 32 plan9 LDS 0(CX), DX
c60011|223344556677885f5f5f5f5f5f 32 intel mov byte ptr [eax], 0x11
c60011|223344556677885f5f5f5f5f5f 32 plan9 MOVL $0x11, 0(AX)
c60011|223344556677885f5f5f5f5f5f 32 plan9 MOVB $0x11, 0(AX)
c60011|223344556677885f5f5f5f5f5f 64 gnu movb $0x11,(%rax)
c60011|223344556677885f5f5f5f5f5f 64 intel mov byte ptr [rax], 0x11
c60011|223344556677885f5f5f5f5f5f 64 plan9 MOVL $0x11, 0(AX)
c60011|223344556677885f5f5f5f5f5f 64 plan9 MOVB $0x11, 0(AX)
c6f811|223344556677885f5f5f5f5f5f 32 intel xabort 0x11
c6f811|223344556677885f5f5f5f5f5f 32 plan9 XABORT $0x11
c6f811|223344556677885f5f5f5f5f5f 64 gnu xabort $0x11
@ -5362,40 +5364,40 @@ cf|11223344556677885f5f5f5f5f5f5f 64 gnu iret
cf|11223344556677885f5f5f5f5f5f5f 64 intel iretd
cf|11223344556677885f5f5f5f5f5f5f 64 plan9 IRETD
d000|11223344556677885f5f5f5f5f5f 32 intel rol byte ptr [eax], 0x1
d000|11223344556677885f5f5f5f5f5f 32 plan9 ROLL $0x1, 0(AX)
d000|11223344556677885f5f5f5f5f5f 32 plan9 ROLB $0x1, 0(AX)
d000|11223344556677885f5f5f5f5f5f 64 gnu rolb (%rax)
d000|11223344556677885f5f5f5f5f5f 64 intel rol byte ptr [rax], 0x1
d000|11223344556677885f5f5f5f5f5f 64 plan9 ROLL $0x1, 0(AX)
d000|11223344556677885f5f5f5f5f5f 64 plan9 ROLB $0x1, 0(AX)
d008|11223344556677885f5f5f5f5f5f 32 intel ror byte ptr [eax], 0x1
d008|11223344556677885f5f5f5f5f5f 32 plan9 RORL $0x1, 0(AX)
d008|11223344556677885f5f5f5f5f5f 32 plan9 RORB $0x1, 0(AX)
d008|11223344556677885f5f5f5f5f5f 64 gnu rorb (%rax)
d008|11223344556677885f5f5f5f5f5f 64 intel ror byte ptr [rax], 0x1
d008|11223344556677885f5f5f5f5f5f 64 plan9 RORL $0x1, 0(AX)
d008|11223344556677885f5f5f5f5f5f 64 plan9 RORB $0x1, 0(AX)
d011|223344556677885f5f5f5f5f5f5f 32 intel rcl byte ptr [ecx], 0x1
d011|223344556677885f5f5f5f5f5f5f 32 plan9 RCLL $0x1, 0(CX)
d011|223344556677885f5f5f5f5f5f5f 32 plan9 RCLB $0x1, 0(CX)
d011|223344556677885f5f5f5f5f5f5f 64 gnu rclb (%rcx)
d011|223344556677885f5f5f5f5f5f5f 64 intel rcl byte ptr [rcx], 0x1
d011|223344556677885f5f5f5f5f5f5f 64 plan9 RCLL $0x1, 0(CX)
d011|223344556677885f5f5f5f5f5f5f 64 plan9 RCLB $0x1, 0(CX)
d018|11223344556677885f5f5f5f5f5f 32 intel rcr byte ptr [eax], 0x1
d018|11223344556677885f5f5f5f5f5f 32 plan9 RCRL $0x1, 0(AX)
d018|11223344556677885f5f5f5f5f5f 32 plan9 RCRB $0x1, 0(AX)
d018|11223344556677885f5f5f5f5f5f 64 gnu rcrb (%rax)
d018|11223344556677885f5f5f5f5f5f 64 intel rcr byte ptr [rax], 0x1
d018|11223344556677885f5f5f5f5f5f 64 plan9 RCRL $0x1, 0(AX)
d018|11223344556677885f5f5f5f5f5f 64 plan9 RCRB $0x1, 0(AX)
d020|11223344556677885f5f5f5f5f5f 32 intel shl byte ptr [eax], 0x1
d020|11223344556677885f5f5f5f5f5f 32 plan9 SHLL $0x1, 0(AX)
d020|11223344556677885f5f5f5f5f5f 32 plan9 SHLB $0x1, 0(AX)
d020|11223344556677885f5f5f5f5f5f 64 gnu shlb (%rax)
d020|11223344556677885f5f5f5f5f5f 64 intel shl byte ptr [rax], 0x1
d020|11223344556677885f5f5f5f5f5f 64 plan9 SHLL $0x1, 0(AX)
d020|11223344556677885f5f5f5f5f5f 64 plan9 SHLB $0x1, 0(AX)
d028|11223344556677885f5f5f5f5f5f 32 intel shr byte ptr [eax], 0x1
d028|11223344556677885f5f5f5f5f5f 32 plan9 SHRL $0x1, 0(AX)
d028|11223344556677885f5f5f5f5f5f 32 plan9 SHRB $0x1, 0(AX)
d028|11223344556677885f5f5f5f5f5f 64 gnu shrb (%rax)
d028|11223344556677885f5f5f5f5f5f 64 intel shr byte ptr [rax], 0x1
d028|11223344556677885f5f5f5f5f5f 64 plan9 SHRL $0x1, 0(AX)
d028|11223344556677885f5f5f5f5f5f 64 plan9 SHRB $0x1, 0(AX)
d038|11223344556677885f5f5f5f5f5f 32 intel sar byte ptr [eax], 0x1
d038|11223344556677885f5f5f5f5f5f 32 plan9 SARL $0x1, 0(AX)
d038|11223344556677885f5f5f5f5f5f 32 plan9 SARB $0x1, 0(AX)
d038|11223344556677885f5f5f5f5f5f 64 gnu sarb (%rax)
d038|11223344556677885f5f5f5f5f5f 64 intel sar byte ptr [rax], 0x1
d038|11223344556677885f5f5f5f5f5f 64 plan9 SARL $0x1, 0(AX)
d038|11223344556677885f5f5f5f5f5f 64 plan9 SARB $0x1, 0(AX)
d100|11223344556677885f5f5f5f5f5f 32 intel rol dword ptr [eax], 0x1
d100|11223344556677885f5f5f5f5f5f 32 plan9 ROLL $0x1, 0(AX)
d100|11223344556677885f5f5f5f5f5f 64 gnu roll (%rax)
@ -5432,40 +5434,40 @@ d138|11223344556677885f5f5f5f5f5f 64 gnu sarl (%rax)
d138|11223344556677885f5f5f5f5f5f 64 intel sar dword ptr [rax], 0x1
d138|11223344556677885f5f5f5f5f5f 64 plan9 SARL $0x1, 0(AX)
d200|11223344556677885f5f5f5f5f5f 32 intel rol byte ptr [eax], cl
d200|11223344556677885f5f5f5f5f5f 32 plan9 ROLL CL, 0(AX)
d200|11223344556677885f5f5f5f5f5f 32 plan9 ROLB CL, 0(AX)
d200|11223344556677885f5f5f5f5f5f 64 gnu rolb %cl,(%rax)
d200|11223344556677885f5f5f5f5f5f 64 intel rol byte ptr [rax], cl
d200|11223344556677885f5f5f5f5f5f 64 plan9 ROLL CL, 0(AX)
d200|11223344556677885f5f5f5f5f5f 64 plan9 ROLB CL, 0(AX)
d208|11223344556677885f5f5f5f5f5f 32 intel ror byte ptr [eax], cl
d208|11223344556677885f5f5f5f5f5f 32 plan9 RORL CL, 0(AX)
d208|11223344556677885f5f5f5f5f5f 32 plan9 RORB CL, 0(AX)
d208|11223344556677885f5f5f5f5f5f 64 gnu rorb %cl,(%rax)
d208|11223344556677885f5f5f5f5f5f 64 intel ror byte ptr [rax], cl
d208|11223344556677885f5f5f5f5f5f 64 plan9 RORL CL, 0(AX)
d208|11223344556677885f5f5f5f5f5f 64 plan9 RORB CL, 0(AX)
d211|223344556677885f5f5f5f5f5f5f 32 intel rcl byte ptr [ecx], cl
d211|223344556677885f5f5f5f5f5f5f 32 plan9 RCLL CL, 0(CX)
d211|223344556677885f5f5f5f5f5f5f 32 plan9 RCLB CL, 0(CX)
d211|223344556677885f5f5f5f5f5f5f 64 gnu rclb %cl,(%rcx)
d211|223344556677885f5f5f5f5f5f5f 64 intel rcl byte ptr [rcx], cl
d211|223344556677885f5f5f5f5f5f5f 64 plan9 RCLL CL, 0(CX)
d211|223344556677885f5f5f5f5f5f5f 64 plan9 RCLB CL, 0(CX)
d218|11223344556677885f5f5f5f5f5f 32 intel rcr byte ptr [eax], cl
d218|11223344556677885f5f5f5f5f5f 32 plan9 RCRL CL, 0(AX)
d218|11223344556677885f5f5f5f5f5f 32 plan9 RCRB CL, 0(AX)
d218|11223344556677885f5f5f5f5f5f 64 gnu rcrb %cl,(%rax)
d218|11223344556677885f5f5f5f5f5f 64 intel rcr byte ptr [rax], cl
d218|11223344556677885f5f5f5f5f5f 64 plan9 RCRL CL, 0(AX)
d218|11223344556677885f5f5f5f5f5f 64 plan9 RCRB CL, 0(AX)
d220|11223344556677885f5f5f5f5f5f 32 intel shl byte ptr [eax], cl
d220|11223344556677885f5f5f5f5f5f 32 plan9 SHLL CL, 0(AX)
d220|11223344556677885f5f5f5f5f5f 32 plan9 SHLB CL, 0(AX)
d220|11223344556677885f5f5f5f5f5f 64 gnu shlb %cl,(%rax)
d220|11223344556677885f5f5f5f5f5f 64 intel shl byte ptr [rax], cl
d220|11223344556677885f5f5f5f5f5f 64 plan9 SHLL CL, 0(AX)
d220|11223344556677885f5f5f5f5f5f 64 plan9 SHLB CL, 0(AX)
d228|11223344556677885f5f5f5f5f5f 32 intel shr byte ptr [eax], cl
d228|11223344556677885f5f5f5f5f5f 32 plan9 SHRL CL, 0(AX)
d228|11223344556677885f5f5f5f5f5f 32 plan9 SHRB CL, 0(AX)
d228|11223344556677885f5f5f5f5f5f 64 gnu shrb %cl,(%rax)
d228|11223344556677885f5f5f5f5f5f 64 intel shr byte ptr [rax], cl
d228|11223344556677885f5f5f5f5f5f 64 plan9 SHRL CL, 0(AX)
d228|11223344556677885f5f5f5f5f5f 64 plan9 SHRB CL, 0(AX)
d238|11223344556677885f5f5f5f5f5f 32 intel sar byte ptr [eax], cl
d238|11223344556677885f5f5f5f5f5f 32 plan9 SARL CL, 0(AX)
d238|11223344556677885f5f5f5f5f5f 32 plan9 SARB CL, 0(AX)
d238|11223344556677885f5f5f5f5f5f 64 gnu sarb %cl,(%rax)
d238|11223344556677885f5f5f5f5f5f 64 intel sar byte ptr [rax], cl
d238|11223344556677885f5f5f5f5f5f 64 plan9 SARL CL, 0(AX)
d238|11223344556677885f5f5f5f5f5f 64 plan9 SARB CL, 0(AX)
d300|11223344556677885f5f5f5f5f5f 32 intel rol dword ptr [eax], cl
d300|11223344556677885f5f5f5f5f5f 32 plan9 ROLL CL, 0(AX)
d300|11223344556677885f5f5f5f5f5f 64 gnu roll %cl,(%rax)
@ -6254,15 +6256,15 @@ f20f2a11|223344556677885f5f5f5f5f 64 gnu cvtsi2sdl (%rcx),%xmm2
f20f2a11|223344556677885f5f5f5f5f 64 intel cvtsi2sd xmm2, dword ptr [rcx]
f20f2a11|223344556677885f5f5f5f5f 64 plan9 REPNE CVTSI2SDL 0(CX), X2
f20f2c11|223344556677885f5f5f5f5f 32 intel cvttsd2si edx, qword ptr [ecx]
f20f2c11|223344556677885f5f5f5f5f 32 plan9 REPNE CVTTSD2SIL 0(CX), DX
f20f2c11|223344556677885f5f5f5f5f 32 plan9 REPNE CVTTSD2SIQ 0(CX), DX
f20f2c11|223344556677885f5f5f5f5f 64 gnu cvttsd2si (%rcx),%edx
f20f2c11|223344556677885f5f5f5f5f 64 intel cvttsd2si edx, qword ptr [rcx]
f20f2c11|223344556677885f5f5f5f5f 64 plan9 REPNE CVTTSD2SIL 0(CX), DX
f20f2c11|223344556677885f5f5f5f5f 64 plan9 REPNE CVTTSD2SIQ 0(CX), DX
f20f2d11|223344556677885f5f5f5f5f 32 intel cvtsd2si edx, qword ptr [ecx]
f20f2d11|223344556677885f5f5f5f5f 32 plan9 REPNE CVTSD2SIL 0(CX), DX
f20f2d11|223344556677885f5f5f5f5f 32 plan9 REPNE CVTSD2SIQ 0(CX), DX
f20f2d11|223344556677885f5f5f5f5f 64 gnu cvtsd2si (%rcx),%edx
f20f2d11|223344556677885f5f5f5f5f 64 intel cvtsd2si edx, qword ptr [rcx]
f20f2d11|223344556677885f5f5f5f5f 64 plan9 REPNE CVTSD2SIL 0(CX), DX
f20f2d11|223344556677885f5f5f5f5f 64 plan9 REPNE CVTSD2SIQ 0(CX), DX
f20f38f011|223344556677885f5f5f5f 32 intel crc32 edx, byte ptr [ecx]
f20f38f011|223344556677885f5f5f5f 32 plan9 REPNE CRC32 0(CX), DX
f20f38f011|223344556677885f5f5f5f 64 gnu crc32b (%rcx),%edx
@ -6530,10 +6532,10 @@ f3480f2a11|223344556677885f5f5f5f 64 intel cvtsi2ss xmm2, qword ptr [rcx]
f3480f2a11|223344556677885f5f5f5f 64 plan9 REP CVTSI2SSQ 0(CX), X2
f3480f2c11|223344556677885f5f5f5f 64 gnu cvttss2si (%rcx),%rdx
f3480f2c11|223344556677885f5f5f5f 64 intel cvttss2si rdx, dword ptr [rcx]
f3480f2c11|223344556677885f5f5f5f 64 plan9 REP CVTTSS2SIQ 0(CX), DX
f3480f2c11|223344556677885f5f5f5f 64 plan9 REP CVTTSS2SIL 0(CX), DX
f3480f2d11|223344556677885f5f5f5f 64 gnu cvtss2si (%rcx),%rdx
f3480f2d11|223344556677885f5f5f5f 64 intel cvtss2si rdx, dword ptr [rcx]
f3480f2d11|223344556677885f5f5f5f 64 plan9 REP CVTSS2SIQ 0(CX), DX
f3480f2d11|223344556677885f5f5f5f 64 plan9 REP CVTSS2SIL 0(CX), DX
f3480fae11|223344556677885f5f5f5f 64 gnu wrfsbaseq (%rcx)
f3480fae11|223344556677885f5f5f5f 64 intel wrfsbase qword ptr [rcx]
f3480fae11|223344556677885f5f5f5f 64 plan9 REP WRFSBASE 0(CX)
@ -6591,40 +6593,40 @@ f5|11223344556677885f5f5f5f5f5f5f 64 gnu cmc
f5|11223344556677885f5f5f5f5f5f5f 64 intel cmc
f5|11223344556677885f5f5f5f5f5f5f 64 plan9 CMC
f60011|223344556677885f5f5f5f5f5f 32 intel test byte ptr [eax], 0x11
f60011|223344556677885f5f5f5f5f5f 32 plan9 TESTL $0x11, 0(AX)
f60011|223344556677885f5f5f5f5f5f 32 plan9 TESTB $0x11, 0(AX)
f60011|223344556677885f5f5f5f5f5f 64 gnu testb $0x11,(%rax)
f60011|223344556677885f5f5f5f5f5f 64 intel test byte ptr [rax], 0x11
f60011|223344556677885f5f5f5f5f5f 64 plan9 TESTL $0x11, 0(AX)
f60011|223344556677885f5f5f5f5f5f 64 plan9 TESTB $0x11, 0(AX)
f611|223344556677885f5f5f5f5f5f5f 32 intel not byte ptr [ecx]
f611|223344556677885f5f5f5f5f5f5f 32 plan9 NOTL 0(CX)
f611|223344556677885f5f5f5f5f5f5f 32 plan9 NOTB 0(CX)
f611|223344556677885f5f5f5f5f5f5f 64 gnu notb (%rcx)
f611|223344556677885f5f5f5f5f5f5f 64 intel not byte ptr [rcx]
f611|223344556677885f5f5f5f5f5f5f 64 plan9 NOTL 0(CX)
f611|223344556677885f5f5f5f5f5f5f 64 plan9 NOTB 0(CX)
f618|11223344556677885f5f5f5f5f5f 32 intel neg byte ptr [eax]
f618|11223344556677885f5f5f5f5f5f 32 plan9 NEGL 0(AX)
f618|11223344556677885f5f5f5f5f5f 32 plan9 NEGB 0(AX)
f618|11223344556677885f5f5f5f5f5f 64 gnu negb (%rax)
f618|11223344556677885f5f5f5f5f5f 64 intel neg byte ptr [rax]
f618|11223344556677885f5f5f5f5f5f 64 plan9 NEGL 0(AX)
f618|11223344556677885f5f5f5f5f5f 64 plan9 NEGB 0(AX)
f620|11223344556677885f5f5f5f5f5f 32 intel mul byte ptr [eax]
f620|11223344556677885f5f5f5f5f5f 32 plan9 MULL 0(AX)
f620|11223344556677885f5f5f5f5f5f 32 plan9 MULB 0(AX)
f620|11223344556677885f5f5f5f5f5f 64 gnu mulb (%rax)
f620|11223344556677885f5f5f5f5f5f 64 intel mul byte ptr [rax]
f620|11223344556677885f5f5f5f5f5f 64 plan9 MULL 0(AX)
f620|11223344556677885f5f5f5f5f5f 64 plan9 MULB 0(AX)
f628|11223344556677885f5f5f5f5f5f 32 intel imul byte ptr [eax]
f628|11223344556677885f5f5f5f5f5f 32 plan9 IMULL 0(AX)
f628|11223344556677885f5f5f5f5f5f 32 plan9 IMULB 0(AX)
f628|11223344556677885f5f5f5f5f5f 64 gnu imulb (%rax)
f628|11223344556677885f5f5f5f5f5f 64 intel imul byte ptr [rax]
f628|11223344556677885f5f5f5f5f5f 64 plan9 IMULL 0(AX)
f628|11223344556677885f5f5f5f5f5f 64 plan9 IMULB 0(AX)
f630|11223344556677885f5f5f5f5f5f 32 intel div byte ptr [eax]
f630|11223344556677885f5f5f5f5f5f 32 plan9 DIVL 0(AX)
f630|11223344556677885f5f5f5f5f5f 32 plan9 DIVB 0(AX)
f630|11223344556677885f5f5f5f5f5f 64 gnu divb (%rax)
f630|11223344556677885f5f5f5f5f5f 64 intel div byte ptr [rax]
f630|11223344556677885f5f5f5f5f5f 64 plan9 DIVL 0(AX)
f630|11223344556677885f5f5f5f5f5f 64 plan9 DIVB 0(AX)
f638|11223344556677885f5f5f5f5f5f 32 intel idiv byte ptr [eax]
f638|11223344556677885f5f5f5f5f5f 32 plan9 IDIVL 0(AX)
f638|11223344556677885f5f5f5f5f5f 32 plan9 IDIVB 0(AX)
f638|11223344556677885f5f5f5f5f5f 64 gnu idivb (%rax)
f638|11223344556677885f5f5f5f5f5f 64 intel idiv byte ptr [rax]
f638|11223344556677885f5f5f5f5f5f 64 plan9 IDIVL 0(AX)
f638|11223344556677885f5f5f5f5f5f 64 plan9 IDIVB 0(AX)
f70011223344|556677885f5f5f5f5f5f 32 intel test dword ptr [eax], 0x44332211
f70011223344|556677885f5f5f5f5f5f 32 plan9 TESTL $0x44332211, 0(AX)
f70011223344|556677885f5f5f5f5f5f 64 gnu testl $0x44332211,(%rax)
@ -6691,15 +6693,15 @@ fd|11223344556677885f5f5f5f5f5f5f 64 gnu std
fd|11223344556677885f5f5f5f5f5f5f 64 intel std
fd|11223344556677885f5f5f5f5f5f5f 64 plan9 STD
fe00|11223344556677885f5f5f5f5f5f 32 intel inc byte ptr [eax]
fe00|11223344556677885f5f5f5f5f5f 32 plan9 INCL 0(AX)
fe00|11223344556677885f5f5f5f5f5f 32 plan9 INCB 0(AX)
fe00|11223344556677885f5f5f5f5f5f 64 gnu incb (%rax)
fe00|11223344556677885f5f5f5f5f5f 64 intel inc byte ptr [rax]
fe00|11223344556677885f5f5f5f5f5f 64 plan9 INCL 0(AX)
fe00|11223344556677885f5f5f5f5f5f 64 plan9 INCB 0(AX)
fe08|11223344556677885f5f5f5f5f5f 32 intel dec byte ptr [eax]
fe08|11223344556677885f5f5f5f5f5f 32 plan9 DECL 0(AX)
fe08|11223344556677885f5f5f5f5f5f 32 plan9 DECB 0(AX)
fe08|11223344556677885f5f5f5f5f5f 64 gnu decb (%rax)
fe08|11223344556677885f5f5f5f5f5f 64 intel dec byte ptr [rax]
fe08|11223344556677885f5f5f5f5f5f 64 plan9 DECL 0(AX)
fe08|11223344556677885f5f5f5f5f5f 64 plan9 DECB 0(AX)
ff00|11223344556677885f5f5f5f5f5f 32 intel inc dword ptr [eax]
ff00|11223344556677885f5f5f5f5f5f 32 plan9 INCL 0(AX)
ff00|11223344556677885f5f5f5f5f5f 64 gnu incl (%rax)
@ -6728,4 +6730,4 @@ ff30|11223344556677885f5f5f5f5f5f 32 intel push dword ptr [eax]
ff30|11223344556677885f5f5f5f5f5f 32 plan9 PUSHL 0(AX)
ff30|11223344556677885f5f5f5f5f5f 64 gnu pushq (%rax)
ff30|11223344556677885f5f5f5f5f5f 64 intel push qword ptr [rax]
ff30|11223344556677885f5f5f5f5f5f 64 plan9 PUSHL 0(AX)
ff30|11223344556677885f5f5f5f5f5f 64 plan9 PUSHQ 0(AX)

View File

@ -125,14 +125,10 @@ func checkCopyLocksFunc(f *File, name string, recv *ast.FieldList, typ *ast.Func
}
}
if typ.Results != nil {
for _, field := range typ.Results.List {
expr := field.Type
if path := lockPath(f.pkg.typesPkg, f.pkg.types[expr].Type); path != nil {
f.Badf(expr.Pos(), "%s returns lock by value: %v", name, path)
}
}
}
// Don't check typ.Results. If T has a Lock field it's OK to write
// return T{}
// because that is returning the zero value. Leave result checking
// to the return statement.
}
// checkCopyLocksRange checks whether a range statement
@ -194,6 +190,16 @@ func lockPathRhs(f *File, x ast.Expr) typePath {
if _, ok := x.(*ast.CompositeLit); ok {
return nil
}
if _, ok := x.(*ast.CallExpr); ok {
// A call may return a zero value.
return nil
}
if star, ok := x.(*ast.StarExpr); ok {
if _, ok := star.X.(*ast.CallExpr); ok {
// A call may return a pointer to a zero value.
return nil
}
}
return lockPath(f.pkg.typesPkg, f.pkg.types[x].Type)
}

View File

@ -29,6 +29,8 @@ type deadState struct {
}
// checkUnreachable checks a function body for dead code.
//
// TODO(adonovan): use the new cfg package, which is more precise.
func checkUnreachable(f *File, node ast.Node) {
var body *ast.BlockStmt
switch n := node.(type) {

View File

@ -91,6 +91,15 @@ Flag: -tests
Mistakes involving tests including functions with incorrect names or signatures
and example tests that document identifiers not in the package.
Failure to call the cancelation function returned by context.WithCancel.
Flag: -lostcancel
The cancelation function returned by context.WithCancel, WithTimeout,
and WithDeadline must be called or the new context will remain live
until its parent context is cancelled.
(The background context is never cancelled.)
Methods
Flag: -methods

View File

@ -0,0 +1,512 @@
// Copyright 2016 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 cfg
// This file implements the CFG construction pass.
import (
"fmt"
"go/ast"
"go/token"
)
type builder struct {
cfg *CFG
mayReturn func(*ast.CallExpr) bool
current *Block
lblocks map[*ast.Object]*lblock // labeled blocks
targets *targets // linked stack of branch targets
}
func (b *builder) stmt(_s ast.Stmt) {
// The label of the current statement. If non-nil, its _goto
// target is always set; its _break and _continue are set only
// within the body of switch/typeswitch/select/for/range.
// It is effectively an additional default-nil parameter of stmt().
var label *lblock
start:
switch s := _s.(type) {
case *ast.BadStmt,
*ast.SendStmt,
*ast.IncDecStmt,
*ast.GoStmt,
*ast.DeferStmt,
*ast.EmptyStmt,
*ast.AssignStmt:
// No effect on control flow.
b.add(s)
case *ast.ExprStmt:
b.add(s)
if call, ok := s.X.(*ast.CallExpr); ok && !b.mayReturn(call) {
// Calls to panic, os.Exit, etc, never return.
b.current = b.newUnreachableBlock("unreachable.call")
}
case *ast.DeclStmt:
// Treat each var ValueSpec as a separate statement.
d := s.Decl.(*ast.GenDecl)
if d.Tok == token.VAR {
for _, spec := range d.Specs {
if spec, ok := spec.(*ast.ValueSpec); ok {
b.add(spec)
}
}
}
case *ast.LabeledStmt:
label = b.labeledBlock(s.Label)
b.jump(label._goto)
b.current = label._goto
_s = s.Stmt
goto start // effectively: tailcall stmt(g, s.Stmt, label)
case *ast.ReturnStmt:
b.add(s)
b.current = b.newUnreachableBlock("unreachable.return")
case *ast.BranchStmt:
var block *Block
switch s.Tok {
case token.BREAK:
if s.Label != nil {
if lb := b.labeledBlock(s.Label); lb != nil {
block = lb._break
}
} else {
for t := b.targets; t != nil && block == nil; t = t.tail {
block = t._break
}
}
case token.CONTINUE:
if s.Label != nil {
if lb := b.labeledBlock(s.Label); lb != nil {
block = lb._continue
}
} else {
for t := b.targets; t != nil && block == nil; t = t.tail {
block = t._continue
}
}
case token.FALLTHROUGH:
for t := b.targets; t != nil; t = t.tail {
block = t._fallthrough
}
case token.GOTO:
if s.Label != nil {
block = b.labeledBlock(s.Label)._goto
}
}
if block == nil {
block = b.newBlock("undefined.branch")
}
b.jump(block)
b.current = b.newUnreachableBlock("unreachable.branch")
case *ast.BlockStmt:
b.stmtList(s.List)
case *ast.IfStmt:
if s.Init != nil {
b.stmt(s.Init)
}
then := b.newBlock("if.then")
done := b.newBlock("if.done")
_else := done
if s.Else != nil {
_else = b.newBlock("if.else")
}
b.add(s.Cond)
b.ifelse(then, _else)
b.current = then
b.stmt(s.Body)
b.jump(done)
if s.Else != nil {
b.current = _else
b.stmt(s.Else)
b.jump(done)
}
b.current = done
case *ast.SwitchStmt:
b.switchStmt(s, label)
case *ast.TypeSwitchStmt:
b.typeSwitchStmt(s, label)
case *ast.SelectStmt:
b.selectStmt(s, label)
case *ast.ForStmt:
b.forStmt(s, label)
case *ast.RangeStmt:
b.rangeStmt(s, label)
default:
panic(fmt.Sprintf("unexpected statement kind: %T", s))
}
}
func (b *builder) stmtList(list []ast.Stmt) {
for _, s := range list {
b.stmt(s)
}
}
func (b *builder) switchStmt(s *ast.SwitchStmt, label *lblock) {
if s.Init != nil {
b.stmt(s.Init)
}
if s.Tag != nil {
b.add(s.Tag)
}
done := b.newBlock("switch.done")
if label != nil {
label._break = done
}
// We pull the default case (if present) down to the end.
// But each fallthrough label must point to the next
// body block in source order, so we preallocate a
// body block (fallthru) for the next case.
// Unfortunately this makes for a confusing block order.
var defaultBody *[]ast.Stmt
var defaultFallthrough *Block
var fallthru, defaultBlock *Block
ncases := len(s.Body.List)
for i, clause := range s.Body.List {
body := fallthru
if body == nil {
body = b.newBlock("switch.body") // first case only
}
// Preallocate body block for the next case.
fallthru = done
if i+1 < ncases {
fallthru = b.newBlock("switch.body")
}
cc := clause.(*ast.CaseClause)
if cc.List == nil {
// Default case.
defaultBody = &cc.Body
defaultFallthrough = fallthru
defaultBlock = body
continue
}
var nextCond *Block
for _, cond := range cc.List {
nextCond = b.newBlock("switch.next")
b.add(cond) // one half of the tag==cond condition
b.ifelse(body, nextCond)
b.current = nextCond
}
b.current = body
b.targets = &targets{
tail: b.targets,
_break: done,
_fallthrough: fallthru,
}
b.stmtList(cc.Body)
b.targets = b.targets.tail
b.jump(done)
b.current = nextCond
}
if defaultBlock != nil {
b.jump(defaultBlock)
b.current = defaultBlock
b.targets = &targets{
tail: b.targets,
_break: done,
_fallthrough: defaultFallthrough,
}
b.stmtList(*defaultBody)
b.targets = b.targets.tail
}
b.jump(done)
b.current = done
}
func (b *builder) typeSwitchStmt(s *ast.TypeSwitchStmt, label *lblock) {
if s.Init != nil {
b.stmt(s.Init)
}
if s.Assign != nil {
b.add(s.Assign)
}
done := b.newBlock("typeswitch.done")
if label != nil {
label._break = done
}
var default_ *ast.CaseClause
for _, clause := range s.Body.List {
cc := clause.(*ast.CaseClause)
if cc.List == nil {
default_ = cc
continue
}
body := b.newBlock("typeswitch.body")
var next *Block
for _, casetype := range cc.List {
next = b.newBlock("typeswitch.next")
// casetype is a type, so don't call b.add(casetype).
// This block logically contains a type assertion,
// x.(casetype), but it's unclear how to represent x.
_ = casetype
b.ifelse(body, next)
b.current = next
}
b.current = body
b.typeCaseBody(cc, done)
b.current = next
}
if default_ != nil {
b.typeCaseBody(default_, done)
} else {
b.jump(done)
}
b.current = done
}
func (b *builder) typeCaseBody(cc *ast.CaseClause, done *Block) {
b.targets = &targets{
tail: b.targets,
_break: done,
}
b.stmtList(cc.Body)
b.targets = b.targets.tail
b.jump(done)
}
func (b *builder) selectStmt(s *ast.SelectStmt, label *lblock) {
// First evaluate channel expressions.
// TODO(adonovan): fix: evaluate only channel exprs here.
for _, clause := range s.Body.List {
if comm := clause.(*ast.CommClause).Comm; comm != nil {
b.stmt(comm)
}
}
done := b.newBlock("select.done")
if label != nil {
label._break = done
}
var defaultBody *[]ast.Stmt
for _, cc := range s.Body.List {
clause := cc.(*ast.CommClause)
if clause.Comm == nil {
defaultBody = &clause.Body
continue
}
body := b.newBlock("select.body")
next := b.newBlock("select.next")
b.ifelse(body, next)
b.current = body
b.targets = &targets{
tail: b.targets,
_break: done,
}
switch comm := clause.Comm.(type) {
case *ast.ExprStmt: // <-ch
// nop
case *ast.AssignStmt: // x := <-states[state].Chan
b.add(comm.Lhs[0])
}
b.stmtList(clause.Body)
b.targets = b.targets.tail
b.jump(done)
b.current = next
}
if defaultBody != nil {
b.targets = &targets{
tail: b.targets,
_break: done,
}
b.stmtList(*defaultBody)
b.targets = b.targets.tail
b.jump(done)
}
b.current = done
}
func (b *builder) forStmt(s *ast.ForStmt, label *lblock) {
// ...init...
// jump loop
// loop:
// if cond goto body else done
// body:
// ...body...
// jump post
// post: (target of continue)
// ...post...
// jump loop
// done: (target of break)
if s.Init != nil {
b.stmt(s.Init)
}
body := b.newBlock("for.body")
done := b.newBlock("for.done") // target of 'break'
loop := body // target of back-edge
if s.Cond != nil {
loop = b.newBlock("for.loop")
}
cont := loop // target of 'continue'
if s.Post != nil {
cont = b.newBlock("for.post")
}
if label != nil {
label._break = done
label._continue = cont
}
b.jump(loop)
b.current = loop
if loop != body {
b.add(s.Cond)
b.ifelse(body, done)
b.current = body
}
b.targets = &targets{
tail: b.targets,
_break: done,
_continue: cont,
}
b.stmt(s.Body)
b.targets = b.targets.tail
b.jump(cont)
if s.Post != nil {
b.current = cont
b.stmt(s.Post)
b.jump(loop) // back-edge
}
b.current = done
}
func (b *builder) rangeStmt(s *ast.RangeStmt, label *lblock) {
b.add(s.X)
if s.Key != nil {
b.add(s.Key)
}
if s.Value != nil {
b.add(s.Value)
}
// ...
// loop: (target of continue)
// if ... goto body else done
// body:
// ...
// jump loop
// done: (target of break)
loop := b.newBlock("range.loop")
b.jump(loop)
b.current = loop
body := b.newBlock("range.body")
done := b.newBlock("range.done")
b.ifelse(body, done)
b.current = body
if label != nil {
label._break = done
label._continue = loop
}
b.targets = &targets{
tail: b.targets,
_break: done,
_continue: loop,
}
b.stmt(s.Body)
b.targets = b.targets.tail
b.jump(loop) // back-edge
b.current = done
}
// -------- helpers --------
// Destinations associated with unlabeled for/switch/select stmts.
// We push/pop one of these as we enter/leave each construct and for
// each BranchStmt we scan for the innermost target of the right type.
//
type targets struct {
tail *targets // rest of stack
_break *Block
_continue *Block
_fallthrough *Block
}
// Destinations associated with a labeled block.
// We populate these as labels are encountered in forward gotos or
// labeled statements.
//
type lblock struct {
_goto *Block
_break *Block
_continue *Block
}
// labeledBlock returns the branch target associated with the
// specified label, creating it if needed.
//
func (b *builder) labeledBlock(label *ast.Ident) *lblock {
lb := b.lblocks[label.Obj]
if lb == nil {
lb = &lblock{_goto: b.newBlock(label.Name)}
if b.lblocks == nil {
b.lblocks = make(map[*ast.Object]*lblock)
}
b.lblocks[label.Obj] = lb
}
return lb
}
// newBlock appends a new unconnected basic block to b.cfg's block
// slice and returns it.
// It does not automatically become the current block.
// comment is an optional string for more readable debugging output.
func (b *builder) newBlock(comment string) *Block {
g := b.cfg
block := &Block{
index: int32(len(g.Blocks)),
comment: comment,
}
block.Succs = block.succs2[:0]
g.Blocks = append(g.Blocks, block)
return block
}
func (b *builder) newUnreachableBlock(comment string) *Block {
block := b.newBlock(comment)
block.unreachable = true
return block
}
func (b *builder) add(n ast.Node) {
b.current.Nodes = append(b.current.Nodes, n)
}
// jump adds an edge from the current block to the target block,
// and sets b.current to nil.
func (b *builder) jump(target *Block) {
b.current.Succs = append(b.current.Succs, target)
b.current = nil
}
// ifelse emits edges from the current block to the t and f blocks,
// and sets b.current to nil.
func (b *builder) ifelse(t, f *Block) {
b.current.Succs = append(b.current.Succs, t, f)
b.current = nil
}

View File

@ -0,0 +1,142 @@
// Copyright 2016 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.
// This package constructs a simple control-flow graph (CFG) of the
// statements and expressions within a single function.
//
// Use cfg.New to construct the CFG for a function body.
//
// The blocks of the CFG contain all the function's non-control
// statements. The CFG does not contain control statements such as If,
// Switch, Select, and Branch, but does contain their subexpressions.
// For example, this source code:
//
// if x := f(); x != nil {
// T()
// } else {
// F()
// }
//
// produces this CFG:
//
// 1: x := f()
// x != nil
// succs: 2, 3
// 2: T()
// succs: 4
// 3: F()
// succs: 4
// 4:
//
// The CFG does contain Return statements; even implicit returns are
// materialized (at the position of the function's closing brace).
//
// The CFG does not record conditions associated with conditional branch
// edges, nor the short-circuit semantics of the && and || operators,
// nor abnormal control flow caused by panic. If you need this
// information, use golang.org/x/tools/go/ssa instead.
//
package cfg
// Although the vet tool has type information, it is often extremely
// fragmentary, so for simplicity this package does not depend on
// go/types. Consequently control-flow conditions are ignored even
// when constant, and "mayReturn" information must be provided by the
// client.
import (
"bytes"
"fmt"
"go/ast"
"go/format"
"go/token"
)
// A CFG represents the control-flow graph of a single function.
//
// The entry point is Blocks[0]; there may be multiple return blocks.
type CFG struct {
Blocks []*Block // block[0] is entry; order otherwise undefined
}
// A Block represents a basic block: a list of statements and
// expressions that are always evaluated sequentially.
//
// A block may have 0-2 successors: zero for a return block or a block
// that calls a function such as panic that never returns; one for a
// normal (jump) block; and two for a conditional (if) block.
type Block struct {
Nodes []ast.Node // statements, expressions, and ValueSpecs
Succs []*Block // successor nodes in the graph
comment string // for debugging
index int32 // index within CFG.Blocks
unreachable bool // is block of stmts following return/panic/for{}
succs2 [2]*Block // underlying array for Succs
}
// New returns a new control-flow graph for the specified function body,
// which must be non-nil.
//
// The CFG builder calls mayReturn to determine whether a given function
// call may return. For example, calls to panic, os.Exit, and log.Fatal
// do not return, so the builder can remove infeasible graph edges
// following such calls. The builder calls mayReturn only for a
// CallExpr beneath an ExprStmt.
func New(body *ast.BlockStmt, mayReturn func(*ast.CallExpr) bool) *CFG {
b := builder{
mayReturn: mayReturn,
cfg: new(CFG),
}
b.current = b.newBlock("entry")
b.stmt(body)
// Does control fall off the end of the function's body?
// Make implicit return explicit.
if b.current != nil && !b.current.unreachable {
b.add(&ast.ReturnStmt{
Return: body.End() - 1,
})
}
return b.cfg
}
func (b *Block) String() string {
return fmt.Sprintf("block %d (%s)", b.index, b.comment)
}
// Return returns the return statement at the end of this block if present, nil otherwise.
func (b *Block) Return() (ret *ast.ReturnStmt) {
if len(b.Nodes) > 0 {
ret, _ = b.Nodes[len(b.Nodes)-1].(*ast.ReturnStmt)
}
return
}
// Format formats the control-flow graph for ease of debugging.
func (g *CFG) Format(fset *token.FileSet) string {
var buf bytes.Buffer
for _, b := range g.Blocks {
fmt.Fprintf(&buf, ".%d: # %s\n", b.index, b.comment)
for _, n := range b.Nodes {
fmt.Fprintf(&buf, "\t%s\n", formatNode(fset, n))
}
if len(b.Succs) > 0 {
fmt.Fprintf(&buf, "\tsuccs:")
for _, succ := range b.Succs {
fmt.Fprintf(&buf, " %d", succ.index)
}
buf.WriteByte('\n')
}
buf.WriteByte('\n')
}
return buf.String()
}
func formatNode(fset *token.FileSet, n ast.Node) string {
var buf bytes.Buffer
format.Node(&buf, fset, n)
// Indent secondary lines by a tab.
return string(bytes.Replace(buf.Bytes(), []byte("\n"), []byte("\n\t"), -1))
}

View File

@ -0,0 +1,190 @@
// Copyright 2016 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 cfg
import (
"bytes"
"fmt"
"go/ast"
"go/parser"
"go/token"
"testing"
)
const src = `package main
import "log"
func f1() {
live()
return
dead()
}
func f2() {
for {
live()
}
dead()
}
func f3() {
if true { // even known values are ignored
return
}
for true { // even known values are ignored
live()
}
for {
live()
}
dead()
}
func f4(x int) {
switch x {
case 1:
live()
fallthrough
case 2:
live()
log.Fatal()
default:
panic("oops")
}
dead()
}
func f4(ch chan int) {
select {
case <-ch:
live()
return
default:
live()
panic("oops")
}
dead()
}
func f5(unknown bool) {
for {
if unknown {
break
}
continue
dead()
}
live()
}
func f6(unknown bool) {
outer:
for {
for {
break outer
dead()
}
dead()
}
live()
}
func f7() {
for {
break nosuchlabel
dead()
}
dead()
}
func f8() {
select{}
dead()
}
func f9(ch chan int) {
select {
case <-ch:
return
}
dead()
}
func f10(ch chan int) {
select {
case <-ch:
return
dead()
default:
}
live()
}
func f11() {
goto; // mustn't crash
dead()
}
`
func TestDeadCode(t *testing.T) {
// We'll use dead code detection to verify the CFG.
fset := token.NewFileSet()
f, err := parser.ParseFile(fset, "dummy.go", src, parser.Mode(0))
if err != nil {
t.Fatal(err)
}
for _, decl := range f.Decls {
if decl, ok := decl.(*ast.FuncDecl); ok {
g := New(decl.Body, mayReturn)
// Mark blocks reachable from entry.
live := make(map[*Block]bool)
var visit func(*Block)
visit = func(b *Block) {
if !live[b] {
live[b] = true
for _, succ := range b.Succs {
visit(succ)
}
}
}
visit(g.Blocks[0])
// Print statements in unreachable blocks
// (in order determined by builder).
var buf bytes.Buffer
for _, b := range g.Blocks {
if !live[b] {
for _, n := range b.Nodes {
fmt.Fprintf(&buf, "\t%s\n", formatNode(fset, n))
}
}
}
// Check that the result contains "dead" at least once but not "live".
if !bytes.Contains(buf.Bytes(), []byte("dead")) ||
bytes.Contains(buf.Bytes(), []byte("live")) {
t.Errorf("unexpected dead statements in function %s:\n%s",
decl.Name.Name,
&buf)
t.Logf("control flow graph:\n%s", g.Format(fset))
}
}
}
}
// A trivial mayReturn predicate that looks only at syntax, not types.
func mayReturn(call *ast.CallExpr) bool {
switch fun := call.Fun.(type) {
case *ast.Ident:
return fun.Name != "panic"
case *ast.SelectorExpr:
return fun.Sel.Name != "Fatal"
}
return true
}

318
src/cmd/vet/lostcancel.go Normal file
View File

@ -0,0 +1,318 @@
// Copyright 2016 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 main
import (
"cmd/vet/internal/cfg"
"fmt"
"go/ast"
"go/types"
"strconv"
)
func init() {
register("lostcancel",
"check for failure to call cancelation function returned by context.WithCancel",
checkLostCancel,
funcDecl, funcLit)
}
const debugLostCancel = false
var contextPackage = "context"
// checkLostCancel reports a failure to the call the cancel function
// returned by context.WithCancel, either because the variable was
// assigned to the blank identifier, or because there exists a
// control-flow path from the call to a return statement and that path
// does not "use" the cancel function. Any reference to the variable
// counts as a use, even within a nested function literal.
//
// checkLostCancel analyzes a single named or literal function.
func checkLostCancel(f *File, node ast.Node) {
// Fast path: bypass check if file doesn't use context.WithCancel.
if !hasImport(f.file, contextPackage) {
return
}
// Maps each cancel variable to its defining ValueSpec/AssignStmt.
cancelvars := make(map[*types.Var]ast.Node)
// Find the set of cancel vars to analyze.
stack := make([]ast.Node, 0, 32)
ast.Inspect(node, func(n ast.Node) bool {
switch n.(type) {
case *ast.FuncLit:
if len(stack) > 0 {
return false // don't stray into nested functions
}
case nil:
stack = stack[:len(stack)-1] // pop
return true
}
stack = append(stack, n) // push
// Look for [{AssignStmt,ValueSpec} CallExpr SelectorExpr]:
//
// ctx, cancel := context.WithCancel(...)
// ctx, cancel = context.WithCancel(...)
// var ctx, cancel = context.WithCancel(...)
//
if isContextWithCancel(f, n) && isCall(stack[len(stack)-2]) {
var id *ast.Ident // id of cancel var
stmt := stack[len(stack)-3]
switch stmt := stmt.(type) {
case *ast.ValueSpec:
if len(stmt.Names) > 1 {
id = stmt.Names[1]
}
case *ast.AssignStmt:
if len(stmt.Lhs) > 1 {
id, _ = stmt.Lhs[1].(*ast.Ident)
}
}
if id != nil {
if id.Name == "_" {
f.Badf(id.Pos(), "the cancel function returned by context.%s should be called, not discarded, to avoid a context leak",
n.(*ast.SelectorExpr).Sel.Name)
} else if v, ok := f.pkg.uses[id].(*types.Var); ok {
cancelvars[v] = stmt
} else if v, ok := f.pkg.defs[id].(*types.Var); ok {
cancelvars[v] = stmt
}
}
}
return true
})
if len(cancelvars) == 0 {
return // no need to build CFG
}
// Tell the CFG builder which functions never return.
info := &types.Info{Uses: f.pkg.uses, Selections: f.pkg.selectors}
mayReturn := func(call *ast.CallExpr) bool {
name := callName(info, call)
return !noReturnFuncs[name]
}
// Build the CFG.
var g *cfg.CFG
var sig *types.Signature
switch node := node.(type) {
case *ast.FuncDecl:
sig, _ = f.pkg.defs[node.Name].Type().(*types.Signature)
g = cfg.New(node.Body, mayReturn)
case *ast.FuncLit:
sig, _ = f.pkg.types[node.Type].Type.(*types.Signature)
g = cfg.New(node.Body, mayReturn)
}
// Print CFG.
if debugLostCancel {
fmt.Println(g.Format(f.fset))
}
// Examine the CFG for each variable in turn.
// (It would be more efficient to analyze all cancelvars in a
// single pass over the AST, but seldom is there more than one.)
for v, stmt := range cancelvars {
if ret := lostCancelPath(f, g, v, stmt, sig); ret != nil {
lineno := f.fset.Position(stmt.Pos()).Line
f.Badf(stmt.Pos(), "the %s function is not used on all paths (possible context leak)", v.Name())
f.Badf(ret.Pos(), "this return statement may be reached without using the %s var defined on line %d", v.Name(), lineno)
}
}
}
func isCall(n ast.Node) bool { _, ok := n.(*ast.CallExpr); return ok }
func hasImport(f *ast.File, path string) bool {
for _, imp := range f.Imports {
v, _ := strconv.Unquote(imp.Path.Value)
if v == path {
return true
}
}
return false
}
// isContextWithCancel reports whether n is one of the qualified identifiers
// context.With{Cancel,Timeout,Deadline}.
func isContextWithCancel(f *File, n ast.Node) bool {
if sel, ok := n.(*ast.SelectorExpr); ok {
switch sel.Sel.Name {
case "WithCancel", "WithTimeout", "WithDeadline":
if x, ok := sel.X.(*ast.Ident); ok {
if pkgname, ok := f.pkg.uses[x].(*types.PkgName); ok {
return pkgname.Imported().Path() == contextPackage
}
// Import failed, so we can't check package path.
// Just check the local package name (heuristic).
return x.Name == "context"
}
}
}
return false
}
// lostCancelPath finds a path through the CFG, from stmt (which defines
// the 'cancel' variable v) to a return statement, that doesn't "use" v.
// If it finds one, it returns the return statement (which may be synthetic).
// sig is the function's type, if known.
func lostCancelPath(f *File, g *cfg.CFG, v *types.Var, stmt ast.Node, sig *types.Signature) *ast.ReturnStmt {
vIsNamedResult := sig != nil && tupleContains(sig.Results(), v)
// uses reports whether stmts contain a "use" of variable v.
uses := func(f *File, v *types.Var, stmts []ast.Node) bool {
found := false
for _, stmt := range stmts {
ast.Inspect(stmt, func(n ast.Node) bool {
switch n := n.(type) {
case *ast.Ident:
if f.pkg.uses[n] == v {
found = true
}
case *ast.ReturnStmt:
// A naked return statement counts as a use
// of the named result variables.
if n.Results == nil && vIsNamedResult {
found = true
}
}
return !found
})
}
return found
}
// blockUses computes "uses" for each block, caching the result.
memo := make(map[*cfg.Block]bool)
blockUses := func(f *File, v *types.Var, b *cfg.Block) bool {
res, ok := memo[b]
if !ok {
res = uses(f, v, b.Nodes)
memo[b] = res
}
return res
}
// Find the var's defining block in the CFG,
// plus the rest of the statements of that block.
var defblock *cfg.Block
var rest []ast.Node
outer:
for _, b := range g.Blocks {
for i, n := range b.Nodes {
if n == stmt {
defblock = b
rest = b.Nodes[i+1:]
break outer
}
}
}
if defblock == nil {
panic("internal error: can't find defining block for cancel var")
}
// Is v "used" in the remainder of its defining block?
if uses(f, v, rest) {
return nil
}
// Does the defining block return without using v?
if ret := defblock.Return(); ret != nil {
return ret
}
// Search the CFG depth-first for a path, from defblock to a
// return block, in which v is never "used".
seen := make(map[*cfg.Block]bool)
var search func(blocks []*cfg.Block) *ast.ReturnStmt
search = func(blocks []*cfg.Block) *ast.ReturnStmt {
for _, b := range blocks {
if !seen[b] {
seen[b] = true
// Prune the search if the block uses v.
if blockUses(f, v, b) {
continue
}
// Found path to return statement?
if ret := b.Return(); ret != nil {
if debugLostCancel {
fmt.Printf("found path to return in block %s\n", b)
}
return ret // found
}
// Recur
if ret := search(b.Succs); ret != nil {
if debugLostCancel {
fmt.Printf(" from block %s\n", b)
}
return ret
}
}
}
return nil
}
return search(defblock.Succs)
}
func tupleContains(tuple *types.Tuple, v *types.Var) bool {
for i := 0; i < tuple.Len(); i++ {
if tuple.At(i) == v {
return true
}
}
return false
}
var noReturnFuncs = map[string]bool{
"(*testing.common).FailNow": true,
"(*testing.common).Fatal": true,
"(*testing.common).Fatalf": true,
"(*testing.common).Skip": true,
"(*testing.common).SkipNow": true,
"(*testing.common).Skipf": true,
"log.Fatal": true,
"log.Fatalf": true,
"log.Fatalln": true,
"os.Exit": true,
"panic": true,
"runtime.Goexit": true,
}
// callName returns the canonical name of the builtin, method, or
// function called by call, if known.
func callName(info *types.Info, call *ast.CallExpr) string {
switch fun := call.Fun.(type) {
case *ast.Ident:
// builtin, e.g. "panic"
if obj, ok := info.Uses[fun].(*types.Builtin); ok {
return obj.Name()
}
case *ast.SelectorExpr:
if sel, ok := info.Selections[fun]; ok && sel.Kind() == types.MethodVal {
// method call, e.g. "(*testing.common).Fatal"
meth := sel.Obj()
return fmt.Sprintf("(%s).%s",
meth.Type().(*types.Signature).Recv().Type(),
meth.Name())
}
if obj, ok := info.Uses[fun.Sel]; ok {
// qualified identifier, e.g. "os.Exit"
return fmt.Sprintf("%s.%s",
obj.Pkg().Path(),
obj.Name())
}
}
// function with no name, or defined in missing imported package
return ""
}

View File

@ -182,6 +182,9 @@ type File struct {
file *ast.File
b bytes.Buffer // for use by methods
// Parsed package "foo" when checking package "foo_test"
basePkg *Package
// The objects that are receivers of a "String() string" method.
// This is used by the recursiveStringer method in print.go.
stringers map[*ast.Object]bool
@ -238,7 +241,7 @@ func main() {
}
os.Exit(exitCode)
}
if !doPackage(".", flag.Args()) {
if doPackage(".", flag.Args(), nil) == nil {
warnf("no files checked")
}
os.Exit(exitCode)
@ -278,12 +281,12 @@ func doPackageDir(directory string) {
names = append(names, pkg.TestGoFiles...) // These are also in the "foo" package.
names = append(names, pkg.SFiles...)
prefixDirectory(directory, names)
doPackage(directory, names)
basePkg := doPackage(directory, names, nil)
// Is there also a "foo_test" package? If so, do that one as well.
if len(pkg.XTestGoFiles) > 0 {
names = pkg.XTestGoFiles
prefixDirectory(directory, names)
doPackage(directory, names)
doPackage(directory, names, basePkg)
}
}
@ -299,8 +302,8 @@ type Package struct {
}
// doPackage analyzes the single package constructed from the named files.
// It returns whether any files were checked.
func doPackage(directory string, names []string) bool {
// It returns the parsed Package or nil if none of the files have been checked.
func doPackage(directory string, names []string, basePkg *Package) *Package {
var files []*File
var astFiles []*ast.File
fs := token.NewFileSet()
@ -309,7 +312,7 @@ func doPackage(directory string, names []string) bool {
if err != nil {
// Warn but continue to next package.
warnf("%s: %s", name, err)
return false
return nil
}
checkBuildTag(name, data)
var parsedFile *ast.File
@ -317,14 +320,14 @@ func doPackage(directory string, names []string) bool {
parsedFile, err = parser.ParseFile(fs, name, data, 0)
if err != nil {
warnf("%s: %s", name, err)
return false
return nil
}
astFiles = append(astFiles, parsedFile)
}
files = append(files, &File{fset: fs, content: data, name: name, file: parsedFile})
}
if len(astFiles) == 0 {
return false
return nil
}
pkg := new(Package)
pkg.path = astFiles[0].Name.Name
@ -346,13 +349,14 @@ func doPackage(directory string, names []string) bool {
}
for _, file := range files {
file.pkg = pkg
file.basePkg = basePkg
file.checkers = chk
if file.file != nil {
file.walkFile(file.name, file.file)
}
}
asmCheck(pkg)
return true
return pkg
}
func visit(path string, f os.FileInfo, err error) error {

View File

@ -12,7 +12,7 @@ import "sync"
func OkFunc(*sync.Mutex) {}
func BadFunc(sync.Mutex) {} // ERROR "BadFunc passes lock by value: sync.Mutex"
func OkRet() *sync.Mutex {}
func BadRet() sync.Mutex {} // ERROR "BadRet returns lock by value: sync.Mutex"
func BadRet() sync.Mutex {} // Don't warn about results
var (
OkClosure = func(*sync.Mutex) {}
@ -28,7 +28,7 @@ func (EmbeddedRWMutex) BadMeth() {} // ERROR "BadMeth passes lock by value: test
func OkFunc(e *EmbeddedRWMutex) {}
func BadFunc(EmbeddedRWMutex) {} // ERROR "BadFunc passes lock by value: testdata.EmbeddedRWMutex"
func OkRet() *EmbeddedRWMutex {}
func BadRet() EmbeddedRWMutex {} // ERROR "BadRet returns lock by value: testdata.EmbeddedRWMutex"
func BadRet() EmbeddedRWMutex {} // Don't warn about results
type FieldMutex struct {
s sync.Mutex
@ -107,6 +107,14 @@ func ReturnViaInterface(x int) (int, interface{}) {
}
}
// Some cases that we don't warn about.
func AcceptedCases() {
x := EmbeddedRwMutex{} // composite literal on RHS is OK (#16227)
x = BadRet() // function call on RHS is OK (#16227)
x = *OKRet() // indirection of function call on RHS is OK (#16227)
}
// TODO: Unfortunate cases
// Non-ideal error message:

View File

@ -4,11 +4,11 @@ package buf_test
func Example() {} // OK because is package-level.
func Example_suffix() // OK because refers to suffix annotation.
func Example_suffix() {} // OK because refers to suffix annotation.
func Example_BadSuffix() // ERROR "Example_BadSuffix has malformed example suffix: BadSuffix"
func Example_BadSuffix() {} // ERROR "Example_BadSuffix has malformed example suffix: BadSuffix"
func ExampleBuf() // OK because refers to known top-level type.
func ExampleBuf() {} // OK because refers to known top-level type.
func ExampleBuf_Append() {} // OK because refers to known method.
@ -28,8 +28,8 @@ func ExampleBuf_Len(i int) {} // ERROR "ExampleBuf_Len should be niladic"
// "Puffer" is German for "Buffer".
func ExamplePuffer() // ERROR "ExamplePuffer refers to unknown identifier: Puffer"
func ExamplePuffer() {} // ERROR "ExamplePuffer refers to unknown identifier: Puffer"
func ExamplePuffer_Append() // ERROR "ExamplePuffer_Append refers to unknown identifier: Puffer"
func ExamplePuffer_Append() {} // ERROR "ExamplePuffer_Append refers to unknown identifier: Puffer"
func ExamplePuffer_suffix() // ERROR "ExamplePuffer_suffix refers to unknown identifier: Puffer"
func ExamplePuffer_suffix() {} // ERROR "ExamplePuffer_suffix refers to unknown identifier: Puffer"

155
src/cmd/vet/testdata/lostcancel.go vendored Normal file
View File

@ -0,0 +1,155 @@
// Copyright 2016 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 testdata
import (
"context"
"log"
"os"
"testing"
)
// Check the three functions and assignment forms (var, :=, =) we look for.
// (Do these early: line numbers are fragile.)
func _() {
var ctx, cancel = context.WithCancel() // ERROR "the cancel function is not used on all paths \(possible context leak\)"
} // ERROR "this return statement may be reached without using the cancel var defined on line 17"
func _() {
ctx, cancel2 := context.WithDeadline() // ERROR "the cancel2 function is not used..."
} // ERROR "may be reached without using the cancel2 var defined on line 21"
func _() {
var ctx context.Context
var cancel3 func()
ctx, cancel3 = context.WithTimeout() // ERROR "function is not used..."
} // ERROR "this return statement may be reached without using the cancel3 var defined on line 27"
func _() {
ctx, _ := context.WithCancel() // ERROR "the cancel function returned by context.WithCancel should be called, not discarded, to avoid a context leak"
ctx, _ = context.WithTimeout() // ERROR "the cancel function returned by context.WithTimeout should be called, not discarded, to avoid a context leak"
ctx, _ = context.WithDeadline() // ERROR "the cancel function returned by context.WithDeadline should be called, not discarded, to avoid a context leak"
}
func _() {
ctx, cancel := context.WithCancel()
defer cancel() // ok
}
func _() {
ctx, cancel := context.WithCancel() // ERROR "not used on all paths"
if condition {
cancel()
}
return // ERROR "this return statement may be reached without using the cancel var"
}
func _() {
ctx, cancel := context.WithCancel()
if condition {
cancel()
} else {
// ok: infinite loop
for {
print(0)
}
}
}
func _() {
ctx, cancel := context.WithCancel() // ERROR "not used on all paths"
if condition {
cancel()
} else {
for i := 0; i < 10; i++ {
print(0)
}
}
} // ERROR "this return statement may be reached without using the cancel var"
func _() {
ctx, cancel := context.WithCancel()
// ok: used on all paths
switch someInt {
case 0:
new(testing.T).FailNow()
case 1:
log.Fatal()
case 2:
cancel()
case 3:
print("hi")
fallthrough
default:
os.Exit(1)
}
}
func _() {
ctx, cancel := context.WithCancel() // ERROR "not used on all paths"
switch someInt {
case 0:
new(testing.T).FailNow()
case 1:
log.Fatal()
case 2:
cancel()
case 3:
print("hi") // falls through to implicit return
default:
os.Exit(1)
}
} // ERROR "this return statement may be reached without using the cancel var"
func _(ch chan int) int {
ctx, cancel := context.WithCancel() // ERROR "not used on all paths"
select {
case <-ch:
new(testing.T).FailNow()
case y <- ch:
print("hi") // falls through to implicit return
case ch <- 1:
cancel()
default:
os.Exit(1)
}
} // ERROR "this return statement may be reached without using the cancel var"
func _(ch chan int) int {
ctx, cancel := context.WithCancel()
// A blocking select must execute one of its cases.
select {
case <-ch:
panic()
}
}
func _() {
go func() {
ctx, cancel := context.WithCancel() // ERROR "not used on all paths"
print(ctx)
}() // ERROR "may be reached without using the cancel var"
}
var condition bool
var someInt int
// Regression test for Go issue 16143.
func _() {
var x struct{ f func() }
x.f()
}
// Regression test for Go issue 16230.
func _() (ctx context.Context, cancel func()) {
ctx, cancel = context.WithCancel()
return // a naked return counts as a load of the named result values
}
// Same as above, but for literal function.
var _ = func() (ctx context.Context, cancel func()) {
ctx, cancel = context.WithCancel()
return
}

View File

@ -59,23 +59,28 @@ func lookup(name string, scopes []*types.Scope) types.Object {
return nil
}
func extendedScope(pkg *Package) []*types.Scope {
scopes := []*types.Scope{pkg.typesPkg.Scope()}
pkgName := pkg.typesPkg.Name()
if strings.HasPrefix(pkgName, "_test") {
basePkg := strings.TrimSuffix(pkgName, "_test")
for _, p := range pkg.typesPkg.Imports() {
if p.Name() == basePkg {
scopes = append(scopes, p.Scope())
break
func extendedScope(f *File) []*types.Scope {
scopes := []*types.Scope{f.pkg.typesPkg.Scope()}
if f.basePkg != nil {
scopes = append(scopes, f.basePkg.typesPkg.Scope())
} else {
// If basePkg is not specified (e.g. when checking a single file) try to
// find it among imports.
pkgName := f.pkg.typesPkg.Name()
if strings.HasSuffix(pkgName, "_test") {
basePkgName := strings.TrimSuffix(pkgName, "_test")
for _, p := range f.pkg.typesPkg.Imports() {
if p.Name() == basePkgName {
scopes = append(scopes, p.Scope())
break
}
}
}
}
return scopes
}
func checkExample(fn *ast.FuncDecl, pkg *Package, report reporter) {
func checkExample(fn *ast.FuncDecl, f *File, report reporter) {
fnName := fn.Name.Name
if params := fn.Type.Params; len(params.List) != 0 {
report("%s should be niladic", fnName)
@ -100,7 +105,7 @@ func checkExample(fn *ast.FuncDecl, pkg *Package, report reporter) {
exName = strings.TrimPrefix(fnName, "Example")
elems = strings.SplitN(exName, "_", 3)
ident = elems[0]
obj = lookup(ident, extendedScope(pkg))
obj = lookup(ident, extendedScope(f))
)
if ident != "" && obj == nil {
// Check ExampleFoo and ExampleBadFoo.
@ -173,7 +178,7 @@ func checkTestFunctions(f *File, node ast.Node) {
switch {
case strings.HasPrefix(fn.Name.Name, "Example"):
checkExample(fn, f.pkg, report)
checkExample(fn, f, report)
case strings.HasPrefix(fn.Name.Name, "Test"):
checkTest(fn, "Test", report)
case strings.HasPrefix(fn.Name.Name, "Benchmark"):

View File

@ -102,7 +102,7 @@ func TestVet(t *testing.T) {
func TestDivergentPackagesExamples(t *testing.T) {
Build(t)
// errchk ./testvet
Vet(t, []string{"testdata/divergent/buf.go", "testdata/divergent/buf_test.go"})
Vet(t, []string{"testdata/divergent"})
}
func TestIncompleteExamples(t *testing.T) {

View File

@ -683,6 +683,10 @@ outer:
levprd[nprod] = 0
}
if TEMPSIZE < ntokens+nnonter+1 {
errorf("too many tokens (%d) or non-terminals (%d)", ntokens, nnonter)
}
//
// end of all rules
// dump out the prefix code

View File

@ -766,7 +766,7 @@ func (f *decompressor) Reset(r io.Reader, dict []byte) error {
dict: f.dict,
step: (*decompressor).nextBlock,
}
f.dict.init(maxMatchOffset, nil)
f.dict.init(maxMatchOffset, dict)
return nil
}

View File

@ -37,3 +37,33 @@ func TestReset(t *testing.T) {
}
}
}
func TestResetDict(t *testing.T) {
dict := []byte("the lorem fox")
ss := []string{
"lorem ipsum izzle fo rizzle",
"the quick brown fox jumped over",
}
deflated := make([]bytes.Buffer, len(ss))
for i, s := range ss {
w, _ := NewWriterDict(&deflated[i], DefaultCompression, dict)
w.Write([]byte(s))
w.Close()
}
inflated := make([]bytes.Buffer, len(ss))
f := NewReader(nil)
for i := range inflated {
f.(Resetter).Reset(&deflated[i], dict)
io.Copy(&inflated[i], f)
}
f.Close()
for i, s := range ss {
if s != inflated[i].String() {
t.Errorf("inflated[%d]:\ngot %q\nwant %q", i, inflated[i], s)
}
}
}

View File

@ -6,24 +6,35 @@
// cancelation signals, and other request-scoped values across API boundaries
// and between processes.
//
// Incoming requests to a server should create a Context, and outgoing calls to
// servers should accept a Context. The chain of function calls between must
// propagate the Context, optionally replacing it with a modified copy created
// using WithDeadline, WithTimeout, WithCancel, or WithValue.
// Incoming requests to a server should create a Context, and outgoing
// calls to servers should accept a Context. The chain of function
// calls between them must propagate the Context, optionally replacing
// it with a derived Context created using WithCancel, WithDeadline,
// WithTimeout, or WithValue. When a Context is canceled, all
// Contexts derived from it are also canceled.
//
// The WithCancel, WithDeadline, and WithTimeout functions take a
// Context (the parent) and return a derived Context (the child) and a
// CancelFunc. Calling the CancelFunc cancels the child and its
// children, removes the parent's reference to the child, and stops
// any associated timers. Failing to call the CancelFunc leaks the
// child and its children until the parent is canceled or the timer
// fires. The go vet tool checks that CancelFuncs are used on all
// control-flow paths.
//
// Programs that use Contexts should follow these rules to keep interfaces
// consistent across packages and enable static analysis tools to check context
// propagation:
//
// Do not store Contexts inside a struct type; instead, pass a Context
// explicitly to each function that needs it. The Context should be the first
// explicitly to each function that needs it. The Context should be the first
// parameter, typically named ctx:
//
// func DoSomething(ctx context.Context, arg Arg) error {
// // ... use ctx ...
// }
//
// Do not pass a nil Context, even if a function permits it. Pass context.TODO
// Do not pass a nil Context, even if a function permits it. Pass context.TODO
// if you are unsure about which Context to use.
//
// Use context Values only for request-scoped data that transits processes and
@ -50,13 +61,13 @@ import (
// Context's methods may be called by multiple goroutines simultaneously.
type Context interface {
// Deadline returns the time when work done on behalf of this context
// should be canceled. Deadline returns ok==false when no deadline is
// set. Successive calls to Deadline return the same results.
// should be canceled. Deadline returns ok==false when no deadline is
// set. Successive calls to Deadline return the same results.
Deadline() (deadline time.Time, ok bool)
// Done returns a channel that's closed when work done on behalf of this
// context should be canceled. Done may return nil if this context can
// never be canceled. Successive calls to Done return the same value.
// context should be canceled. Done may return nil if this context can
// never be canceled. Successive calls to Done return the same value.
//
// WithCancel arranges for Done to be closed when cancel is called;
// WithDeadline arranges for Done to be closed when the deadline
@ -85,24 +96,24 @@ type Context interface {
// a Done channel for cancelation.
Done() <-chan struct{}
// Err returns a non-nil error value after Done is closed. Err returns
// Err returns a non-nil error value after Done is closed. Err returns
// Canceled if the context was canceled or DeadlineExceeded if the
// context's deadline passed. No other values for Err are defined.
// context's deadline passed. No other values for Err are defined.
// After Done is closed, successive calls to Err return the same value.
Err() error
// Value returns the value associated with this context for key, or nil
// if no value is associated with key. Successive calls to Value with
// if no value is associated with key. Successive calls to Value with
// the same key returns the same result.
//
// Use context values only for request-scoped data that transits
// processes and API boundaries, not for passing optional parameters to
// functions.
//
// A key identifies a specific value in a Context. Functions that wish
// A key identifies a specific value in a Context. Functions that wish
// to store values in Context typically allocate a key in a global
// variable then use that key as the argument to context.WithValue and
// Context.Value. A key can be any type that supports equality;
// Context.Value. A key can be any type that supports equality;
// packages should define keys as an unexported type to avoid
// collisions.
//
@ -121,7 +132,7 @@ type Context interface {
// // This prevents collisions with keys defined in other packages.
// type key int
//
// // userKey is the key for user.User values in Contexts. It is
// // userKey is the key for user.User values in Contexts. It is
// // unexported; clients use user.NewContext and user.FromContext
// // instead of using this key directly.
// var userKey key = 0
@ -152,7 +163,7 @@ func (deadlineExceededError) Error() string { return "context deadline exceeded"
func (deadlineExceededError) Timeout() bool { return true }
// An emptyCtx is never canceled, has no values, and has no deadline. It is not
// An emptyCtx is never canceled, has no values, and has no deadline. It is not
// struct{}, since vars of this type must have distinct addresses.
type emptyCtx int
@ -188,17 +199,17 @@ var (
)
// Background returns a non-nil, empty Context. It is never canceled, has no
// values, and has no deadline. It is typically used by the main function,
// values, and has no deadline. It is typically used by the main function,
// initialization, and tests, and as the top-level Context for incoming
// requests.
func Background() Context {
return background
}
// TODO returns a non-nil, empty Context. Code should use context.TODO when
// TODO returns a non-nil, empty Context. Code should use context.TODO when
// it's unclear which Context to use or it is not yet available (because the
// surrounding function has not yet been extended to accept a Context
// parameter). TODO is recognized by static analysis tools that determine
// parameter). TODO is recognized by static analysis tools that determine
// whether Contexts are propagated correctly in a program.
func TODO() Context {
return todo
@ -258,7 +269,7 @@ func propagateCancel(parent Context, child canceler) {
}
// parentCancelCtx follows a chain of parent references until it finds a
// *cancelCtx. This function understands how each of the concrete types in this
// *cancelCtx. This function understands how each of the concrete types in this
// package represents its parent.
func parentCancelCtx(parent Context) (*cancelCtx, bool) {
for {
@ -288,14 +299,14 @@ func removeChild(parent Context, child canceler) {
p.mu.Unlock()
}
// A canceler is a context type that can be canceled directly. The
// A canceler is a context type that can be canceled directly. The
// implementations are *cancelCtx and *timerCtx.
type canceler interface {
cancel(removeFromParent bool, err error)
Done() <-chan struct{}
}
// A cancelCtx can be canceled. When canceled, it also cancels any children
// A cancelCtx can be canceled. When canceled, it also cancels any children
// that implement canceler.
type cancelCtx struct {
Context
@ -347,8 +358,8 @@ func (c *cancelCtx) cancel(removeFromParent bool, err error) {
}
// WithDeadline returns a copy of the parent context with the deadline adjusted
// to be no later than d. If the parent's deadline is already earlier than d,
// WithDeadline(parent, d) is semantically equivalent to parent. The returned
// to be no later than d. If the parent's deadline is already earlier than d,
// WithDeadline(parent, d) is semantically equivalent to parent. The returned
// context's Done channel is closed when the deadline expires, when the returned
// cancel function is called, or when the parent context's Done channel is
// closed, whichever happens first.
@ -380,8 +391,8 @@ func WithDeadline(parent Context, deadline time.Time) (Context, CancelFunc) {
return c, func() { c.cancel(true, Canceled) }
}
// A timerCtx carries a timer and a deadline. It embeds a cancelCtx to
// implement Done and Err. It implements cancel by stopping its timer then
// A timerCtx carries a timer and a deadline. It embeds a cancelCtx to
// implement Done and Err. It implements cancel by stopping its timer then
// delegating to cancelCtx.cancel.
type timerCtx struct {
cancelCtx
@ -443,7 +454,7 @@ func WithValue(parent Context, key, val interface{}) Context {
return &valueCtx{parent, key, val}
}
// A valueCtx carries a key-value pair. It implements Value for that key and
// A valueCtx carries a key-value pair. It implements Value for that key and
// delegates all other calls to the embedded Context.
type valueCtx struct {
Context

View File

@ -13,13 +13,21 @@ import (
func ExampleWithTimeout() {
// Pass a context with a timeout to tell a blocking function that it
// should abandon its work after the timeout elapses.
ctx, _ := context.WithTimeout(context.Background(), 50*time.Millisecond)
ctx, cancel := context.WithTimeout(context.Background(), 50*time.Millisecond)
select {
case <-time.After(1 * time.Second):
fmt.Println("overslept")
case <-ctx.Done():
fmt.Println(ctx.Err()) // prints "context deadline exceeded"
}
// Even though ctx should have expired already, it is good
// practice to call its cancelation function in any case.
// Failure to do so may keep the context and its parent alive
// longer than necessary.
cancel()
// Output:
// context deadline exceeded
}

View File

@ -143,10 +143,11 @@ func fermatInverse(k, N *big.Int) *big.Int {
var errZeroParam = errors.New("zero parameter")
// Sign signs an arbitrary length hash (which should be the result of hashing a
// larger message) using the private key, priv. It returns the signature as a
// pair of integers. The security of the private key depends on the entropy of
// rand.
// Sign signs a hash (which should be the result of hashing a larger message)
// using the private key, priv. If the hash is longer than the bit-length of the
// private key's curve order, the hash will be truncated to that length. It
// returns the signature as a pair of integers. The security of the private key
// depends on the entropy of rand.
func Sign(rand io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int, err error) {
// Get max(log2(q) / 2, 256) bits of entropy from rand.
entropylen := (priv.Curve.Params().BitSize + 7) / 16

View File

@ -422,6 +422,33 @@ func ticketKeyFromBytes(b [32]byte) (key ticketKey) {
return key
}
// clone returns a copy of c. Only the exported fields are copied.
func (c *Config) clone() *Config {
return &Config{
Rand: c.Rand,
Time: c.Time,
Certificates: c.Certificates,
NameToCertificate: c.NameToCertificate,
GetCertificate: c.GetCertificate,
RootCAs: c.RootCAs,
NextProtos: c.NextProtos,
ServerName: c.ServerName,
ClientAuth: c.ClientAuth,
ClientCAs: c.ClientCAs,
InsecureSkipVerify: c.InsecureSkipVerify,
CipherSuites: c.CipherSuites,
PreferServerCipherSuites: c.PreferServerCipherSuites,
SessionTicketsDisabled: c.SessionTicketsDisabled,
SessionTicketKey: c.SessionTicketKey,
ClientSessionCache: c.ClientSessionCache,
MinVersion: c.MinVersion,
MaxVersion: c.MaxVersion,
CurvePreferences: c.CurvePreferences,
DynamicRecordSizingDisabled: c.DynamicRecordSizingDisabled,
Renegotiation: c.Renegotiation,
}
}
func (c *Config) serverInit() {
if c.SessionTicketsDisabled {
return

View File

@ -124,9 +124,9 @@ func TestCertificateSelection(t *testing.T) {
func runDynamicRecordSizingTest(t *testing.T, config *Config) {
clientConn, serverConn := net.Pipe()
serverConfig := *config
serverConfig := config.clone()
serverConfig.DynamicRecordSizingDisabled = false
tlsConn := Server(serverConn, &serverConfig)
tlsConn := Server(serverConn, serverConfig)
recordSizesChan := make(chan []int, 1)
go func() {
@ -225,19 +225,19 @@ func runDynamicRecordSizingTest(t *testing.T, config *Config) {
}
func TestDynamicRecordSizingWithStreamCipher(t *testing.T) {
config := *testConfig
config := testConfig.clone()
config.CipherSuites = []uint16{TLS_RSA_WITH_RC4_128_SHA}
runDynamicRecordSizingTest(t, &config)
runDynamicRecordSizingTest(t, config)
}
func TestDynamicRecordSizingWithCBC(t *testing.T) {
config := *testConfig
config := testConfig.clone()
config.CipherSuites = []uint16{TLS_RSA_WITH_AES_256_CBC_SHA}
runDynamicRecordSizingTest(t, &config)
runDynamicRecordSizingTest(t, config)
}
func TestDynamicRecordSizingWithAEAD(t *testing.T) {
config := *testConfig
config := testConfig.clone()
config.CipherSuites = []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}
runDynamicRecordSizingTest(t, &config)
runDynamicRecordSizingTest(t, config)
}

View File

@ -509,14 +509,14 @@ func TestHandshakeClientAES256GCMSHA384(t *testing.T) {
}
func TestHandshakeClientCertRSA(t *testing.T) {
config := *testConfig
config := testConfig.clone()
cert, _ := X509KeyPair([]byte(clientCertificatePEM), []byte(clientKeyPEM))
config.Certificates = []Certificate{cert}
test := &clientTest{
name: "ClientCert-RSA-RSA",
command: []string{"openssl", "s_server", "-cipher", "RC4-SHA", "-verify", "1"},
config: &config,
config: config,
}
runClientTestTLS10(t, test)
@ -525,7 +525,7 @@ func TestHandshakeClientCertRSA(t *testing.T) {
test = &clientTest{
name: "ClientCert-RSA-ECDSA",
command: []string{"openssl", "s_server", "-cipher", "ECDHE-ECDSA-AES128-SHA", "-verify", "1"},
config: &config,
config: config,
cert: testECDSACertificate,
key: testECDSAPrivateKey,
}
@ -536,7 +536,7 @@ func TestHandshakeClientCertRSA(t *testing.T) {
test = &clientTest{
name: "ClientCert-RSA-AES256-GCM-SHA384",
command: []string{"openssl", "s_server", "-cipher", "ECDHE-RSA-AES256-GCM-SHA384", "-verify", "1"},
config: &config,
config: config,
cert: testRSACertificate,
key: testRSAPrivateKey,
}
@ -545,14 +545,14 @@ func TestHandshakeClientCertRSA(t *testing.T) {
}
func TestHandshakeClientCertECDSA(t *testing.T) {
config := *testConfig
config := testConfig.clone()
cert, _ := X509KeyPair([]byte(clientECDSACertificatePEM), []byte(clientECDSAKeyPEM))
config.Certificates = []Certificate{cert}
test := &clientTest{
name: "ClientCert-ECDSA-RSA",
command: []string{"openssl", "s_server", "-cipher", "RC4-SHA", "-verify", "1"},
config: &config,
config: config,
}
runClientTestTLS10(t, test)
@ -561,7 +561,7 @@ func TestHandshakeClientCertECDSA(t *testing.T) {
test = &clientTest{
name: "ClientCert-ECDSA-ECDSA",
command: []string{"openssl", "s_server", "-cipher", "ECDHE-ECDSA-AES128-SHA", "-verify", "1"},
config: &config,
config: config,
cert: testECDSACertificate,
key: testECDSAPrivateKey,
}
@ -691,7 +691,7 @@ func TestLRUClientSessionCache(t *testing.T) {
}
func TestHandshakeClientALPNMatch(t *testing.T) {
config := *testConfig
config := testConfig.clone()
config.NextProtos = []string{"proto2", "proto1"}
test := &clientTest{
@ -699,7 +699,7 @@ func TestHandshakeClientALPNMatch(t *testing.T) {
// Note that this needs OpenSSL 1.0.2 because that is the first
// version that supports the -alpn flag.
command: []string{"openssl", "s_server", "-alpn", "proto1,proto2"},
config: &config,
config: config,
validate: func(state ConnectionState) error {
// The server's preferences should override the client.
if state.NegotiatedProtocol != "proto1" {
@ -712,7 +712,7 @@ func TestHandshakeClientALPNMatch(t *testing.T) {
}
func TestHandshakeClientALPNNoMatch(t *testing.T) {
config := *testConfig
config := testConfig.clone()
config.NextProtos = []string{"proto3"}
test := &clientTest{
@ -720,7 +720,7 @@ func TestHandshakeClientALPNNoMatch(t *testing.T) {
// Note that this needs OpenSSL 1.0.2 because that is the first
// version that supports the -alpn flag.
command: []string{"openssl", "s_server", "-alpn", "proto1,proto2"},
config: &config,
config: config,
validate: func(state ConnectionState) error {
// There's no overlap so OpenSSL will not select a protocol.
if state.NegotiatedProtocol != "" {
@ -736,7 +736,7 @@ func TestHandshakeClientALPNNoMatch(t *testing.T) {
const sctsBase64 = "ABIBaQFnAHUApLkJkLQYWBSHuxOizGdwCjw1mAT5G9+443fNDsgN3BAAAAFHl5nuFgAABAMARjBEAiAcS4JdlW5nW9sElUv2zvQyPoZ6ejKrGGB03gjaBZFMLwIgc1Qbbn+hsH0RvObzhS+XZhr3iuQQJY8S9G85D9KeGPAAdgBo9pj4H2SCvjqM7rkoHUz8cVFdZ5PURNEKZ6y7T0/7xAAAAUeX4bVwAAAEAwBHMEUCIDIhFDgG2HIuADBkGuLobU5a4dlCHoJLliWJ1SYT05z6AiEAjxIoZFFPRNWMGGIjskOTMwXzQ1Wh2e7NxXE1kd1J0QsAdgDuS723dc5guuFCaR+r4Z5mow9+X7By2IMAxHuJeqj9ywAAAUhcZIqHAAAEAwBHMEUCICmJ1rBT09LpkbzxtUC+Hi7nXLR0J+2PmwLp+sJMuqK+AiEAr0NkUnEVKVhAkccIFpYDqHOlZaBsuEhWWrYpg2RtKp0="
func TestHandshakClientSCTs(t *testing.T) {
config := *testConfig
config := testConfig.clone()
scts, err := base64.StdEncoding.DecodeString(sctsBase64)
if err != nil {
@ -748,7 +748,7 @@ func TestHandshakClientSCTs(t *testing.T) {
// Note that this needs OpenSSL 1.0.2 because that is the first
// version that supports the -serverinfo flag.
command: []string{"openssl", "s_server"},
config: &config,
config: config,
extensions: [][]byte{scts},
validate: func(state ConnectionState) error {
expectedSCTs := [][]byte{
@ -771,11 +771,11 @@ func TestHandshakClientSCTs(t *testing.T) {
}
func TestRenegotiationRejected(t *testing.T) {
config := *testConfig
config := testConfig.clone()
test := &clientTest{
name: "RenegotiationRejected",
command: []string{"openssl", "s_server", "-state"},
config: &config,
config: config,
numRenegotiations: 1,
renegotiationExpectedToFail: 1,
checkRenegotiationError: func(renegotiationNum int, err error) error {
@ -793,13 +793,13 @@ func TestRenegotiationRejected(t *testing.T) {
}
func TestRenegotiateOnce(t *testing.T) {
config := *testConfig
config := testConfig.clone()
config.Renegotiation = RenegotiateOnceAsClient
test := &clientTest{
name: "RenegotiateOnce",
command: []string{"openssl", "s_server", "-state"},
config: &config,
config: config,
numRenegotiations: 1,
}
@ -807,13 +807,13 @@ func TestRenegotiateOnce(t *testing.T) {
}
func TestRenegotiateTwice(t *testing.T) {
config := *testConfig
config := testConfig.clone()
config.Renegotiation = RenegotiateFreelyAsClient
test := &clientTest{
name: "RenegotiateTwice",
command: []string{"openssl", "s_server", "-state"},
config: &config,
config: config,
numRenegotiations: 2,
}
@ -821,13 +821,13 @@ func TestRenegotiateTwice(t *testing.T) {
}
func TestRenegotiateTwiceRejected(t *testing.T) {
config := *testConfig
config := testConfig.clone()
config.Renegotiation = RenegotiateOnceAsClient
test := &clientTest{
name: "RenegotiateTwiceRejected",
command: []string{"openssl", "s_server", "-state"},
config: &config,
config: config,
numRenegotiations: 2,
renegotiationExpectedToFail: 2,
checkRenegotiationError: func(renegotiationNum int, err error) error {

View File

@ -130,11 +130,11 @@ func TestNoRC4ByDefault(t *testing.T) {
cipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
compressionMethods: []uint8{compressionNone},
}
serverConfig := *testConfig
serverConfig := testConfig.clone()
// Reset the enabled cipher suites to nil in order to test the
// defaults.
serverConfig.CipherSuites = nil
testClientHelloFailure(t, &serverConfig, clientHello, "no cipher suite supported by both client and server")
testClientHelloFailure(t, serverConfig, clientHello, "no cipher suite supported by both client and server")
}
func TestDontSelectECDSAWithRSAKey(t *testing.T) {
@ -147,19 +147,19 @@ func TestDontSelectECDSAWithRSAKey(t *testing.T) {
supportedCurves: []CurveID{CurveP256},
supportedPoints: []uint8{pointFormatUncompressed},
}
serverConfig := *testConfig
serverConfig := testConfig.clone()
serverConfig.CipherSuites = clientHello.cipherSuites
serverConfig.Certificates = make([]Certificate, 1)
serverConfig.Certificates[0].Certificate = [][]byte{testECDSACertificate}
serverConfig.Certificates[0].PrivateKey = testECDSAPrivateKey
serverConfig.BuildNameToCertificate()
// First test that it *does* work when the server's key is ECDSA.
testClientHello(t, &serverConfig, clientHello)
testClientHello(t, serverConfig, clientHello)
// Now test that switching to an RSA key causes the expected error (and
// not an internal error about a signing failure).
serverConfig.Certificates = testConfig.Certificates
testClientHelloFailure(t, &serverConfig, clientHello, "no cipher suite supported by both client and server")
testClientHelloFailure(t, serverConfig, clientHello, "no cipher suite supported by both client and server")
}
func TestDontSelectRSAWithECDSAKey(t *testing.T) {
@ -172,10 +172,10 @@ func TestDontSelectRSAWithECDSAKey(t *testing.T) {
supportedCurves: []CurveID{CurveP256},
supportedPoints: []uint8{pointFormatUncompressed},
}
serverConfig := *testConfig
serverConfig := testConfig.clone()
serverConfig.CipherSuites = clientHello.cipherSuites
// First test that it *does* work when the server's key is RSA.
testClientHello(t, &serverConfig, clientHello)
testClientHello(t, serverConfig, clientHello)
// Now test that switching to an ECDSA key causes the expected error
// (and not an internal error about a signing failure).
@ -183,7 +183,7 @@ func TestDontSelectRSAWithECDSAKey(t *testing.T) {
serverConfig.Certificates[0].Certificate = [][]byte{testECDSACertificate}
serverConfig.Certificates[0].PrivateKey = testECDSAPrivateKey
serverConfig.BuildNameToCertificate()
testClientHelloFailure(t, &serverConfig, clientHello, "no cipher suite supported by both client and server")
testClientHelloFailure(t, serverConfig, clientHello, "no cipher suite supported by both client and server")
}
func TestRenegotiationExtension(t *testing.T) {
@ -265,9 +265,9 @@ func TestTLS12OnlyCipherSuites(t *testing.T) {
reply, clientErr = cli.readHandshake()
c.Close()
}()
config := *testConfig
config := testConfig.clone()
config.CipherSuites = clientHello.cipherSuites
Server(s, &config).Handshake()
Server(s, config).Handshake()
s.Close()
if clientErr != nil {
t.Fatal(clientErr)
@ -732,7 +732,7 @@ func TestHandshakeServerAES256GCMSHA384(t *testing.T) {
}
func TestHandshakeServerECDHEECDSAAES(t *testing.T) {
config := *testConfig
config := testConfig.clone()
config.Certificates = make([]Certificate, 1)
config.Certificates[0].Certificate = [][]byte{testECDSACertificate}
config.Certificates[0].PrivateKey = testECDSAPrivateKey
@ -741,14 +741,14 @@ func TestHandshakeServerECDHEECDSAAES(t *testing.T) {
test := &serverTest{
name: "ECDHE-ECDSA-AES",
command: []string{"openssl", "s_client", "-no_ticket", "-cipher", "ECDHE-ECDSA-AES256-SHA"},
config: &config,
config: config,
}
runServerTestTLS10(t, test)
runServerTestTLS12(t, test)
}
func TestHandshakeServerALPN(t *testing.T) {
config := *testConfig
config := testConfig.clone()
config.NextProtos = []string{"proto1", "proto2"}
test := &serverTest{
@ -756,7 +756,7 @@ func TestHandshakeServerALPN(t *testing.T) {
// Note that this needs OpenSSL 1.0.2 because that is the first
// version that supports the -alpn flag.
command: []string{"openssl", "s_client", "-alpn", "proto2,proto1"},
config: &config,
config: config,
validate: func(state ConnectionState) error {
// The server's preferences should override the client.
if state.NegotiatedProtocol != "proto1" {
@ -769,7 +769,7 @@ func TestHandshakeServerALPN(t *testing.T) {
}
func TestHandshakeServerALPNNoMatch(t *testing.T) {
config := *testConfig
config := testConfig.clone()
config.NextProtos = []string{"proto3"}
test := &serverTest{
@ -777,7 +777,7 @@ func TestHandshakeServerALPNNoMatch(t *testing.T) {
// Note that this needs OpenSSL 1.0.2 because that is the first
// version that supports the -alpn flag.
command: []string{"openssl", "s_client", "-alpn", "proto2,proto1"},
config: &config,
config: config,
validate: func(state ConnectionState) error {
// Rather than reject the connection, Go doesn't select
// a protocol when there is no overlap.
@ -804,7 +804,7 @@ func TestHandshakeServerSNI(t *testing.T) {
// TestHandshakeServerSNICertForName is similar to TestHandshakeServerSNI, but
// tests the dynamic GetCertificate method
func TestHandshakeServerSNIGetCertificate(t *testing.T) {
config := *testConfig
config := testConfig.clone()
// Replace the NameToCertificate map with a GetCertificate function
nameToCert := config.NameToCertificate
@ -816,7 +816,7 @@ func TestHandshakeServerSNIGetCertificate(t *testing.T) {
test := &serverTest{
name: "SNI-GetCertificate",
command: []string{"openssl", "s_client", "-no_ticket", "-cipher", "AES128-SHA", "-servername", "snitest.com"},
config: &config,
config: config,
}
runServerTestTLS12(t, test)
}
@ -826,7 +826,7 @@ func TestHandshakeServerSNIGetCertificate(t *testing.T) {
// GetCertificate method doesn't return a cert, we fall back to what's in
// the NameToCertificate map.
func TestHandshakeServerSNIGetCertificateNotFound(t *testing.T) {
config := *testConfig
config := testConfig.clone()
config.GetCertificate = func(clientHello *ClientHelloInfo) (*Certificate, error) {
return nil, nil
@ -834,7 +834,7 @@ func TestHandshakeServerSNIGetCertificateNotFound(t *testing.T) {
test := &serverTest{
name: "SNI-GetCertificateNotFound",
command: []string{"openssl", "s_client", "-no_ticket", "-cipher", "AES128-SHA", "-servername", "snitest.com"},
config: &config,
config: config,
}
runServerTestTLS12(t, test)
}
@ -844,7 +844,7 @@ func TestHandshakeServerSNIGetCertificateNotFound(t *testing.T) {
func TestHandshakeServerSNIGetCertificateError(t *testing.T) {
const errMsg = "TestHandshakeServerSNIGetCertificateError error"
serverConfig := *testConfig
serverConfig := testConfig.clone()
serverConfig.GetCertificate = func(clientHello *ClientHelloInfo) (*Certificate, error) {
return nil, errors.New(errMsg)
}
@ -855,7 +855,7 @@ func TestHandshakeServerSNIGetCertificateError(t *testing.T) {
compressionMethods: []uint8{compressionNone},
serverName: "test",
}
testClientHelloFailure(t, &serverConfig, clientHello, errMsg)
testClientHelloFailure(t, serverConfig, clientHello, errMsg)
}
// TestHandshakeServerEmptyCertificates tests that GetCertificates is called in
@ -863,7 +863,7 @@ func TestHandshakeServerSNIGetCertificateError(t *testing.T) {
func TestHandshakeServerEmptyCertificates(t *testing.T) {
const errMsg = "TestHandshakeServerEmptyCertificates error"
serverConfig := *testConfig
serverConfig := testConfig.clone()
serverConfig.GetCertificate = func(clientHello *ClientHelloInfo) (*Certificate, error) {
return nil, errors.New(errMsg)
}
@ -874,7 +874,7 @@ func TestHandshakeServerEmptyCertificates(t *testing.T) {
cipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
compressionMethods: []uint8{compressionNone},
}
testClientHelloFailure(t, &serverConfig, clientHello, errMsg)
testClientHelloFailure(t, serverConfig, clientHello, errMsg)
// With an empty Certificates and a nil GetCertificate, the server
// should always return a “no certificates” error.
@ -885,23 +885,23 @@ func TestHandshakeServerEmptyCertificates(t *testing.T) {
cipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
compressionMethods: []uint8{compressionNone},
}
testClientHelloFailure(t, &serverConfig, clientHello, "no certificates")
testClientHelloFailure(t, serverConfig, clientHello, "no certificates")
}
// TestCipherSuiteCertPreferance ensures that we select an RSA ciphersuite with
// an RSA certificate and an ECDSA ciphersuite with an ECDSA certificate.
func TestCipherSuiteCertPreferenceECDSA(t *testing.T) {
config := *testConfig
config := testConfig.clone()
config.CipherSuites = []uint16{TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA}
config.PreferServerCipherSuites = true
test := &serverTest{
name: "CipherSuiteCertPreferenceRSA",
config: &config,
config: config,
}
runServerTestTLS12(t, test)
config = *testConfig
config = testConfig.clone()
config.CipherSuites = []uint16{TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA}
config.Certificates = []Certificate{
{
@ -914,7 +914,7 @@ func TestCipherSuiteCertPreferenceECDSA(t *testing.T) {
test = &serverTest{
name: "CipherSuiteCertPreferenceECDSA",
config: &config,
config: config,
}
runServerTestTLS12(t, test)
}
@ -940,12 +940,12 @@ func TestResumptionDisabled(t *testing.T) {
sessionFilePath := tempFile("")
defer os.Remove(sessionFilePath)
config := *testConfig
config := testConfig.clone()
test := &serverTest{
name: "IssueTicketPreDisable",
command: []string{"openssl", "s_client", "-cipher", "RC4-SHA", "-sess_out", sessionFilePath},
config: &config,
config: config,
}
runServerTestTLS12(t, test)
@ -954,7 +954,7 @@ func TestResumptionDisabled(t *testing.T) {
test = &serverTest{
name: "ResumeDisabled",
command: []string{"openssl", "s_client", "-cipher", "RC4-SHA", "-sess_in", sessionFilePath},
config: &config,
config: config,
}
runServerTestTLS12(t, test)
@ -963,12 +963,12 @@ func TestResumptionDisabled(t *testing.T) {
}
func TestFallbackSCSV(t *testing.T) {
serverConfig := &Config{
serverConfig := Config{
Certificates: testConfig.Certificates,
}
test := &serverTest{
name: "FallbackSCSV",
config: serverConfig,
config: &serverConfig,
// OpenSSL 1.0.1j is needed for the -fallback_scsv option.
command: []string{"openssl", "s_client", "-fallback_scsv"},
expectHandshakeErrorIncluding: "inappropriate protocol fallback",
@ -1053,20 +1053,20 @@ func TestClientAuth(t *testing.T) {
defer os.Remove(ecdsaKeyPath)
}
config := *testConfig
config := testConfig.clone()
config.ClientAuth = RequestClientCert
test := &serverTest{
name: "ClientAuthRequestedNotGiven",
command: []string{"openssl", "s_client", "-no_ticket", "-cipher", "RC4-SHA"},
config: &config,
config: config,
}
runServerTestTLS12(t, test)
test = &serverTest{
name: "ClientAuthRequestedAndGiven",
command: []string{"openssl", "s_client", "-no_ticket", "-cipher", "RC4-SHA", "-cert", certPath, "-key", keyPath},
config: &config,
config: config,
expectedPeerCerts: []string{clientCertificatePEM},
}
runServerTestTLS12(t, test)
@ -1074,7 +1074,7 @@ func TestClientAuth(t *testing.T) {
test = &serverTest{
name: "ClientAuthRequestedAndECDSAGiven",
command: []string{"openssl", "s_client", "-no_ticket", "-cipher", "RC4-SHA", "-cert", ecdsaCertPath, "-key", ecdsaKeyPath},
config: &config,
config: config,
expectedPeerCerts: []string{clientECDSACertificatePEM},
}
runServerTestTLS12(t, test)

View File

@ -135,9 +135,9 @@ func DialWithDialer(dialer *net.Dialer, network, addr string, config *Config) (*
// from the hostname we're connecting to.
if config.ServerName == "" {
// Make a copy to avoid polluting argument or default.
c := *config
c := config.clone()
c.ServerName = hostname
config = &c
config = c
}
conn := Client(rawConn, config)

View File

@ -6,14 +6,19 @@ package tls
import (
"bytes"
"crypto/x509"
"errors"
"fmt"
"internal/testenv"
"io"
"math"
"math/rand"
"net"
"os"
"reflect"
"strings"
"testing"
"testing/quick"
"time"
)
@ -236,8 +241,8 @@ func testConnReadNonzeroAndEOF(t *testing.T, delay time.Duration) error {
srvCh <- nil
return
}
serverConfig := *testConfig
srv := Server(sconn, &serverConfig)
serverConfig := testConfig.clone()
srv := Server(sconn, serverConfig)
if err := srv.Handshake(); err != nil {
serr = fmt.Errorf("handshake: %v", err)
srvCh <- nil
@ -246,8 +251,8 @@ func testConnReadNonzeroAndEOF(t *testing.T, delay time.Duration) error {
srvCh <- srv
}()
clientConfig := *testConfig
conn, err := Dial("tcp", ln.Addr().String(), &clientConfig)
clientConfig := testConfig.clone()
conn, err := Dial("tcp", ln.Addr().String(), clientConfig)
if err != nil {
t.Fatal(err)
}
@ -290,8 +295,8 @@ func TestTLSUniqueMatches(t *testing.T) {
if err != nil {
t.Fatal(err)
}
serverConfig := *testConfig
srv := Server(sconn, &serverConfig)
serverConfig := testConfig.clone()
srv := Server(sconn, serverConfig)
if err := srv.Handshake(); err != nil {
t.Fatal(err)
}
@ -299,9 +304,9 @@ func TestTLSUniqueMatches(t *testing.T) {
}
}()
clientConfig := *testConfig
clientConfig := testConfig.clone()
clientConfig.ClientSessionCache = NewLRUClientSessionCache(1)
conn, err := Dial("tcp", ln.Addr().String(), &clientConfig)
conn, err := Dial("tcp", ln.Addr().String(), clientConfig)
if err != nil {
t.Fatal(err)
}
@ -310,7 +315,7 @@ func TestTLSUniqueMatches(t *testing.T) {
}
conn.Close()
conn, err = Dial("tcp", ln.Addr().String(), &clientConfig)
conn, err = Dial("tcp", ln.Addr().String(), clientConfig)
if err != nil {
t.Fatal(err)
}
@ -389,8 +394,8 @@ func TestConnCloseBreakingWrite(t *testing.T) {
srvCh <- nil
return
}
serverConfig := *testConfig
srv := Server(sconn, &serverConfig)
serverConfig := testConfig.clone()
srv := Server(sconn, serverConfig)
if err := srv.Handshake(); err != nil {
serr = fmt.Errorf("handshake: %v", err)
srvCh <- nil
@ -409,8 +414,8 @@ func TestConnCloseBreakingWrite(t *testing.T) {
Conn: cconn,
}
clientConfig := *testConfig
tconn := Client(conn, &clientConfig)
clientConfig := testConfig.clone()
tconn := Client(conn, clientConfig)
if err := tconn.Handshake(); err != nil {
t.Fatal(err)
}
@ -453,6 +458,58 @@ func TestConnCloseBreakingWrite(t *testing.T) {
}
}
func TestClone(t *testing.T) {
var c1 Config
v := reflect.ValueOf(&c1).Elem()
rnd := rand.New(rand.NewSource(time.Now().Unix()))
typ := v.Type()
for i := 0; i < typ.NumField(); i++ {
f := v.Field(i)
if !f.CanSet() {
// unexported field; not cloned.
continue
}
// testing/quick can't handle functions or interfaces.
fn := typ.Field(i).Name
switch fn {
case "Rand":
f.Set(reflect.ValueOf(io.Reader(os.Stdin)))
continue
case "Time", "GetCertificate":
// DeepEqual can't compare functions.
continue
case "Certificates":
f.Set(reflect.ValueOf([]Certificate{
{Certificate: [][]byte{[]byte{'b'}}},
}))
continue
case "NameToCertificate":
f.Set(reflect.ValueOf(map[string]*Certificate{"a": nil}))
continue
case "RootCAs", "ClientCAs":
f.Set(reflect.ValueOf(x509.NewCertPool()))
continue
case "ClientSessionCache":
f.Set(reflect.ValueOf(NewLRUClientSessionCache(10)))
continue
}
q, ok := quick.Value(f.Type(), rnd)
if !ok {
t.Fatalf("quick.Value failed on field %s", fn)
}
f.Set(q)
}
c2 := c1.clone()
if !reflect.DeepEqual(&c1, c2) {
t.Errorf("clone failed to copy a field")
}
}
// changeImplConn is a net.Conn which can change its Write and Close
// methods.
type changeImplConn struct {
@ -481,7 +538,12 @@ func throughput(b *testing.B, totalBytes int64, dynamicRecordSizingDisabled bool
N := b.N
// Less than 64KB because Windows appears to use a TCP rwin < 64KB.
// See Issue #15899.
const bufsize = 32 << 10
go func() {
buf := make([]byte, bufsize)
for i := 0; i < N; i++ {
sconn, err := ln.Accept()
if err != nil {
@ -489,24 +551,26 @@ func throughput(b *testing.B, totalBytes int64, dynamicRecordSizingDisabled bool
// (cannot call b.Fatal in goroutine)
panic(fmt.Errorf("accept: %v", err))
}
serverConfig := *testConfig
serverConfig := testConfig.clone()
serverConfig.DynamicRecordSizingDisabled = dynamicRecordSizingDisabled
srv := Server(sconn, &serverConfig)
srv := Server(sconn, serverConfig)
if err := srv.Handshake(); err != nil {
panic(fmt.Errorf("handshake: %v", err))
}
io.Copy(srv, srv)
if _, err := io.CopyBuffer(srv, srv, buf); err != nil {
panic(fmt.Errorf("copy buffer: %v", err))
}
}
}()
b.SetBytes(totalBytes)
clientConfig := *testConfig
clientConfig := testConfig.clone()
clientConfig.DynamicRecordSizingDisabled = dynamicRecordSizingDisabled
buf := make([]byte, 1<<14)
buf := make([]byte, bufsize)
chunks := int(math.Ceil(float64(totalBytes) / float64(len(buf))))
for i := 0; i < N; i++ {
conn, err := Dial("tcp", ln.Addr().String(), &clientConfig)
conn, err := Dial("tcp", ln.Addr().String(), clientConfig)
if err != nil {
b.Fatal(err)
}
@ -577,9 +641,9 @@ func latency(b *testing.B, bps int, dynamicRecordSizingDisabled bool) {
// (cannot call b.Fatal in goroutine)
panic(fmt.Errorf("accept: %v", err))
}
serverConfig := *testConfig
serverConfig := testConfig.clone()
serverConfig.DynamicRecordSizingDisabled = dynamicRecordSizingDisabled
srv := Server(&slowConn{sconn, bps}, &serverConfig)
srv := Server(&slowConn{sconn, bps}, serverConfig)
if err := srv.Handshake(); err != nil {
panic(fmt.Errorf("handshake: %v", err))
}
@ -587,14 +651,14 @@ func latency(b *testing.B, bps int, dynamicRecordSizingDisabled bool) {
}
}()
clientConfig := *testConfig
clientConfig := testConfig.clone()
clientConfig.DynamicRecordSizingDisabled = dynamicRecordSizingDisabled
buf := make([]byte, 16384)
peek := make([]byte, 1)
for i := 0; i < N; i++ {
conn, err := Dial("tcp", ln.Addr().String(), &clientConfig)
conn, err := Dial("tcp", ln.Addr().String(), clientConfig)
if err != nil {
b.Fatal(err)
}

View File

@ -718,6 +718,9 @@ func (db *DB) maybeOpenNewConnections() {
for numRequests > 0 {
db.numOpen++ // optimistically
numRequests--
if db.closed {
return
}
db.openerCh <- struct{}{}
}
}
@ -915,6 +918,9 @@ func (db *DB) putConn(dc *driverConn, err error) {
// If a connRequest was fulfilled or the *driverConn was placed in the
// freeConn list, then true is returned, otherwise false is returned.
func (db *DB) putConnDBLocked(dc *driverConn, err error) bool {
if db.closed {
return false
}
if db.maxOpen > 0 && db.numOpen > db.maxOpen {
return false
}

View File

@ -144,7 +144,7 @@ func closeDB(t testing.TB, db *DB) {
count := db.numOpen
db.mu.Unlock()
if count != 0 {
t.Fatalf("%d connections still open after closing DB", db.numOpen)
t.Fatalf("%d connections still open after closing DB", count)
}
}
@ -1239,7 +1239,7 @@ func TestPendingConnsAfterErr(t *testing.T) {
time.Sleep(10 * time.Millisecond) // make extra sure all workers are blocked
close(unblock) // let all workers proceed
const timeout = 100 * time.Millisecond
const timeout = 5 * time.Second
to := time.NewTimer(timeout)
defer to.Stop()
@ -1615,6 +1615,8 @@ func TestManyErrBadConn(t *testing.T) {
}
}()
db.mu.Lock()
defer db.mu.Unlock()
if db.numOpen != nconn {
t.Fatalf("unexpected numOpen %d (was expecting %d)", db.numOpen, nconn)
} else if len(db.freeConn) != nconn {

View File

@ -104,6 +104,41 @@ var fileTests = []fileTest{
{".debug_loc", 0x38, 0xf000, 0x200, 0x3a00, 0x0, 0x0, 0x0, 0x0, 0x42100000},
},
},
{
file: "testdata/gcc-386-mingw-no-symbols-exec",
hdr: FileHeader{0x14c, 0x8, 0x69676572, 0x0, 0x0, 0xe0, 0x30f},
opthdr: &OptionalHeader32{0x10b, 0x2, 0x18, 0xe00, 0x1e00, 0x200, 0x1280, 0x1000, 0x2000, 0x400000, 0x1000, 0x200, 0x4, 0x0, 0x1, 0x0, 0x4, 0x0, 0x0, 0x9000, 0x400, 0x5306, 0x3, 0x0, 0x200000, 0x1000, 0x100000, 0x1000, 0x0, 0x10,
[16]DataDirectory{
{0x0, 0x0},
{0x6000, 0x378},
{0x0, 0x0},
{0x0, 0x0},
{0x0, 0x0},
{0x0, 0x0},
{0x0, 0x0},
{0x0, 0x0},
{0x0, 0x0},
{0x8004, 0x18},
{0x0, 0x0},
{0x0, 0x0},
{0x60b8, 0x7c},
{0x0, 0x0},
{0x0, 0x0},
{0x0, 0x0},
},
},
sections: []*SectionHeader{
{".text", 0xc64, 0x1000, 0xe00, 0x400, 0x0, 0x0, 0x0, 0x0, 0x60500060},
{".data", 0x10, 0x2000, 0x200, 0x1200, 0x0, 0x0, 0x0, 0x0, 0xc0300040},
{".rdata", 0x134, 0x3000, 0x200, 0x1400, 0x0, 0x0, 0x0, 0x0, 0x40300040},
{".eh_fram", 0x3a0, 0x4000, 0x400, 0x1600, 0x0, 0x0, 0x0, 0x0, 0x40300040},
{".bss", 0x60, 0x5000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc0300080},
{".idata", 0x378, 0x6000, 0x400, 0x1a00, 0x0, 0x0, 0x0, 0x0, 0xc0300040},
{".CRT", 0x18, 0x7000, 0x200, 0x1e00, 0x0, 0x0, 0x0, 0x0, 0xc0300040},
{".tls", 0x20, 0x8000, 0x200, 0x2000, 0x0, 0x0, 0x0, 0x0, 0xc0300040},
},
hasNoDwarfInfo: true,
},
{
file: "testdata/gcc-amd64-mingw-obj",
hdr: FileHeader{0x8664, 0x6, 0x0, 0x198, 0x12, 0x0, 0x4},

View File

@ -24,6 +24,9 @@ type _StringTable []byte
func readStringTable(fh *FileHeader, r io.ReadSeeker) (_StringTable, error) {
// COFF string table is located right after COFF symbol table.
if fh.PointerToSymbolTable <= 0 {
return nil, nil
}
offset := fh.PointerToSymbolTable + COFFSymbolSize*fh.NumberOfSymbols
_, err := r.Seek(int64(offset), io.SeekStart)
if err != nil {

Binary file not shown.

View File

@ -645,10 +645,10 @@ func (dec *Decoder) decodeInterface(ityp reflect.Type, state *decoderState, valu
errorf("invalid type name length %d: exceeds input size", nr)
}
n := int(nr)
name := string(state.b.Bytes()[:n])
name := state.b.Bytes()[:n]
state.b.Drop(n)
// Allocate the destination interface value.
if name == "" {
if len(name) == 0 {
// Copy the nil interface value to the target.
value.Set(reflect.Zero(value.Type()))
return
@ -658,7 +658,7 @@ func (dec *Decoder) decodeInterface(ityp reflect.Type, state *decoderState, valu
}
// The concrete type must be registered.
registerLock.RLock()
typ, ok := nameToConcreteType[name]
typ, ok := nameToConcreteType[string(name)]
registerLock.RUnlock()
if !ok {
errorf("name not registered for interface: %q", name)

View File

@ -17,7 +17,8 @@ Basics
A stream of gobs is self-describing. Each data item in the stream is preceded by
a specification of its type, expressed in terms of a small set of predefined
types. Pointers are not transmitted, but the things they point to are
transmitted; that is, the values are flattened. Recursive types work fine, but
transmitted; that is, the values are flattened. Nil pointers are not permitted,
as they have no value. Recursive types work fine, but
recursive values (data with cycles) are problematic. This may change.
To use gobs, create an Encoder and present it with a series of data items as

View File

@ -170,6 +170,7 @@ func (enc *Encoder) sendType(w io.Writer, state *encoderState, origt reflect.Typ
// Encode transmits the data item represented by the empty interface value,
// guaranteeing that all necessary type information has been transmitted first.
// Passing a nil pointer to Encoder will panic, as they cannot be transmitted by gob.
func (enc *Encoder) Encode(e interface{}) error {
return enc.EncodeValue(reflect.ValueOf(e))
}
@ -212,9 +213,8 @@ func (enc *Encoder) sendTypeId(state *encoderState, ut *userTypeInfo) {
// EncodeValue transmits the data item represented by the reflection value,
// guaranteeing that all necessary type information has been transmitted first.
// Passing a nil pointer to EncodeValue will panic, as they cannot be transmitted by gob.
func (enc *Encoder) EncodeValue(value reflect.Value) error {
// Gobs contain values. They cannot represent nil pointers, which
// have no value to encode.
if value.Kind() == reflect.Ptr && value.IsNil() {
panic("gob: cannot encode nil pointer of type " + value.Type().String())
}

View File

@ -8,6 +8,7 @@ import (
"bytes"
"encoding/hex"
"fmt"
"io/ioutil"
"reflect"
"strings"
"testing"
@ -831,30 +832,81 @@ func TestPtrToMapOfMap(t *testing.T) {
// A top-level nil pointer generates a panic with a helpful string-valued message.
func TestTopLevelNilPointer(t *testing.T) {
errMsg := topLevelNilPanic(t)
if errMsg == "" {
var ip *int
encodeErr, panicErr := encodeAndRecover(ip)
if encodeErr != nil {
t.Fatal("error in encode:", encodeErr)
}
if panicErr == nil {
t.Fatal("top-level nil pointer did not panic")
}
errMsg := panicErr.Error()
if !strings.Contains(errMsg, "nil pointer") {
t.Fatal("expected nil pointer error, got:", errMsg)
}
}
func topLevelNilPanic(t *testing.T) (panicErr string) {
func encodeAndRecover(value interface{}) (encodeErr, panicErr error) {
defer func() {
e := recover()
if err, ok := e.(string); ok {
panicErr = err
if e != nil {
switch err := e.(type) {
case error:
panicErr = err
default:
panicErr = fmt.Errorf("%v", err)
}
}
}()
var ip *int
buf := new(bytes.Buffer)
if err := NewEncoder(buf).Encode(ip); err != nil {
t.Fatal("error in encode:", err)
}
encodeErr = NewEncoder(ioutil.Discard).Encode(value)
return
}
func TestNilPointerPanics(t *testing.T) {
var (
nilStringPtr *string
intMap = make(map[int]int)
intMapPtr = &intMap
nilIntMapPtr *map[int]int
zero int
nilBoolChannel chan bool
nilBoolChannelPtr *chan bool
nilStringSlice []string
stringSlice = make([]string, 1)
nilStringSlicePtr *[]string
)
testCases := []struct {
value interface{}
mustPanic bool
}{
{nilStringPtr, true},
{intMap, false},
{intMapPtr, false},
{nilIntMapPtr, true},
{zero, false},
{nilStringSlice, false},
{stringSlice, false},
{nilStringSlicePtr, true},
{nilBoolChannel, false},
{nilBoolChannelPtr, true},
}
for _, tt := range testCases {
_, panicErr := encodeAndRecover(tt.value)
if tt.mustPanic {
if panicErr == nil {
t.Errorf("expected panic with input %#v, did not panic", tt.value)
}
continue
}
if panicErr != nil {
t.Fatalf("expected no panic with input %#v, got panic=%v", tt.value, panicErr)
}
}
}
func TestNilPointerInsideInterface(t *testing.T) {
var ip *int
si := struct {

View File

@ -22,6 +22,7 @@ import (
"strconv"
"strings"
"sync"
"sync/atomic"
"unicode"
"unicode/utf8"
)
@ -1231,15 +1232,14 @@ func dominantField(fields []field) (field, bool) {
}
var fieldCache struct {
sync.RWMutex
m map[reflect.Type][]field
value atomic.Value // map[reflect.Type][]field
mu sync.Mutex // used only by writers
}
// cachedTypeFields is like typeFields but uses a cache to avoid repeated work.
func cachedTypeFields(t reflect.Type) []field {
fieldCache.RLock()
f := fieldCache.m[t]
fieldCache.RUnlock()
m, _ := fieldCache.value.Load().(map[reflect.Type][]field)
f := m[t]
if f != nil {
return f
}
@ -1251,11 +1251,14 @@ func cachedTypeFields(t reflect.Type) []field {
f = []field{}
}
fieldCache.Lock()
if fieldCache.m == nil {
fieldCache.m = map[reflect.Type][]field{}
fieldCache.mu.Lock()
m, _ = fieldCache.value.Load().(map[reflect.Type][]field)
newM := make(map[reflect.Type][]field, len(m)+1)
for k, v := range m {
newM[k] = v
}
fieldCache.m[t] = f
fieldCache.Unlock()
newM[t] = f
fieldCache.value.Store(newM)
fieldCache.mu.Unlock()
return f
}

View File

@ -33,7 +33,7 @@ const (
//
// The name for the XML elements is taken from, in order of preference:
// - the tag on the XMLName field, if the data is a struct
// - the value of the XMLName field of type xml.Name
// - the value of the XMLName field of type Name
// - the tag of the struct field used to obtain the data
// - the name of the struct field used to obtain the data
// - the name of the marshalled type

View File

@ -39,7 +39,7 @@ import (
// ",innerxml", Unmarshal accumulates the raw XML nested inside the
// element in that field. The rest of the rules still apply.
//
// * If the struct has a field named XMLName of type xml.Name,
// * If the struct has a field named XMLName of type Name,
// Unmarshal records the element name in that field.
//
// * If the XMLName field has an associated tag of the form
@ -105,8 +105,8 @@ import (
// interpreting the string value in decimal. There is no check for
// overflow.
//
// Unmarshal maps an XML element to an xml.Name by recording the
// element name.
// Unmarshal maps an XML element to a Name by recording the element
// name.
//
// Unmarshal maps an XML element to a pointer by setting the pointer
// to a freshly allocated value and then mapping the element to that value.
@ -115,13 +115,13 @@ func Unmarshal(data []byte, v interface{}) error {
return NewDecoder(bytes.NewReader(data)).Decode(v)
}
// Decode works like xml.Unmarshal, except it reads the decoder
// Decode works like Unmarshal, except it reads the decoder
// stream to find the start element.
func (d *Decoder) Decode(v interface{}) error {
return d.DecodeElement(v, nil)
}
// DecodeElement works like xml.Unmarshal except that it takes
// DecodeElement works like Unmarshal except that it takes
// a pointer to the start XML element to decode into v.
// It is useful when a client reads some raw XML tokens itself
// but also wants to defer to Unmarshal for some elements.

View File

@ -418,7 +418,7 @@ type (
)
// Pos and End implementations for expression/type nodes.
//
func (x *BadExpr) Pos() token.Pos { return x.From }
func (x *Ident) Pos() token.Pos { return x.NamePos }
func (x *Ellipsis) Pos() token.Pos { return x.Ellipsis }
@ -709,7 +709,7 @@ type (
)
// Pos and End implementations for statement nodes.
//
func (s *BadStmt) Pos() token.Pos { return s.From }
func (s *DeclStmt) Pos() token.Pos { return s.Decl.Pos() }
func (s *EmptyStmt) Pos() token.Pos { return s.Semicolon }
@ -854,7 +854,7 @@ type (
)
// Pos and End implementations for spec nodes.
//
func (s *ImportSpec) Pos() token.Pos {
if s.Name != nil {
return s.Name.Pos()
@ -931,7 +931,7 @@ type (
)
// Pos and End implementations for declaration nodes.
//
func (d *BadDecl) Pos() token.Pos { return d.From }
func (d *GenDecl) Pos() token.Pos { return d.TokPos }
func (d *FuncDecl) Pos() token.Pos { return d.Type.Pos() }

View File

@ -244,6 +244,7 @@ var stringTests = []struct {
{"1e9999", "1e+9999", "0x.f8d4a9da224650a8cb2959e10d985ad92adbd44c62917e608b1f24c0e1b76b6f61edffeb15c135a4b601637315f7662f325f82325422b244286a07663c9415d2p+33216"},
{"1e-9999", "1e-9999", "0x.83b01ba6d8c0425eec1b21e96f7742d63c2653ed0a024cf8a2f9686df578d7b07d7a83d84df6a2ec70a921d1f6cd5574893a7eda4d28ee719e13a5dce2700759p-33215"},
{"2.71828182845904523536028747135266249775724709369995957496696763", "2.71828", "271828182845904523536028747135266249775724709369995957496696763/100000000000000000000000000000000000000000000000000000000000000"},
{"0e9999999999", "0", "0"}, // issue #16176
// Complex
{"0i", "(0 + 0i)", "(0 + 0i)"},

View File

@ -21,6 +21,7 @@ type importer struct {
data []byte
path string
buf []byte // for reading strings
version string
// object lists
strList []string // in order of appearance
@ -66,8 +67,9 @@ func BImportData(imports map[string]*types.Package, data []byte, path string) (i
// --- generic export data ---
if v := p.string(); v != "v0" {
return p.read, nil, fmt.Errorf("unknown export data version: %s", v)
p.version = p.string()
if p.version != "v0" && p.version != "v1" {
return p.read, nil, fmt.Errorf("unknown export data version: %s", p.version)
}
// populate typList with predeclared "known" types
@ -304,6 +306,10 @@ func (p *importer) typ(parent *types.Package) types.Type {
params, isddd := p.paramList()
result, _ := p.paramList()
if p.version == "v1" {
p.int() // nointerface flag - discarded
}
sig := types.NewSignature(recv.At(0), params, result, isddd)
t0.AddMethod(types.NewFunc(token.NoPos, parent, name, sig))
}

View File

@ -166,7 +166,7 @@ that would have been produced if {{.}} was a regular string.
Security Model
http://js-quasis-libraries-and-repl.googlecode.com/svn/trunk/safetemplate.html#problem_definition defines "safe" as used by this package.
https://rawgit.com/mikesamuel/sanitized-jquery-templates/trunk/safetemplate.html#problem_definition defines "safe" as used by this package.
This package assumes that template authors are trusted, that Execute's data
parameter is not, and seeks to preserve the properties below in the face

View File

@ -60,21 +60,34 @@ const (
// Parse parses, post-processes and verifies the trace.
func Parse(r io.Reader, bin string) ([]*Event, error) {
ver, rawEvents, strings, err := readTrace(r)
ver, events, err := parse(r, bin)
if err != nil {
return nil, err
}
if ver < 1007 && bin == "" {
return nil, fmt.Errorf("for traces produced by go 1.6 or below, the binary argument must be provided")
}
return events, nil
}
// parse parses, post-processes and verifies the trace. It returns the
// trace version and the list of events.
func parse(r io.Reader, bin string) (int, []*Event, error) {
ver, rawEvents, strings, err := readTrace(r)
if err != nil {
return 0, nil, err
}
events, stacks, err := parseEvents(ver, rawEvents, strings)
if err != nil {
return nil, err
return 0, nil, err
}
events, err = removeFutile(events)
if err != nil {
return nil, err
return 0, nil, err
}
err = postProcessTrace(ver, events)
if err != nil {
return nil, err
return 0, nil, err
}
// Attach stack traces.
for _, ev := range events {
@ -84,10 +97,10 @@ func Parse(r io.Reader, bin string) ([]*Event, error) {
}
if ver < 1007 && bin != "" {
if err := symbolize(events, bin); err != nil {
return nil, err
return 0, nil, err
}
}
return events, nil
return ver, events, nil
}
// rawEvent is a helper type used during parsing.

View File

@ -42,7 +42,9 @@ func TestParseCanned(t *testing.T) {
if err != nil {
t.Fatalf("failed to read input file: %v", err)
}
_, err = Parse(bytes.NewReader(data), "")
// Instead of Parse that requires a proper binary name for old traces,
// we use 'parse' that omits symbol lookup if an empty string is given.
_, _, err = parse(bytes.NewReader(data), "")
switch {
case strings.HasSuffix(f.Name(), "_good"):
if err != nil {

View File

@ -88,6 +88,12 @@ func (z *Rat) SetString(s string) (*Rat, bool) {
return nil, false
}
// special-case 0 (see also issue #16176)
if len(z.a.abs) == 0 {
return z, true
}
// len(z.a.abs) > 0
// correct exponent
if ecorr < 0 {
exp += int64(ecorr)

View File

@ -48,6 +48,7 @@ var setStringTests = []StringTest{
{"53/70893980658822810696", "53/70893980658822810696", true},
{"106/141787961317645621392", "53/70893980658822810696", true},
{"204211327800791583.81095", "4084226556015831676219/20000", true},
{"0e9999999999", "0", true}, // issue #16176
{in: "1/0"},
}

View File

@ -0,0 +1,47 @@
// Copyright 2016 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 rand
import (
"sync"
"testing"
)
// TestConcurrent exercises the rand API concurrently, triggering situations
// where the race detector is likely to detect issues.
func TestConcurrent(t *testing.T) {
const (
numRoutines = 10
numCycles = 10
)
var wg sync.WaitGroup
defer wg.Wait()
wg.Add(numRoutines)
for i := 0; i < numRoutines; i++ {
go func(i int) {
defer wg.Done()
buf := make([]byte, 997)
for j := 0; j < numCycles; j++ {
var seed int64
seed += int64(ExpFloat64())
seed += int64(Float32())
seed += int64(Float64())
seed += int64(Intn(Int()))
seed += int64(Int31n(Int31()))
seed += int64(Int63n(Int63()))
seed += int64(NormFloat64())
seed += int64(Uint32())
for _, p := range Perm(10) {
seed += int64(p)
}
Read(buf)
for _, b := range buf {
seed += int64(b)
}
Seed(int64(i*j) * seed)
}
}(i)
}
}

View File

@ -33,14 +33,32 @@ func NewSource(seed int64) Source {
// A Rand is a source of random numbers.
type Rand struct {
src Source
// readVal contains remainder of 63-bit integer used for bytes
// generation during most recent Read call.
// It is saved so next Read call can start where the previous
// one finished.
readVal int64
// readPos indicates the number of low-order bytes of readVal
// that are still valid.
readPos int8
}
// New returns a new Rand that uses random values from src
// to generate other random values.
func New(src Source) *Rand { return &Rand{src} }
func New(src Source) *Rand { return &Rand{src: src} }
// Seed uses the provided seed value to initialize the generator to a deterministic state.
func (r *Rand) Seed(seed int64) { r.src.Seed(seed) }
// Seed should not be called concurrently with any other Rand method.
func (r *Rand) Seed(seed int64) {
if lk, ok := r.src.(*lockedSource); ok {
lk.seedPos(seed, &r.readPos)
return
}
r.src.Seed(seed)
r.readPos = 0
}
// Int63 returns a non-negative pseudo-random 63-bit integer as an int64.
func (r *Rand) Int63() int64 { return r.src.Int63() }
@ -160,15 +178,29 @@ func (r *Rand) Perm(n int) []int {
// Read generates len(p) random bytes and writes them into p. It
// always returns len(p) and a nil error.
// Read should not be called concurrently with any other Rand method.
func (r *Rand) Read(p []byte) (n int, err error) {
for i := 0; i < len(p); i += 7 {
val := r.src.Int63()
for j := 0; i+j < len(p) && j < 7; j++ {
p[i+j] = byte(val)
val >>= 8
}
if lk, ok := r.src.(*lockedSource); ok {
return lk.read(p, &r.readVal, &r.readPos)
}
return len(p), nil
return read(p, r.Int63, &r.readVal, &r.readPos)
}
func read(p []byte, int63 func() int64, readVal *int64, readPos *int8) (n int, err error) {
pos := *readPos
val := *readVal
for n = 0; n < len(p); n++ {
if pos == 0 {
val = int63()
pos = 7
}
p[n] = byte(val)
val >>= 8
pos--
}
*readPos = pos
*readVal = val
return
}
/*
@ -179,8 +211,9 @@ var globalRand = New(&lockedSource{src: NewSource(1)})
// Seed uses the provided seed value to initialize the default Source to a
// deterministic state. If Seed is not called, the generator behaves as
// if seeded by Seed(1). Only uses the bottom 31 bits of seed; the top 33
// bits are ignored.
// if seeded by Seed(1). Seed values that have the same remainder when
// divided by 2^31-1 generate the same pseudo-random sequence.
// Seed, unlike the Rand.Seed method, is safe for concurrent use.
func Seed(seed int64) { globalRand.Seed(seed) }
// Int63 returns a non-negative pseudo-random 63-bit integer as an int64
@ -227,6 +260,7 @@ func Perm(n int) []int { return globalRand.Perm(n) }
// Read generates len(p) random bytes from the default Source and
// writes them into p. It always returns len(p) and a nil error.
// Read, unlike the Rand.Read method, is safe for concurrent use.
func Read(p []byte) (n int, err error) { return globalRand.Read(p) }
// NormFloat64 returns a normally distributed float64 in the range
@ -267,3 +301,19 @@ func (r *lockedSource) Seed(seed int64) {
r.src.Seed(seed)
r.lk.Unlock()
}
// seedPos implements Seed for a lockedSource without a race condiiton.
func (r *lockedSource) seedPos(seed int64, readPos *int8) {
r.lk.Lock()
r.src.Seed(seed)
*readPos = 0
r.lk.Unlock()
}
// read implements Read for a lockedSource without a race condition.
func (r *lockedSource) read(p []byte, readVal *int64, readPos *int8) (n int, err error) {
r.lk.Lock()
n, err = read(p, r.src.Int63, readVal, readPos)
r.lk.Unlock()
return
}

View File

@ -5,13 +5,16 @@
package rand
import (
"bytes"
"errors"
"fmt"
"internal/testenv"
"io"
"math"
"os"
"runtime"
"testing"
"testing/iotest"
)
const (
@ -373,7 +376,7 @@ func testReadUniformity(t *testing.T, n int, seed int64) {
checkSampleDistribution(t, samples, expected)
}
func TestRead(t *testing.T) {
func TestReadUniformity(t *testing.T) {
testBufferSizes := []int{
2, 4, 7, 64, 1024, 1 << 16, 1 << 20,
}
@ -394,7 +397,42 @@ func TestReadEmpty(t *testing.T) {
if n != 0 {
t.Errorf("Read into empty buffer returned unexpected n of %d", n)
}
}
func TestReadByOneByte(t *testing.T) {
r := New(NewSource(1))
b1 := make([]byte, 100)
_, err := io.ReadFull(iotest.OneByteReader(r), b1)
if err != nil {
t.Errorf("read by one byte: %v", err)
}
r = New(NewSource(1))
b2 := make([]byte, 100)
_, err = r.Read(b2)
if err != nil {
t.Errorf("read: %v", err)
}
if !bytes.Equal(b1, b2) {
t.Errorf("read by one byte vs single read:\n%x\n%x", b1, b2)
}
}
func TestReadSeedReset(t *testing.T) {
r := New(NewSource(42))
b1 := make([]byte, 128)
_, err := r.Read(b1)
if err != nil {
t.Errorf("read: %v", err)
}
r.Seed(42)
b2 := make([]byte, 128)
_, err = r.Read(b2)
if err != nil {
t.Errorf("read: %v", err)
}
if !bytes.Equal(b1, b2) {
t.Errorf("mismatch after re-seed:\n%x\n%x", b1, b2)
}
}
// Benchmarks

View File

@ -342,25 +342,25 @@ var regressGolden = []interface{}{
[]int{8, 7, 5, 3, 4, 6, 0, 1, 2}, // Perm(9)
[]int{1, 0, 2, 5, 7, 6, 9, 8, 3, 4}, // Perm(10)
[]byte{0x1}, // Read([0])
[]byte{0xc0, 0x41, 0xd3, 0xff, 0x12, 0x4, 0x5b}, // Read([0 0 0 0 0 0 0])
[]byte{0x73, 0xc8, 0x6e, 0x4f, 0xf9, 0x5f, 0xf6, 0x62}, // Read([0 0 0 0 0 0 0 0])
[]byte{0x4a, 0x2d, 0xb, 0x75, 0xfb, 0x18, 0xd, 0xaf, 0x48}, // Read([0 0 0 0 0 0 0 0 0])
[]byte{0x39, 0x46, 0x51, 0x85, 0xf, 0xd4, 0xa1, 0x78, 0x89, 0x2e}, // Read([0 0 0 0 0 0 0 0 0 0])
[]byte{0x51}, // Read([0])
[]byte{0x4e, 0xe2, 0xd3, 0xd0, 0xd0, 0xde, 0x6b}, // Read([0 0 0 0 0 0 0])
[]byte{0xf8, 0xf9, 0xb4, 0x4c, 0xe8, 0x5f, 0xf0, 0x44}, // Read([0 0 0 0 0 0 0 0])
[]byte{0x3b, 0xbf, 0x85, 0x7a, 0xab, 0x99, 0xc5, 0xb2, 0x52}, // Read([0 0 0 0 0 0 0 0 0])
[]byte{0xa8, 0xae, 0xb7, 0x9e, 0xf8, 0x56, 0xf6, 0x59, 0xc1, 0x8f}, // Read([0 0 0 0 0 0 0 0 0 0])
[]byte{0xc7}, // Read([0])
[]byte{0x5f, 0x67, 0xcf, 0xe2, 0x42, 0xcf, 0x3c}, // Read([0 0 0 0 0 0 0])
[]byte{0xc3, 0x54, 0xf3, 0xed, 0xe2, 0xd6, 0xbe, 0xcc}, // Read([0 0 0 0 0 0 0 0])
[]byte{0x6a, 0x9f, 0x4a, 0x57, 0x8b, 0xcb, 0x9e, 0xf2, 0xd4}, // Read([0 0 0 0 0 0 0 0 0])
[]byte{0x6d, 0x29, 0x97, 0x61, 0xea, 0x9e, 0x4f, 0x5a, 0xa6, 0xae}, // Read([0 0 0 0 0 0 0 0 0 0])
[]byte{0xaa}, // Read([0])
[]byte{0x20, 0xef, 0xcd, 0x6c, 0xea, 0x84, 0xb6}, // Read([0 0 0 0 0 0 0])
[]byte{0x92, 0x5e, 0x60, 0x7b, 0xe0, 0x63, 0x71, 0x6f}, // Read([0 0 0 0 0 0 0 0])
[]byte{0x4, 0x5c, 0x3f, 0x0, 0xf, 0x8a, 0x79, 0x6b, 0xce}, // Read([0 0 0 0 0 0 0 0 0])
[]byte{0xaa, 0xca, 0xee, 0xdf, 0xad, 0x5b, 0x50, 0x66, 0x64, 0xe8}, // Read([0 0 0 0 0 0 0 0 0 0])
[]byte{0x94, 0xfd, 0xc2, 0xfa, 0x2f, 0xfc, 0xc0}, // Read([0 0 0 0 0 0 0])
[]byte{0x41, 0xd3, 0xff, 0x12, 0x4, 0x5b, 0x73, 0xc8}, // Read([0 0 0 0 0 0 0 0])
[]byte{0x6e, 0x4f, 0xf9, 0x5f, 0xf6, 0x62, 0xa5, 0xee, 0xe8}, // Read([0 0 0 0 0 0 0 0 0])
[]byte{0x2a, 0xbd, 0xf4, 0x4a, 0x2d, 0xb, 0x75, 0xfb, 0x18, 0xd}, // Read([0 0 0 0 0 0 0 0 0 0])
[]byte{0xaf}, // Read([0])
[]byte{0x48, 0xa7, 0x9e, 0xe0, 0xb1, 0xd, 0x39}, // Read([0 0 0 0 0 0 0])
[]byte{0x46, 0x51, 0x85, 0xf, 0xd4, 0xa1, 0x78, 0x89}, // Read([0 0 0 0 0 0 0 0])
[]byte{0x2e, 0xe2, 0x85, 0xec, 0xe1, 0x51, 0x14, 0x55, 0x78}, // Read([0 0 0 0 0 0 0 0 0])
[]byte{0x8, 0x75, 0xd6, 0x4e, 0xe2, 0xd3, 0xd0, 0xd0, 0xde, 0x6b}, // Read([0 0 0 0 0 0 0 0 0 0])
[]byte{0xf8}, // Read([0])
[]byte{0xf9, 0xb4, 0x4c, 0xe8, 0x5f, 0xf0, 0x44}, // Read([0 0 0 0 0 0 0])
[]byte{0xc6, 0xb1, 0xf8, 0x3b, 0x8e, 0x88, 0x3b, 0xbf}, // Read([0 0 0 0 0 0 0 0])
[]byte{0x85, 0x7a, 0xab, 0x99, 0xc5, 0xb2, 0x52, 0xc7, 0x42}, // Read([0 0 0 0 0 0 0 0 0])
[]byte{0x9c, 0x32, 0xf3, 0xa8, 0xae, 0xb7, 0x9e, 0xf8, 0x56, 0xf6}, // Read([0 0 0 0 0 0 0 0 0 0])
[]byte{0x59}, // Read([0])
[]byte{0xc1, 0x8f, 0xd, 0xce, 0xcc, 0x77, 0xc7}, // Read([0 0 0 0 0 0 0])
[]byte{0x5e, 0x7a, 0x81, 0xbf, 0xde, 0x27, 0x5f, 0x67}, // Read([0 0 0 0 0 0 0 0])
[]byte{0xcf, 0xe2, 0x42, 0xcf, 0x3c, 0xc3, 0x54, 0xf3, 0xed}, // Read([0 0 0 0 0 0 0 0 0])
[]byte{0xe2, 0xd6, 0xbe, 0xcc, 0x4e, 0xa3, 0xae, 0x5e, 0x88, 0x52}, // Read([0 0 0 0 0 0 0 0 0 0])
uint32(4059586549), // Uint32()
uint32(1052117029), // Uint32()
uint32(2817310706), // Uint32()

View File

@ -972,7 +972,7 @@ func http2terminalReadFrameError(err error) bool {
//
// If the frame is larger than previously set with SetMaxReadFrameSize, the
// returned error is ErrFrameTooLarge. Other errors may be of type
// ConnectionError, StreamError, or anything else from from the underlying
// ConnectionError, StreamError, or anything else from the underlying
// reader.
func (fr *http2Framer) ReadFrame() (http2Frame, error) {
fr.errDetail = nil
@ -1992,6 +1992,29 @@ func http2transportExpectContinueTimeout(t1 *Transport) time.Duration {
return t1.ExpectContinueTimeout
}
// isBadCipher reports whether the cipher is blacklisted by the HTTP/2 spec.
func http2isBadCipher(cipher uint16) bool {
switch cipher {
case tls.TLS_RSA_WITH_RC4_128_SHA,
tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA,
tls.TLS_RSA_WITH_AES_128_CBC_SHA,
tls.TLS_RSA_WITH_AES_256_CBC_SHA,
tls.TLS_RSA_WITH_AES_128_GCM_SHA256,
tls.TLS_RSA_WITH_AES_256_GCM_SHA384,
tls.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
tls.TLS_ECDHE_RSA_WITH_RC4_128_SHA,
tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:
return true
default:
return false
}
}
type http2contextContext interface {
context.Context
}
@ -2999,27 +3022,6 @@ func (s *http2Server) ServeConn(c net.Conn, opts *http2ServeConnOpts) {
sc.serve()
}
// isBadCipher reports whether the cipher is blacklisted by the HTTP/2 spec.
func http2isBadCipher(cipher uint16) bool {
switch cipher {
case tls.TLS_RSA_WITH_RC4_128_SHA,
tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA,
tls.TLS_RSA_WITH_AES_128_CBC_SHA,
tls.TLS_RSA_WITH_AES_256_CBC_SHA,
tls.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
tls.TLS_ECDHE_RSA_WITH_RC4_128_SHA,
tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:
return true
default:
return false
}
}
func (sc *http2serverConn) rejectConn(err http2ErrCode, debug string) {
sc.vlogf("http2: server rejecting conn: %v, %s", err, debug)
@ -4931,6 +4933,7 @@ type http2ClientConn struct {
inflow http2flow // peer's conn-level flow control
closed bool
goAway *http2GoAwayFrame // if non-nil, the GoAwayFrame we received
goAwayDebug string // goAway frame's debug data, retained as a string
streams map[uint32]*http2clientStream // client-initiated
nextStreamID uint32
bw *bufio.Writer
@ -5266,7 +5269,16 @@ func (t *http2Transport) NewClientConn(c net.Conn) (*http2ClientConn, error) {
func (cc *http2ClientConn) setGoAway(f *http2GoAwayFrame) {
cc.mu.Lock()
defer cc.mu.Unlock()
old := cc.goAway
cc.goAway = f
if cc.goAwayDebug == "" {
cc.goAwayDebug = string(f.DebugData())
}
if old != nil && old.ErrCode != http2ErrCodeNo {
cc.goAway.ErrCode = old.ErrCode
}
}
func (cc *http2ClientConn) CanTakeNewRequest() bool {
@ -5871,6 +5883,19 @@ func (cc *http2ClientConn) readLoop() {
}
}
// GoAwayError is returned by the Transport when the server closes the
// TCP connection after sending a GOAWAY frame.
type http2GoAwayError struct {
LastStreamID uint32
ErrCode http2ErrCode
DebugData string
}
func (e http2GoAwayError) Error() string {
return fmt.Sprintf("http2: server sent GOAWAY and closed the connection; LastStreamID=%v, ErrCode=%v, debug=%q",
e.LastStreamID, e.ErrCode, e.DebugData)
}
func (rl *http2clientConnReadLoop) cleanup() {
cc := rl.cc
defer cc.tconn.Close()
@ -5878,10 +5903,18 @@ func (rl *http2clientConnReadLoop) cleanup() {
defer close(cc.readerDone)
err := cc.readerErr
if err == io.EOF {
err = io.ErrUnexpectedEOF
}
cc.mu.Lock()
if err == io.EOF {
if cc.goAway != nil {
err = http2GoAwayError{
LastStreamID: cc.goAway.LastStreamID,
ErrCode: cc.goAway.ErrCode,
DebugData: cc.goAwayDebug,
}
} else {
err = io.ErrUnexpectedEOF
}
}
for _, cs := range rl.activeRes {
cs.bufPipe.CloseWithError(err)
}

View File

@ -17,11 +17,7 @@ func ExampleResponseRecorder() {
http.Error(w, "something failed", http.StatusInternalServerError)
}
req, err := http.NewRequest("GET", "http://example.com/foo", nil)
if err != nil {
log.Fatal(err)
}
req := httptest.NewRequest("GET", "http://example.com/foo", nil)
w := httptest.NewRecorder()
handler(w, req)

View File

@ -4,8 +4,6 @@
// Package pprof serves via its HTTP server runtime profiling data
// in the format expected by the pprof visualization tool.
// For more information about pprof, see
// http://code.google.com/p/google-perftools/.
//
// The package is typically only imported for the side effect of
// registering its HTTP handlers.

View File

@ -213,7 +213,7 @@ func (r *Response) ProtoAtLeast(major, minor int) bool {
r.ProtoMajor == major && r.ProtoMinor >= minor
}
// Write writes r to w in the HTTP/1.n server response format,
// Write writes r to w in the HTTP/1.x server response format,
// including the status line, headers, body, and optional trailer.
//
// This method consults the following fields of the response r:

View File

@ -9,6 +9,7 @@ package http_test
import (
"bufio"
"bytes"
"compress/gzip"
"context"
"crypto/tls"
"encoding/json"
@ -1106,11 +1107,44 @@ func TestTLSServer(t *testing.T) {
})
}
func TestAutomaticHTTP2_Serve(t *testing.T) {
// Issue 15908
func TestAutomaticHTTP2_Serve_NoTLSConfig(t *testing.T) {
testAutomaticHTTP2_Serve(t, nil, true)
}
func TestAutomaticHTTP2_Serve_NonH2TLSConfig(t *testing.T) {
testAutomaticHTTP2_Serve(t, &tls.Config{}, false)
}
func TestAutomaticHTTP2_Serve_H2TLSConfig(t *testing.T) {
testAutomaticHTTP2_Serve(t, &tls.Config{NextProtos: []string{"h2"}}, true)
}
func testAutomaticHTTP2_Serve(t *testing.T, tlsConf *tls.Config, wantH2 bool) {
defer afterTest(t)
ln := newLocalListener(t)
ln.Close() // immediately (not a defer!)
var s Server
s.TLSConfig = tlsConf
if err := s.Serve(ln); err == nil {
t.Fatal("expected an error")
}
gotH2 := s.TLSNextProto["h2"] != nil
if gotH2 != wantH2 {
t.Errorf("http2 configured = %v; want %v", gotH2, wantH2)
}
}
func TestAutomaticHTTP2_Serve_WithTLSConfig(t *testing.T) {
defer afterTest(t)
ln := newLocalListener(t)
ln.Close() // immediately (not a defer!)
var s Server
// Set the TLSConfig. In reality, this would be the
// *tls.Config given to tls.NewListener.
s.TLSConfig = &tls.Config{
NextProtos: []string{"h2"},
}
if err := s.Serve(ln); err == nil {
t.Fatal("expected an error")
}
@ -3957,6 +3991,8 @@ func TestServerValidatesHostHeader(t *testing.T) {
host string
want int
}{
{"HTTP/0.9", "", 400},
{"HTTP/1.1", "", 400},
{"HTTP/1.1", "Host: \r\n", 200},
{"HTTP/1.1", "Host: 1.2.3.4\r\n", 200},
@ -3982,6 +4018,11 @@ func TestServerValidatesHostHeader(t *testing.T) {
// Make an exception for HTTP upgrade requests:
{"PRI * HTTP/2.0", "", 200},
// But not other HTTP/2 stuff:
{"PRI / HTTP/2.0", "", 400},
{"GET / HTTP/2.0", "", 400},
{"GET / HTTP/3.0", "", 400},
}
for _, tt := range tests {
conn := &testConn{closec: make(chan bool, 1)}
@ -4200,6 +4241,24 @@ func TestHandlerSetTransferEncodingChunked(t *testing.T) {
}
}
// https://golang.org/issue/16063
func TestHandlerSetTransferEncodingGzip(t *testing.T) {
defer afterTest(t)
ht := newHandlerTest(HandlerFunc(func(w ResponseWriter, r *Request) {
w.Header().Set("Transfer-Encoding", "gzip")
gz := gzip.NewWriter(w)
gz.Write([]byte("hello"))
gz.Close()
}))
resp := ht.rawResponse("GET / HTTP/1.1\nHost: foo")
for _, v := range []string{"gzip", "chunked"} {
hdr := "Transfer-Encoding: " + v
if n := strings.Count(resp, hdr); n != 1 {
t.Errorf("want 1 occurrence of %q in response, got %v\nresponse: %v", hdr, n, resp)
}
}
}
func BenchmarkClientServer(b *testing.B) {
b.ReportAllocs()
b.StopTimer()

View File

@ -771,8 +771,9 @@ func (c *conn) readRequest(ctx context.Context) (w *response, err error) {
return nil, err
}
ctx, cancelCtx := context.WithCancel(ctx)
req.ctx = ctx
if !http1ServerSupportsRequest(req) {
return nil, badRequestError("unsupported protocol version")
}
c.lastMethod = req.Method
c.r.setInfiniteReadLimit()
@ -800,6 +801,8 @@ func (c *conn) readRequest(ctx context.Context) (w *response, err error) {
}
delete(req.Header, "Host")
ctx, cancelCtx := context.WithCancel(ctx)
req.ctx = ctx
req.RemoteAddr = c.remoteAddr
req.TLS = c.tlsState
if body, ok := req.Body.(*body); ok {
@ -828,6 +831,23 @@ func (c *conn) readRequest(ctx context.Context) (w *response, err error) {
return w, nil
}
// http1ServerSupportsRequest reports whether Go's HTTP/1.x server
// supports the given request.
func http1ServerSupportsRequest(req *Request) bool {
if req.ProtoMajor == 1 {
return true
}
// Accept "PRI * HTTP/2.0" upgrade requests, so Handlers can
// wire up their own HTTP/2 upgrades.
if req.ProtoMajor == 2 && req.ProtoMinor == 0 &&
req.Method == "PRI" && req.RequestURI == "*" {
return true
}
// Reject HTTP/0.x, and all other HTTP/2+ requests (which
// aren't encoded in ASCII anyway).
return false
}
func (w *response) Header() Header {
if w.cw.header == nil && w.wroteHeader && !w.cw.wroteHeader {
// Accessing the header between logically writing it
@ -1147,7 +1167,10 @@ func (cw *chunkWriter) writeHeader(p []byte) {
// to avoid closing the connection at EOF.
cw.chunking = true
setHeader.transferEncoding = "chunked"
delHeader("Transfer-Encoding")
if hasTE && te == "chunked" {
// We will send the chunked Transfer-Encoding header later.
delHeader("Transfer-Encoding")
}
}
} else {
// HTTP version < 1.1: cannot do chunked transfer
@ -2198,9 +2221,37 @@ func (srv *Server) ListenAndServe() error {
var testHookServerServe func(*Server, net.Listener) // used if non-nil
// shouldDoServeHTTP2 reports whether Server.Serve should configure
// automatic HTTP/2. (which sets up the srv.TLSNextProto map)
func (srv *Server) shouldConfigureHTTP2ForServe() bool {
if srv.TLSConfig == nil {
// Compatibility with Go 1.6:
// If there's no TLSConfig, it's possible that the user just
// didn't set it on the http.Server, but did pass it to
// tls.NewListener and passed that listener to Serve.
// So we should configure HTTP/2 (to set up srv.TLSNextProto)
// in case the listener returns an "h2" *tls.Conn.
return true
}
// The user specified a TLSConfig on their http.Server.
// In this, case, only configure HTTP/2 if their tls.Config
// explicitly mentions "h2". Otherwise http2.ConfigureServer
// would modify the tls.Config to add it, but they probably already
// passed this tls.Config to tls.NewListener. And if they did,
// it's too late anyway to fix it. It would only be potentially racy.
// See Issue 15908.
return strSliceContains(srv.TLSConfig.NextProtos, http2NextProtoTLS)
}
// Serve accepts incoming connections on the Listener l, creating a
// new service goroutine for each. The service goroutines read requests and
// then call srv.Handler to reply to them.
//
// For HTTP/2 support, srv.TLSConfig should be initialized to the
// provided listener's TLS Config before calling Serve. If
// srv.TLSConfig is non-nil and doesn't include the string "h2" in
// Config.NextProtos, HTTP/2 support is not enabled.
//
// Serve always returns a non-nil error.
func (srv *Server) Serve(l net.Listener) error {
defer l.Close()
@ -2208,9 +2259,13 @@ func (srv *Server) Serve(l net.Listener) error {
fn(srv, l)
}
var tempDelay time.Duration // how long to sleep on accept failure
if err := srv.setupHTTP2(); err != nil {
return err
if srv.shouldConfigureHTTP2ForServe() {
if err := srv.setupHTTP2(); err != nil {
return err
}
}
// TODO: allow changing base context? can't imagine concrete
// use cases yet.
baseCtx := context.Background()

View File

@ -845,10 +845,26 @@ func (t *Transport) getConn(treq *transportRequest, cm connectMethod) (*persistC
select {
case v := <-dialc:
// Our dial finished.
if trace != nil && trace.GotConn != nil && v.pc != nil && v.pc.alt == nil {
trace.GotConn(httptrace.GotConnInfo{Conn: v.pc.conn})
if v.pc != nil {
if trace != nil && trace.GotConn != nil && v.pc.alt == nil {
trace.GotConn(httptrace.GotConnInfo{Conn: v.pc.conn})
}
return v.pc, nil
}
return v.pc, v.err
// Our dial failed. See why to return a nicer error
// value.
select {
case <-req.Cancel:
case <-req.Context().Done():
case <-cancelc:
default:
// It wasn't an error due to cancelation, so
// return the original error message:
return nil, v.err
}
// It was an error due to cancelation, so prioritize that
// error value. (Issue 16049)
return nil, errRequestCanceledConn
case pc := <-idleConnCh:
// Another request finished first and its net.Conn
// became available before our dial. Or somebody

View File

@ -453,6 +453,10 @@ func TestLookupDotsWithLocalSource(t *testing.T) {
t.Skip("IPv4 is required")
}
if testenv.Builder() == "" {
testenv.MustHaveExternalNetwork(t)
}
for i, fn := range []func() func(){forceGoDNS, forceCgoDNS} {
fixup := fn()
if fixup == nil {

View File

@ -111,6 +111,7 @@ type Cmd struct {
closeAfterWait []io.Closer
goroutine []func() error
errch chan error // one send per goroutine
waitDone chan struct{}
}
// Command returns the Cmd struct to execute the named program with
@ -326,6 +327,15 @@ func (c *Cmd) Start() error {
if c.Process != nil {
return errors.New("exec: already started")
}
if c.ctx != nil {
select {
case <-c.ctx.Done():
c.closeDescriptors(c.closeAfterStart)
c.closeDescriptors(c.closeAfterWait)
return c.ctx.Err()
default:
}
}
type F func(*Cmd) (*os.File, error)
for _, setupFd := range []F{(*Cmd).stdin, (*Cmd).stdout, (*Cmd).stderr} {
@ -361,6 +371,17 @@ func (c *Cmd) Start() error {
}(fn)
}
if c.ctx != nil {
c.waitDone = make(chan struct{})
go func() {
select {
case <-c.ctx.Done():
c.Process.Kill()
case <-c.waitDone:
}
}()
}
return nil
}
@ -410,20 +431,9 @@ func (c *Cmd) Wait() error {
}
c.finished = true
var waitDone chan struct{}
if c.ctx != nil {
waitDone = make(chan struct{})
go func() {
select {
case <-c.ctx.Done():
c.Process.Kill()
case <-waitDone:
}
}()
}
state, err := c.Process.Wait()
if waitDone != nil {
close(waitDone)
if c.waitDone != nil {
close(c.waitDone)
}
c.ProcessState = state

Some files were not shown because too many files have changed in this diff Show More