diff --git a/go.mod b/go.mod index 9ec6be224c..32bb38f913 100644 --- a/go.mod +++ b/go.mod @@ -72,7 +72,7 @@ require ( github.com/charmbracelet/bubbles v0.18.0 github.com/charmbracelet/bubbletea v0.25.0 github.com/charmbracelet/lipgloss v0.9.1 - github.com/go-git/go-git/v5 v5.13.1 + github.com/go-git/go-git/v5 v5.16.5 github.com/gowebpki/jcs v1.0.1 github.com/mark3labs/mcp-go v0.33.0 github.com/mholt/archives v0.1.5 @@ -82,8 +82,8 @@ require ( require ( dario.cat/mergo v1.0.0 // indirect github.com/ActiveState/pty v0.0.0-20230628221854-6fb90eb08a14 // indirect - github.com/Microsoft/go-winio v0.6.1 // indirect - github.com/ProtonMail/go-crypto v1.1.3 // indirect + github.com/Microsoft/go-winio v0.6.2 // indirect + github.com/ProtonMail/go-crypto v1.1.6 // indirect github.com/STARRY-S/zip v0.2.3 // indirect github.com/andybalholm/brotli v1.2.0 // indirect github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.11 // indirect @@ -107,10 +107,10 @@ require ( github.com/bodgit/windows v1.0.1 // indirect github.com/cloudflare/circl v1.6.1 // indirect github.com/containerd/console v1.0.4-0.20230313162750-1ae8d489ac81 // indirect - github.com/cyphar/filepath-securejoin v0.3.6 // indirect + github.com/cyphar/filepath-securejoin v0.4.1 // indirect github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect - github.com/go-git/go-billy/v5 v5.6.1 // indirect - github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect + github.com/go-git/go-billy/v5 v5.6.2 // indirect + github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect github.com/hinshun/vt10x v0.0.0-20220301184237-5011da428d02 // indirect github.com/klauspost/compress v1.18.0 // indirect @@ -127,9 +127,9 @@ require ( github.com/muesli/termenv v0.15.2 // indirect github.com/nwaples/rardecode/v2 v2.2.0 // indirect github.com/pierrec/lz4/v4 v4.1.22 // indirect - github.com/pjbgf/sha1cd v0.3.0 // indirect + github.com/pjbgf/sha1cd v0.3.2 // indirect github.com/shoenig/go-m1cpu v0.1.6 // indirect - github.com/skeema/knownhosts v1.3.0 // indirect + github.com/skeema/knownhosts v1.3.1 // indirect github.com/sorairolake/lzip-go v0.3.8 // indirect github.com/sosodev/duration v1.3.1 // indirect github.com/spf13/afero v1.15.0 // indirect diff --git a/go.sum b/go.sum index 44e702c1de..aec23388d2 100644 --- a/go.sum +++ b/go.sum @@ -34,15 +34,15 @@ github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8 github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= -github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= -github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= +github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= +github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8/go.mod h1:oX5x61PbNXchhh0oikYAH+4Pcfw5LKv21+Jnpr6r6Pc= github.com/Netflix/go-expect v0.0.0-20201125194554-85d881c3777e h1:YYUPbL3iB9+Y/JYEXjCi9AolqiKIIJX/2aRR9TuKD6w= github.com/Netflix/go-expect v0.0.0-20201125194554-85d881c3777e/go.mod h1:68ORG0HSEWDuH5Eh73AFbYWZ1zT4Y+b0vhOa+vZRUdI= github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= -github.com/ProtonMail/go-crypto v1.1.3 h1:nRBOetoydLeUb4nHajyO2bKqMLfWQ/ZPwkXqXxPxCFk= -github.com/ProtonMail/go-crypto v1.1.3/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE= +github.com/ProtonMail/go-crypto v1.1.6 h1:ZcV+Ropw6Qn0AX9brlQLAUXfqLBc7Bl+f/DmNxpLfdw= +github.com/ProtonMail/go-crypto v1.1.6/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE= github.com/PuerkitoBio/goquery v1.9.3 h1:mpJr/ikUA9/GNJB/DBZcGeFDXUtosHRyRrwh7KGdTG0= github.com/PuerkitoBio/goquery v1.9.3/go.mod h1:1ndLHPdTz+DyQPICCWYlYQMPl0oXZj0G6D4LCYA6u4U= github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= @@ -173,8 +173,8 @@ github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7Do github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.11 h1:07n33Z8lZxZ2qwegKbObQohDhXDQxiMMz1NOUGYlesw= github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/cyphar/filepath-securejoin v0.3.6 h1:4d9N5ykBnSp5Xn2JkhocYDkOpURL/18CYMpo6xB9uWM= -github.com/cyphar/filepath-securejoin v0.3.6/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI= +github.com/cyphar/filepath-securejoin v0.4.1 h1:JyxxyPEaktOD+GAnqIqTf9A8tHyAG22rowi7HkoSU1s= +github.com/cyphar/filepath-securejoin v0.4.1/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI= github.com/dave/jennifer v0.18.0 h1:fhwWYwRltL8wW567TWRHCstLaBCEsk5M5DE4rrMsi94= github.com/dave/jennifer v0.18.0/go.mod h1:fIb+770HOpJ2fmN9EPPKOqm1vMGhB+TwXKMZhrIygKg= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -192,8 +192,8 @@ github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdf github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= -github.com/elazarl/goproxy v1.2.3 h1:xwIyKHbaP5yfT6O9KIeYJR5549MXRQkoQMRXGztz8YQ= -github.com/elazarl/goproxy v1.2.3/go.mod h1:YfEbZtqP4AetfO6d40vWchF3znWX7C7Vd6ZMfdL8z64= +github.com/elazarl/goproxy v1.7.2 h1:Y2o6urb7Eule09PjlhQRGNsqRfPmYI3KKQLFpCAV3+o= +github.com/elazarl/goproxy v1.7.2/go.mod h1:82vkLNir0ALaW14Rc399OTTjyNREgmdL2cVoIbS6XaE= github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= @@ -218,12 +218,12 @@ github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0 github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic= -github.com/go-git/go-billy/v5 v5.6.1 h1:u+dcrgaguSSkbjzHwelEjc0Yj300NUevrrPphk/SoRA= -github.com/go-git/go-billy/v5 v5.6.1/go.mod h1:0AsLr1z2+Uksi4NlElmMblP5rPcDZNRCD8ujZCRR2BE= +github.com/go-git/go-billy/v5 v5.6.2 h1:6Q86EsPXMa7c3YZ3aLAQsMA0VlWmy43r6FHqa/UNbRM= +github.com/go-git/go-billy/v5 v5.6.2/go.mod h1:rcFC2rAsp/erv7CMz9GczHcuD0D32fWzH+MJAU+jaUU= github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4= github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII= -github.com/go-git/go-git/v5 v5.13.1 h1:DAQ9APonnlvSWpvolXWIuV6Q6zXy2wHbN4cVlNR5Q+M= -github.com/go-git/go-git/v5 v5.13.1/go.mod h1:qryJB4cSBoq3FRoBRf5A77joojuBcmPJ0qu3XXXVixc= +github.com/go-git/go-git/v5 v5.16.5 h1:mdkuqblwr57kVfXri5TTH+nMFLNUxIj9Z7F5ykFbw5s= +github.com/go-git/go-git/v5 v5.16.5/go.mod h1:QOMLpNf1qxuSY4StA/ArOdfFR2TrKEjJiye2kel2m+M= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= @@ -361,8 +361,8 @@ github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4er github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ= +github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUvekVysuuOpQKo3191zZyTpiI6se1N1ULghS0sw= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= @@ -605,8 +605,8 @@ github.com/phayes/permbits v0.0.0-20190108233746-1efae4548023 h1:qGtiKAVHKJpZywK github.com/phayes/permbits v0.0.0-20190108233746-1efae4548023/go.mod h1:3uODdxMgOaPYeWU7RzZLxVtJHZ/x1f/iHkBZuKJDzuY= github.com/pierrec/lz4/v4 v4.1.22 h1:cKFw6uJDK+/gfw5BcDL0JL5aBsAFdsIT18eRtLj7VIU= github.com/pierrec/lz4/v4 v4.1.22/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= -github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4= -github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI= +github.com/pjbgf/sha1cd v0.3.2 h1:a9wb0bp1oC2TGwStyn0Umc/IGKQnEgF0vVaZ8QF8eo4= +github.com/pjbgf/sha1cd v0.3.2/go.mod h1:zQWigSxVmsHEZow5qaLtPYxpcKMMQpa09ixqBxuCS6A= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -638,8 +638,8 @@ github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6So github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= -github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= +github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= +github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= github.com/rollbar/rollbar-go v1.1.0 h1:3ysiHp3ep8W50ykgBMCKXJGaK2Jdivru7SW9EYfAo+M= github.com/rollbar/rollbar-go v1.1.0/go.mod h1:AcFs5f0I+c71bpHlXNNDbOWJiKwjFDtISeXco0L5PKQ= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= @@ -661,8 +661,8 @@ github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPx github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/skeema/knownhosts v1.3.0 h1:AM+y0rI04VksttfwjkSTNQorvGqmwATnvnAHpSgc0LY= -github.com/skeema/knownhosts v1.3.0/go.mod h1:sPINvnADmT/qYH1kfv+ePMmOBTH6Tbl7b5LvTDjFK7M= +github.com/skeema/knownhosts v1.3.1 h1:X2osQ+RAjK76shCbvhHHHVl3ZlgDm8apHEHFqRjnBY8= +github.com/skeema/knownhosts v1.3.1/go.mod h1:r7KTdC8l4uxWRyK2TpQZ/1o5HaSzh06ePQNxPwTcfiY= github.com/skratchdot/open-golang v0.0.0-20190104022628-a2dfa6d0dab6 h1:cGT4dcuEyBwwu/v6tosyqcDp2yoIo/LwjMGixUvg3nU= github.com/skratchdot/open-golang v0.0.0-20190104022628-a2dfa6d0dab6/go.mod h1:sUM3LWHvSMaG192sy56D9F7CNvL7jUJVXoqM1QKLnog= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= diff --git a/vendor/github.com/Microsoft/go-winio/.golangci.yml b/vendor/github.com/Microsoft/go-winio/.golangci.yml index 7b503d26a3..faedfe937a 100644 --- a/vendor/github.com/Microsoft/go-winio/.golangci.yml +++ b/vendor/github.com/Microsoft/go-winio/.golangci.yml @@ -1,7 +1,3 @@ -run: - skip-dirs: - - pkg/etw/sample - linters: enable: # style @@ -20,9 +16,13 @@ linters: - gofmt # files are gofmt'ed - gosec # security - nilerr # returns nil even with non-nil error + - thelper # test helpers without t.Helper() - unparam # unused function params issues: + exclude-dirs: + - pkg/etw/sample + exclude-rules: # err is very often shadowed in nested scopes - linters: @@ -69,9 +69,7 @@ linters-settings: # struct order is often for Win32 compat # also, ignore pointer bytes/GC issues for now until performance becomes an issue - fieldalignment - check-shadowing: true nolintlint: - allow-leading-space: false require-explanation: true require-specific: true revive: diff --git a/vendor/github.com/Microsoft/go-winio/backup.go b/vendor/github.com/Microsoft/go-winio/backup.go index 09621c8846..b54341daac 100644 --- a/vendor/github.com/Microsoft/go-winio/backup.go +++ b/vendor/github.com/Microsoft/go-winio/backup.go @@ -10,14 +10,14 @@ import ( "io" "os" "runtime" - "syscall" "unicode/utf16" + "github.com/Microsoft/go-winio/internal/fs" "golang.org/x/sys/windows" ) -//sys backupRead(h syscall.Handle, b []byte, bytesRead *uint32, abort bool, processSecurity bool, context *uintptr) (err error) = BackupRead -//sys backupWrite(h syscall.Handle, b []byte, bytesWritten *uint32, abort bool, processSecurity bool, context *uintptr) (err error) = BackupWrite +//sys backupRead(h windows.Handle, b []byte, bytesRead *uint32, abort bool, processSecurity bool, context *uintptr) (err error) = BackupRead +//sys backupWrite(h windows.Handle, b []byte, bytesWritten *uint32, abort bool, processSecurity bool, context *uintptr) (err error) = BackupWrite const ( BackupData = uint32(iota + 1) @@ -104,7 +104,7 @@ func (r *BackupStreamReader) Next() (*BackupHeader, error) { if err := binary.Read(r.r, binary.LittleEndian, name); err != nil { return nil, err } - hdr.Name = syscall.UTF16ToString(name) + hdr.Name = windows.UTF16ToString(name) } if wsi.StreamID == BackupSparseBlock { if err := binary.Read(r.r, binary.LittleEndian, &hdr.Offset); err != nil { @@ -205,7 +205,7 @@ func NewBackupFileReader(f *os.File, includeSecurity bool) *BackupFileReader { // Read reads a backup stream from the file by calling the Win32 API BackupRead(). func (r *BackupFileReader) Read(b []byte) (int, error) { var bytesRead uint32 - err := backupRead(syscall.Handle(r.f.Fd()), b, &bytesRead, false, r.includeSecurity, &r.ctx) + err := backupRead(windows.Handle(r.f.Fd()), b, &bytesRead, false, r.includeSecurity, &r.ctx) if err != nil { return 0, &os.PathError{Op: "BackupRead", Path: r.f.Name(), Err: err} } @@ -220,7 +220,7 @@ func (r *BackupFileReader) Read(b []byte) (int, error) { // the underlying file. func (r *BackupFileReader) Close() error { if r.ctx != 0 { - _ = backupRead(syscall.Handle(r.f.Fd()), nil, nil, true, false, &r.ctx) + _ = backupRead(windows.Handle(r.f.Fd()), nil, nil, true, false, &r.ctx) runtime.KeepAlive(r.f) r.ctx = 0 } @@ -244,7 +244,7 @@ func NewBackupFileWriter(f *os.File, includeSecurity bool) *BackupFileWriter { // Write restores a portion of the file using the provided backup stream. func (w *BackupFileWriter) Write(b []byte) (int, error) { var bytesWritten uint32 - err := backupWrite(syscall.Handle(w.f.Fd()), b, &bytesWritten, false, w.includeSecurity, &w.ctx) + err := backupWrite(windows.Handle(w.f.Fd()), b, &bytesWritten, false, w.includeSecurity, &w.ctx) if err != nil { return 0, &os.PathError{Op: "BackupWrite", Path: w.f.Name(), Err: err} } @@ -259,7 +259,7 @@ func (w *BackupFileWriter) Write(b []byte) (int, error) { // close the underlying file. func (w *BackupFileWriter) Close() error { if w.ctx != 0 { - _ = backupWrite(syscall.Handle(w.f.Fd()), nil, nil, true, false, &w.ctx) + _ = backupWrite(windows.Handle(w.f.Fd()), nil, nil, true, false, &w.ctx) runtime.KeepAlive(w.f) w.ctx = 0 } @@ -271,17 +271,14 @@ func (w *BackupFileWriter) Close() error { // // If the file opened was a directory, it cannot be used with Readdir(). func OpenForBackup(path string, access uint32, share uint32, createmode uint32) (*os.File, error) { - winPath, err := syscall.UTF16FromString(path) - if err != nil { - return nil, err - } - h, err := syscall.CreateFile(&winPath[0], - access, - share, + h, err := fs.CreateFile(path, + fs.AccessMask(access), + fs.FileShareMode(share), nil, - createmode, - syscall.FILE_FLAG_BACKUP_SEMANTICS|syscall.FILE_FLAG_OPEN_REPARSE_POINT, - 0) + fs.FileCreationDisposition(createmode), + fs.FILE_FLAG_BACKUP_SEMANTICS|fs.FILE_FLAG_OPEN_REPARSE_POINT, + 0, + ) if err != nil { err = &os.PathError{Op: "open", Path: path, Err: err} return nil, err diff --git a/vendor/github.com/Microsoft/go-winio/file.go b/vendor/github.com/Microsoft/go-winio/file.go index 175a99d3f4..fe82a180db 100644 --- a/vendor/github.com/Microsoft/go-winio/file.go +++ b/vendor/github.com/Microsoft/go-winio/file.go @@ -15,26 +15,11 @@ import ( "golang.org/x/sys/windows" ) -//sys cancelIoEx(file syscall.Handle, o *syscall.Overlapped) (err error) = CancelIoEx -//sys createIoCompletionPort(file syscall.Handle, port syscall.Handle, key uintptr, threadCount uint32) (newport syscall.Handle, err error) = CreateIoCompletionPort -//sys getQueuedCompletionStatus(port syscall.Handle, bytes *uint32, key *uintptr, o **ioOperation, timeout uint32) (err error) = GetQueuedCompletionStatus -//sys setFileCompletionNotificationModes(h syscall.Handle, flags uint8) (err error) = SetFileCompletionNotificationModes -//sys wsaGetOverlappedResult(h syscall.Handle, o *syscall.Overlapped, bytes *uint32, wait bool, flags *uint32) (err error) = ws2_32.WSAGetOverlappedResult - -type atomicBool int32 - -func (b *atomicBool) isSet() bool { return atomic.LoadInt32((*int32)(b)) != 0 } -func (b *atomicBool) setFalse() { atomic.StoreInt32((*int32)(b), 0) } -func (b *atomicBool) setTrue() { atomic.StoreInt32((*int32)(b), 1) } - -//revive:disable-next-line:predeclared Keep "new" to maintain consistency with "atomic" pkg -func (b *atomicBool) swap(new bool) bool { - var newInt int32 - if new { - newInt = 1 - } - return atomic.SwapInt32((*int32)(b), newInt) == 1 -} +//sys cancelIoEx(file windows.Handle, o *windows.Overlapped) (err error) = CancelIoEx +//sys createIoCompletionPort(file windows.Handle, port windows.Handle, key uintptr, threadCount uint32) (newport windows.Handle, err error) = CreateIoCompletionPort +//sys getQueuedCompletionStatus(port windows.Handle, bytes *uint32, key *uintptr, o **ioOperation, timeout uint32) (err error) = GetQueuedCompletionStatus +//sys setFileCompletionNotificationModes(h windows.Handle, flags uint8) (err error) = SetFileCompletionNotificationModes +//sys wsaGetOverlappedResult(h windows.Handle, o *windows.Overlapped, bytes *uint32, wait bool, flags *uint32) (err error) = ws2_32.WSAGetOverlappedResult var ( ErrFileClosed = errors.New("file has already been closed") @@ -50,7 +35,7 @@ func (*timeoutError) Temporary() bool { return true } type timeoutChan chan struct{} var ioInitOnce sync.Once -var ioCompletionPort syscall.Handle +var ioCompletionPort windows.Handle // ioResult contains the result of an asynchronous IO operation. type ioResult struct { @@ -60,12 +45,12 @@ type ioResult struct { // ioOperation represents an outstanding asynchronous Win32 IO. type ioOperation struct { - o syscall.Overlapped + o windows.Overlapped ch chan ioResult } func initIO() { - h, err := createIoCompletionPort(syscall.InvalidHandle, 0, 0, 0xffffffff) + h, err := createIoCompletionPort(windows.InvalidHandle, 0, 0, 0xffffffff) if err != nil { panic(err) } @@ -76,10 +61,10 @@ func initIO() { // win32File implements Reader, Writer, and Closer on a Win32 handle without blocking in a syscall. // It takes ownership of this handle and will close it if it is garbage collected. type win32File struct { - handle syscall.Handle + handle windows.Handle wg sync.WaitGroup wgLock sync.RWMutex - closing atomicBool + closing atomic.Bool socket bool readDeadline deadlineHandler writeDeadline deadlineHandler @@ -90,11 +75,11 @@ type deadlineHandler struct { channel timeoutChan channelLock sync.RWMutex timer *time.Timer - timedout atomicBool + timedout atomic.Bool } // makeWin32File makes a new win32File from an existing file handle. -func makeWin32File(h syscall.Handle) (*win32File, error) { +func makeWin32File(h windows.Handle) (*win32File, error) { f := &win32File{handle: h} ioInitOnce.Do(initIO) _, err := createIoCompletionPort(h, ioCompletionPort, 0, 0xffffffff) @@ -110,7 +95,12 @@ func makeWin32File(h syscall.Handle) (*win32File, error) { return f, nil } +// Deprecated: use NewOpenFile instead. func MakeOpenFile(h syscall.Handle) (io.ReadWriteCloser, error) { + return NewOpenFile(windows.Handle(h)) +} + +func NewOpenFile(h windows.Handle) (io.ReadWriteCloser, error) { // If we return the result of makeWin32File directly, it can result in an // interface-wrapped nil, rather than a nil interface value. f, err := makeWin32File(h) @@ -124,13 +114,13 @@ func MakeOpenFile(h syscall.Handle) (io.ReadWriteCloser, error) { func (f *win32File) closeHandle() { f.wgLock.Lock() // Atomically set that we are closing, releasing the resources only once. - if !f.closing.swap(true) { + if !f.closing.Swap(true) { f.wgLock.Unlock() // cancel all IO and wait for it to complete _ = cancelIoEx(f.handle, nil) f.wg.Wait() // at this point, no new IO can start - syscall.Close(f.handle) + windows.Close(f.handle) f.handle = 0 } else { f.wgLock.Unlock() @@ -145,14 +135,14 @@ func (f *win32File) Close() error { // IsClosed checks if the file has been closed. func (f *win32File) IsClosed() bool { - return f.closing.isSet() + return f.closing.Load() } // prepareIO prepares for a new IO operation. // The caller must call f.wg.Done() when the IO is finished, prior to Close() returning. func (f *win32File) prepareIO() (*ioOperation, error) { f.wgLock.RLock() - if f.closing.isSet() { + if f.closing.Load() { f.wgLock.RUnlock() return nil, ErrFileClosed } @@ -164,12 +154,12 @@ func (f *win32File) prepareIO() (*ioOperation, error) { } // ioCompletionProcessor processes completed async IOs forever. -func ioCompletionProcessor(h syscall.Handle) { +func ioCompletionProcessor(h windows.Handle) { for { var bytes uint32 var key uintptr var op *ioOperation - err := getQueuedCompletionStatus(h, &bytes, &key, &op, syscall.INFINITE) + err := getQueuedCompletionStatus(h, &bytes, &key, &op, windows.INFINITE) if op == nil { panic(err) } @@ -182,11 +172,11 @@ func ioCompletionProcessor(h syscall.Handle) { // asyncIO processes the return value from ReadFile or WriteFile, blocking until // the operation has actually completed. func (f *win32File) asyncIO(c *ioOperation, d *deadlineHandler, bytes uint32, err error) (int, error) { - if err != syscall.ERROR_IO_PENDING { //nolint:errorlint // err is Errno + if err != windows.ERROR_IO_PENDING { //nolint:errorlint // err is Errno return int(bytes), err } - if f.closing.isSet() { + if f.closing.Load() { _ = cancelIoEx(f.handle, &c.o) } @@ -201,8 +191,8 @@ func (f *win32File) asyncIO(c *ioOperation, d *deadlineHandler, bytes uint32, er select { case r = <-c.ch: err = r.err - if err == syscall.ERROR_OPERATION_ABORTED { //nolint:errorlint // err is Errno - if f.closing.isSet() { + if err == windows.ERROR_OPERATION_ABORTED { //nolint:errorlint // err is Errno + if f.closing.Load() { err = ErrFileClosed } } else if err != nil && f.socket { @@ -214,7 +204,7 @@ func (f *win32File) asyncIO(c *ioOperation, d *deadlineHandler, bytes uint32, er _ = cancelIoEx(f.handle, &c.o) r = <-c.ch err = r.err - if err == syscall.ERROR_OPERATION_ABORTED { //nolint:errorlint // err is Errno + if err == windows.ERROR_OPERATION_ABORTED { //nolint:errorlint // err is Errno err = ErrTimeout } } @@ -235,23 +225,22 @@ func (f *win32File) Read(b []byte) (int, error) { } defer f.wg.Done() - if f.readDeadline.timedout.isSet() { + if f.readDeadline.timedout.Load() { return 0, ErrTimeout } var bytes uint32 - err = syscall.ReadFile(f.handle, b, &bytes, &c.o) + err = windows.ReadFile(f.handle, b, &bytes, &c.o) n, err := f.asyncIO(c, &f.readDeadline, bytes, err) runtime.KeepAlive(b) // Handle EOF conditions. if err == nil && n == 0 && len(b) != 0 { return 0, io.EOF - } else if err == syscall.ERROR_BROKEN_PIPE { //nolint:errorlint // err is Errno + } else if err == windows.ERROR_BROKEN_PIPE { //nolint:errorlint // err is Errno return 0, io.EOF - } else { - return n, err } + return n, err } // Write writes to a file handle. @@ -262,12 +251,12 @@ func (f *win32File) Write(b []byte) (int, error) { } defer f.wg.Done() - if f.writeDeadline.timedout.isSet() { + if f.writeDeadline.timedout.Load() { return 0, ErrTimeout } var bytes uint32 - err = syscall.WriteFile(f.handle, b, &bytes, &c.o) + err = windows.WriteFile(f.handle, b, &bytes, &c.o) n, err := f.asyncIO(c, &f.writeDeadline, bytes, err) runtime.KeepAlive(b) return n, err @@ -282,7 +271,7 @@ func (f *win32File) SetWriteDeadline(deadline time.Time) error { } func (f *win32File) Flush() error { - return syscall.FlushFileBuffers(f.handle) + return windows.FlushFileBuffers(f.handle) } func (f *win32File) Fd() uintptr { @@ -299,7 +288,7 @@ func (d *deadlineHandler) set(deadline time.Time) error { } d.timer = nil } - d.timedout.setFalse() + d.timedout.Store(false) select { case <-d.channel: @@ -314,7 +303,7 @@ func (d *deadlineHandler) set(deadline time.Time) error { } timeoutIO := func() { - d.timedout.setTrue() + d.timedout.Store(true) close(d.channel) } diff --git a/vendor/github.com/Microsoft/go-winio/fileinfo.go b/vendor/github.com/Microsoft/go-winio/fileinfo.go index 702950e72a..c860eb9917 100644 --- a/vendor/github.com/Microsoft/go-winio/fileinfo.go +++ b/vendor/github.com/Microsoft/go-winio/fileinfo.go @@ -18,9 +18,18 @@ type FileBasicInfo struct { _ uint32 // padding } +// alignedFileBasicInfo is a FileBasicInfo, but aligned to uint64 by containing +// uint64 rather than windows.Filetime. Filetime contains two uint32s. uint64 +// alignment is necessary to pass this as FILE_BASIC_INFO. +type alignedFileBasicInfo struct { + CreationTime, LastAccessTime, LastWriteTime, ChangeTime uint64 + FileAttributes uint32 + _ uint32 // padding +} + // GetFileBasicInfo retrieves times and attributes for a file. func GetFileBasicInfo(f *os.File) (*FileBasicInfo, error) { - bi := &FileBasicInfo{} + bi := &alignedFileBasicInfo{} if err := windows.GetFileInformationByHandleEx( windows.Handle(f.Fd()), windows.FileBasicInfo, @@ -30,16 +39,21 @@ func GetFileBasicInfo(f *os.File) (*FileBasicInfo, error) { return nil, &os.PathError{Op: "GetFileInformationByHandleEx", Path: f.Name(), Err: err} } runtime.KeepAlive(f) - return bi, nil + // Reinterpret the alignedFileBasicInfo as a FileBasicInfo so it matches the + // public API of this module. The data may be unnecessarily aligned. + return (*FileBasicInfo)(unsafe.Pointer(bi)), nil } // SetFileBasicInfo sets times and attributes for a file. func SetFileBasicInfo(f *os.File, bi *FileBasicInfo) error { + // Create an alignedFileBasicInfo based on a FileBasicInfo. The copy is + // suitable to pass to GetFileInformationByHandleEx. + biAligned := *(*alignedFileBasicInfo)(unsafe.Pointer(bi)) if err := windows.SetFileInformationByHandle( windows.Handle(f.Fd()), windows.FileBasicInfo, - (*byte)(unsafe.Pointer(bi)), - uint32(unsafe.Sizeof(*bi)), + (*byte)(unsafe.Pointer(&biAligned)), + uint32(unsafe.Sizeof(biAligned)), ); err != nil { return &os.PathError{Op: "SetFileInformationByHandle", Path: f.Name(), Err: err} } diff --git a/vendor/github.com/Microsoft/go-winio/hvsock.go b/vendor/github.com/Microsoft/go-winio/hvsock.go index c881916583..c4fdd9d4ae 100644 --- a/vendor/github.com/Microsoft/go-winio/hvsock.go +++ b/vendor/github.com/Microsoft/go-winio/hvsock.go @@ -10,7 +10,6 @@ import ( "io" "net" "os" - "syscall" "time" "unsafe" @@ -181,13 +180,13 @@ type HvsockConn struct { var _ net.Conn = &HvsockConn{} func newHVSocket() (*win32File, error) { - fd, err := syscall.Socket(afHVSock, syscall.SOCK_STREAM, 1) + fd, err := windows.Socket(afHVSock, windows.SOCK_STREAM, 1) if err != nil { return nil, os.NewSyscallError("socket", err) } f, err := makeWin32File(fd) if err != nil { - syscall.Close(fd) + windows.Close(fd) return nil, err } f.socket = true @@ -197,16 +196,24 @@ func newHVSocket() (*win32File, error) { // ListenHvsock listens for connections on the specified hvsock address. func ListenHvsock(addr *HvsockAddr) (_ *HvsockListener, err error) { l := &HvsockListener{addr: *addr} - sock, err := newHVSocket() + + var sock *win32File + sock, err = newHVSocket() if err != nil { return nil, l.opErr("listen", err) } + defer func() { + if err != nil { + _ = sock.Close() + } + }() + sa := addr.raw() - err = socket.Bind(windows.Handle(sock.handle), &sa) + err = socket.Bind(sock.handle, &sa) if err != nil { return nil, l.opErr("listen", os.NewSyscallError("socket", err)) } - err = syscall.Listen(sock.handle, 16) + err = windows.Listen(sock.handle, 16) if err != nil { return nil, l.opErr("listen", os.NewSyscallError("listen", err)) } @@ -246,7 +253,7 @@ func (l *HvsockListener) Accept() (_ net.Conn, err error) { var addrbuf [addrlen * 2]byte var bytes uint32 - err = syscall.AcceptEx(l.sock.handle, sock.handle, &addrbuf[0], 0 /* rxdatalen */, addrlen, addrlen, &bytes, &c.o) + err = windows.AcceptEx(l.sock.handle, sock.handle, &addrbuf[0], 0 /* rxdatalen */, addrlen, addrlen, &bytes, &c.o) if _, err = l.sock.asyncIO(c, nil, bytes, err); err != nil { return nil, l.opErr("accept", os.NewSyscallError("acceptex", err)) } @@ -263,7 +270,7 @@ func (l *HvsockListener) Accept() (_ net.Conn, err error) { conn.remote.fromRaw((*rawHvsockAddr)(unsafe.Pointer(&addrbuf[addrlen]))) // initialize the accepted socket and update its properties with those of the listening socket - if err = windows.Setsockopt(windows.Handle(sock.handle), + if err = windows.Setsockopt(sock.handle, windows.SOL_SOCKET, windows.SO_UPDATE_ACCEPT_CONTEXT, (*byte)(unsafe.Pointer(&l.sock.handle)), int32(unsafe.Sizeof(l.sock.handle))); err != nil { return nil, conn.opErr("accept", os.NewSyscallError("setsockopt", err)) @@ -334,7 +341,7 @@ func (d *HvsockDialer) Dial(ctx context.Context, addr *HvsockAddr) (conn *Hvsock }() sa := addr.raw() - err = socket.Bind(windows.Handle(sock.handle), &sa) + err = socket.Bind(sock.handle, &sa) if err != nil { return nil, conn.opErr(op, os.NewSyscallError("bind", err)) } @@ -347,7 +354,7 @@ func (d *HvsockDialer) Dial(ctx context.Context, addr *HvsockAddr) (conn *Hvsock var bytes uint32 for i := uint(0); i <= d.Retries; i++ { err = socket.ConnectEx( - windows.Handle(sock.handle), + sock.handle, &sa, nil, // sendBuf 0, // sendDataLen @@ -367,7 +374,7 @@ func (d *HvsockDialer) Dial(ctx context.Context, addr *HvsockAddr) (conn *Hvsock // update the connection properties, so shutdown can be used if err = windows.Setsockopt( - windows.Handle(sock.handle), + sock.handle, windows.SOL_SOCKET, windows.SO_UPDATE_CONNECT_CONTEXT, nil, // optvalue @@ -378,7 +385,7 @@ func (d *HvsockDialer) Dial(ctx context.Context, addr *HvsockAddr) (conn *Hvsock // get the local name var sal rawHvsockAddr - err = socket.GetSockName(windows.Handle(sock.handle), &sal) + err = socket.GetSockName(sock.handle, &sal) if err != nil { return nil, conn.opErr(op, os.NewSyscallError("getsockname", err)) } @@ -421,7 +428,7 @@ func (d *HvsockDialer) redialWait(ctx context.Context) (err error) { return ctx.Err() } -// assumes error is a plain, unwrapped syscall.Errno provided by direct syscall. +// assumes error is a plain, unwrapped windows.Errno provided by direct syscall. func canRedial(err error) bool { //nolint:errorlint // guaranteed to be an Errno switch err { @@ -447,9 +454,9 @@ func (conn *HvsockConn) Read(b []byte) (int, error) { return 0, conn.opErr("read", err) } defer conn.sock.wg.Done() - buf := syscall.WSABuf{Buf: &b[0], Len: uint32(len(b))} + buf := windows.WSABuf{Buf: &b[0], Len: uint32(len(b))} var flags, bytes uint32 - err = syscall.WSARecv(conn.sock.handle, &buf, 1, &bytes, &flags, &c.o, nil) + err = windows.WSARecv(conn.sock.handle, &buf, 1, &bytes, &flags, &c.o, nil) n, err := conn.sock.asyncIO(c, &conn.sock.readDeadline, bytes, err) if err != nil { var eno windows.Errno @@ -482,9 +489,9 @@ func (conn *HvsockConn) write(b []byte) (int, error) { return 0, conn.opErr("write", err) } defer conn.sock.wg.Done() - buf := syscall.WSABuf{Buf: &b[0], Len: uint32(len(b))} + buf := windows.WSABuf{Buf: &b[0], Len: uint32(len(b))} var bytes uint32 - err = syscall.WSASend(conn.sock.handle, &buf, 1, &bytes, 0, &c.o, nil) + err = windows.WSASend(conn.sock.handle, &buf, 1, &bytes, 0, &c.o, nil) n, err := conn.sock.asyncIO(c, &conn.sock.writeDeadline, bytes, err) if err != nil { var eno windows.Errno @@ -511,7 +518,7 @@ func (conn *HvsockConn) shutdown(how int) error { return socket.ErrSocketClosed } - err := syscall.Shutdown(conn.sock.handle, how) + err := windows.Shutdown(conn.sock.handle, how) if err != nil { // If the connection was closed, shutdowns fail with "not connected" if errors.Is(err, windows.WSAENOTCONN) || @@ -525,7 +532,7 @@ func (conn *HvsockConn) shutdown(how int) error { // CloseRead shuts down the read end of the socket, preventing future read operations. func (conn *HvsockConn) CloseRead() error { - err := conn.shutdown(syscall.SHUT_RD) + err := conn.shutdown(windows.SHUT_RD) if err != nil { return conn.opErr("closeread", err) } @@ -535,7 +542,7 @@ func (conn *HvsockConn) CloseRead() error { // CloseWrite shuts down the write end of the socket, preventing future write operations and // notifying the other endpoint that no more data will be written. func (conn *HvsockConn) CloseWrite() error { - err := conn.shutdown(syscall.SHUT_WR) + err := conn.shutdown(windows.SHUT_WR) if err != nil { return conn.opErr("closewrite", err) } diff --git a/vendor/github.com/Microsoft/go-winio/internal/fs/fs.go b/vendor/github.com/Microsoft/go-winio/internal/fs/fs.go index 509b3ec641..0cd9621df7 100644 --- a/vendor/github.com/Microsoft/go-winio/internal/fs/fs.go +++ b/vendor/github.com/Microsoft/go-winio/internal/fs/fs.go @@ -11,12 +11,14 @@ import ( //go:generate go run github.com/Microsoft/go-winio/tools/mkwinsyscall -output zsyscall_windows.go fs.go // https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilew -//sys CreateFile(name string, access AccessMask, mode FileShareMode, sa *syscall.SecurityAttributes, createmode FileCreationDisposition, attrs FileFlagOrAttribute, templatefile windows.Handle) (handle windows.Handle, err error) [failretval==windows.InvalidHandle] = CreateFileW +//sys CreateFile(name string, access AccessMask, mode FileShareMode, sa *windows.SecurityAttributes, createmode FileCreationDisposition, attrs FileFlagOrAttribute, templatefile windows.Handle) (handle windows.Handle, err error) [failretval==windows.InvalidHandle] = CreateFileW const NullHandle windows.Handle = 0 // AccessMask defines standard, specific, and generic rights. // +// Used with CreateFile and NtCreateFile (and co.). +// // Bitmask: // 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 // 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 @@ -47,6 +49,12 @@ const ( // https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilew#parameters FILE_ANY_ACCESS AccessMask = 0 + GENERIC_READ AccessMask = 0x8000_0000 + GENERIC_WRITE AccessMask = 0x4000_0000 + GENERIC_EXECUTE AccessMask = 0x2000_0000 + GENERIC_ALL AccessMask = 0x1000_0000 + ACCESS_SYSTEM_SECURITY AccessMask = 0x0100_0000 + // Specific Object Access // from ntioapi.h @@ -124,14 +132,32 @@ const ( TRUNCATE_EXISTING FileCreationDisposition = 0x05 ) +// Create disposition values for NtCreate* +type NTFileCreationDisposition uint32 + +//nolint:revive // SNAKE_CASE is not idiomatic in Go, but aligned with Win32 API. +const ( + // From ntioapi.h + + FILE_SUPERSEDE NTFileCreationDisposition = 0x00 + FILE_OPEN NTFileCreationDisposition = 0x01 + FILE_CREATE NTFileCreationDisposition = 0x02 + FILE_OPEN_IF NTFileCreationDisposition = 0x03 + FILE_OVERWRITE NTFileCreationDisposition = 0x04 + FILE_OVERWRITE_IF NTFileCreationDisposition = 0x05 + FILE_MAXIMUM_DISPOSITION NTFileCreationDisposition = 0x05 +) + // CreateFile and co. take flags or attributes together as one parameter. // Define alias until we can use generics to allow both - +// // https://learn.microsoft.com/en-us/windows/win32/fileio/file-attribute-constants type FileFlagOrAttribute uint32 //nolint:revive // SNAKE_CASE is not idiomatic in Go, but aligned with Win32 API. -const ( // from winnt.h +const ( + // from winnt.h + FILE_FLAG_WRITE_THROUGH FileFlagOrAttribute = 0x8000_0000 FILE_FLAG_OVERLAPPED FileFlagOrAttribute = 0x4000_0000 FILE_FLAG_NO_BUFFERING FileFlagOrAttribute = 0x2000_0000 @@ -145,17 +171,51 @@ const ( // from winnt.h FILE_FLAG_FIRST_PIPE_INSTANCE FileFlagOrAttribute = 0x0008_0000 ) +// NtCreate* functions take a dedicated CreateOptions parameter. +// +// https://learn.microsoft.com/en-us/windows/win32/api/Winternl/nf-winternl-ntcreatefile +// +// https://learn.microsoft.com/en-us/windows/win32/devnotes/nt-create-named-pipe-file +type NTCreateOptions uint32 + +//nolint:revive // SNAKE_CASE is not idiomatic in Go, but aligned with Win32 API. +const ( + // From ntioapi.h + + FILE_DIRECTORY_FILE NTCreateOptions = 0x0000_0001 + FILE_WRITE_THROUGH NTCreateOptions = 0x0000_0002 + FILE_SEQUENTIAL_ONLY NTCreateOptions = 0x0000_0004 + FILE_NO_INTERMEDIATE_BUFFERING NTCreateOptions = 0x0000_0008 + + FILE_SYNCHRONOUS_IO_ALERT NTCreateOptions = 0x0000_0010 + FILE_SYNCHRONOUS_IO_NONALERT NTCreateOptions = 0x0000_0020 + FILE_NON_DIRECTORY_FILE NTCreateOptions = 0x0000_0040 + FILE_CREATE_TREE_CONNECTION NTCreateOptions = 0x0000_0080 + + FILE_COMPLETE_IF_OPLOCKED NTCreateOptions = 0x0000_0100 + FILE_NO_EA_KNOWLEDGE NTCreateOptions = 0x0000_0200 + FILE_DISABLE_TUNNELING NTCreateOptions = 0x0000_0400 + FILE_RANDOM_ACCESS NTCreateOptions = 0x0000_0800 + + FILE_DELETE_ON_CLOSE NTCreateOptions = 0x0000_1000 + FILE_OPEN_BY_FILE_ID NTCreateOptions = 0x0000_2000 + FILE_OPEN_FOR_BACKUP_INTENT NTCreateOptions = 0x0000_4000 + FILE_NO_COMPRESSION NTCreateOptions = 0x0000_8000 +) + type FileSQSFlag = FileFlagOrAttribute //nolint:revive // SNAKE_CASE is not idiomatic in Go, but aligned with Win32 API. -const ( // from winbase.h +const ( + // from winbase.h + SECURITY_ANONYMOUS FileSQSFlag = FileSQSFlag(SecurityAnonymous << 16) SECURITY_IDENTIFICATION FileSQSFlag = FileSQSFlag(SecurityIdentification << 16) SECURITY_IMPERSONATION FileSQSFlag = FileSQSFlag(SecurityImpersonation << 16) SECURITY_DELEGATION FileSQSFlag = FileSQSFlag(SecurityDelegation << 16) - SECURITY_SQOS_PRESENT FileSQSFlag = 0x00100000 - SECURITY_VALID_SQOS_FLAGS FileSQSFlag = 0x001F0000 + SECURITY_SQOS_PRESENT FileSQSFlag = 0x0010_0000 + SECURITY_VALID_SQOS_FLAGS FileSQSFlag = 0x001F_0000 ) // GetFinalPathNameByHandle flags diff --git a/vendor/github.com/Microsoft/go-winio/internal/fs/zsyscall_windows.go b/vendor/github.com/Microsoft/go-winio/internal/fs/zsyscall_windows.go index e2f7bb24e5..a94e234c70 100644 --- a/vendor/github.com/Microsoft/go-winio/internal/fs/zsyscall_windows.go +++ b/vendor/github.com/Microsoft/go-winio/internal/fs/zsyscall_windows.go @@ -33,9 +33,6 @@ func errnoErr(e syscall.Errno) error { case errnoERROR_IO_PENDING: return errERROR_IO_PENDING } - // TODO: add more here, after collecting data on the common - // error values see on Windows. (perhaps when running - // all.bat?) return e } @@ -45,7 +42,7 @@ var ( procCreateFileW = modkernel32.NewProc("CreateFileW") ) -func CreateFile(name string, access AccessMask, mode FileShareMode, sa *syscall.SecurityAttributes, createmode FileCreationDisposition, attrs FileFlagOrAttribute, templatefile windows.Handle) (handle windows.Handle, err error) { +func CreateFile(name string, access AccessMask, mode FileShareMode, sa *windows.SecurityAttributes, createmode FileCreationDisposition, attrs FileFlagOrAttribute, templatefile windows.Handle) (handle windows.Handle, err error) { var _p0 *uint16 _p0, err = syscall.UTF16PtrFromString(name) if err != nil { @@ -54,8 +51,8 @@ func CreateFile(name string, access AccessMask, mode FileShareMode, sa *syscall. return _CreateFile(_p0, access, mode, sa, createmode, attrs, templatefile) } -func _CreateFile(name *uint16, access AccessMask, mode FileShareMode, sa *syscall.SecurityAttributes, createmode FileCreationDisposition, attrs FileFlagOrAttribute, templatefile windows.Handle) (handle windows.Handle, err error) { - r0, _, e1 := syscall.Syscall9(procCreateFileW.Addr(), 7, uintptr(unsafe.Pointer(name)), uintptr(access), uintptr(mode), uintptr(unsafe.Pointer(sa)), uintptr(createmode), uintptr(attrs), uintptr(templatefile), 0, 0) +func _CreateFile(name *uint16, access AccessMask, mode FileShareMode, sa *windows.SecurityAttributes, createmode FileCreationDisposition, attrs FileFlagOrAttribute, templatefile windows.Handle) (handle windows.Handle, err error) { + r0, _, e1 := syscall.SyscallN(procCreateFileW.Addr(), uintptr(unsafe.Pointer(name)), uintptr(access), uintptr(mode), uintptr(unsafe.Pointer(sa)), uintptr(createmode), uintptr(attrs), uintptr(templatefile)) handle = windows.Handle(r0) if handle == windows.InvalidHandle { err = errnoErr(e1) diff --git a/vendor/github.com/Microsoft/go-winio/internal/socket/socket.go b/vendor/github.com/Microsoft/go-winio/internal/socket/socket.go index aeb7b7250f..88580d974e 100644 --- a/vendor/github.com/Microsoft/go-winio/internal/socket/socket.go +++ b/vendor/github.com/Microsoft/go-winio/internal/socket/socket.go @@ -156,9 +156,7 @@ func connectEx( bytesSent *uint32, overlapped *windows.Overlapped, ) (err error) { - // todo: after upgrading to 1.18, switch from syscall.Syscall9 to syscall.SyscallN - r1, _, e1 := syscall.Syscall9(connectExFunc.addr, - 7, + r1, _, e1 := syscall.SyscallN(connectExFunc.addr, uintptr(s), uintptr(name), uintptr(namelen), @@ -166,8 +164,8 @@ func connectEx( uintptr(sendDataLen), uintptr(unsafe.Pointer(bytesSent)), uintptr(unsafe.Pointer(overlapped)), - 0, - 0) + ) + if r1 == 0 { if e1 != 0 { err = error(e1) diff --git a/vendor/github.com/Microsoft/go-winio/internal/socket/zsyscall_windows.go b/vendor/github.com/Microsoft/go-winio/internal/socket/zsyscall_windows.go index 6d2e1a9e44..e1504126aa 100644 --- a/vendor/github.com/Microsoft/go-winio/internal/socket/zsyscall_windows.go +++ b/vendor/github.com/Microsoft/go-winio/internal/socket/zsyscall_windows.go @@ -33,9 +33,6 @@ func errnoErr(e syscall.Errno) error { case errnoERROR_IO_PENDING: return errERROR_IO_PENDING } - // TODO: add more here, after collecting data on the common - // error values see on Windows. (perhaps when running - // all.bat?) return e } @@ -48,7 +45,7 @@ var ( ) func bind(s windows.Handle, name unsafe.Pointer, namelen int32) (err error) { - r1, _, e1 := syscall.Syscall(procbind.Addr(), 3, uintptr(s), uintptr(name), uintptr(namelen)) + r1, _, e1 := syscall.SyscallN(procbind.Addr(), uintptr(s), uintptr(name), uintptr(namelen)) if r1 == socketError { err = errnoErr(e1) } @@ -56,7 +53,7 @@ func bind(s windows.Handle, name unsafe.Pointer, namelen int32) (err error) { } func getpeername(s windows.Handle, name unsafe.Pointer, namelen *int32) (err error) { - r1, _, e1 := syscall.Syscall(procgetpeername.Addr(), 3, uintptr(s), uintptr(name), uintptr(unsafe.Pointer(namelen))) + r1, _, e1 := syscall.SyscallN(procgetpeername.Addr(), uintptr(s), uintptr(name), uintptr(unsafe.Pointer(namelen))) if r1 == socketError { err = errnoErr(e1) } @@ -64,7 +61,7 @@ func getpeername(s windows.Handle, name unsafe.Pointer, namelen *int32) (err err } func getsockname(s windows.Handle, name unsafe.Pointer, namelen *int32) (err error) { - r1, _, e1 := syscall.Syscall(procgetsockname.Addr(), 3, uintptr(s), uintptr(name), uintptr(unsafe.Pointer(namelen))) + r1, _, e1 := syscall.SyscallN(procgetsockname.Addr(), uintptr(s), uintptr(name), uintptr(unsafe.Pointer(namelen))) if r1 == socketError { err = errnoErr(e1) } diff --git a/vendor/github.com/Microsoft/go-winio/internal/stringbuffer/wstring.go b/vendor/github.com/Microsoft/go-winio/internal/stringbuffer/wstring.go index 7ad5057024..42ebc019fc 100644 --- a/vendor/github.com/Microsoft/go-winio/internal/stringbuffer/wstring.go +++ b/vendor/github.com/Microsoft/go-winio/internal/stringbuffer/wstring.go @@ -62,7 +62,7 @@ func (b *WString) Free() { // ResizeTo grows the buffer to at least c and returns the new capacity, freeing the // previous buffer back into pool. func (b *WString) ResizeTo(c uint32) uint32 { - // allready sufficient (or n is 0) + // already sufficient (or n is 0) if c <= b.Cap() { return b.Cap() } diff --git a/vendor/github.com/Microsoft/go-winio/pipe.go b/vendor/github.com/Microsoft/go-winio/pipe.go index 25cc811031..a2da6639d0 100644 --- a/vendor/github.com/Microsoft/go-winio/pipe.go +++ b/vendor/github.com/Microsoft/go-winio/pipe.go @@ -11,7 +11,6 @@ import ( "net" "os" "runtime" - "syscall" "time" "unsafe" @@ -20,20 +19,44 @@ import ( "github.com/Microsoft/go-winio/internal/fs" ) -//sys connectNamedPipe(pipe syscall.Handle, o *syscall.Overlapped) (err error) = ConnectNamedPipe -//sys createNamedPipe(name string, flags uint32, pipeMode uint32, maxInstances uint32, outSize uint32, inSize uint32, defaultTimeout uint32, sa *syscall.SecurityAttributes) (handle syscall.Handle, err error) [failretval==syscall.InvalidHandle] = CreateNamedPipeW -//sys getNamedPipeInfo(pipe syscall.Handle, flags *uint32, outSize *uint32, inSize *uint32, maxInstances *uint32) (err error) = GetNamedPipeInfo -//sys getNamedPipeHandleState(pipe syscall.Handle, state *uint32, curInstances *uint32, maxCollectionCount *uint32, collectDataTimeout *uint32, userName *uint16, maxUserNameSize uint32) (err error) = GetNamedPipeHandleStateW -//sys localAlloc(uFlags uint32, length uint32) (ptr uintptr) = LocalAlloc -//sys ntCreateNamedPipeFile(pipe *syscall.Handle, access uint32, oa *objectAttributes, iosb *ioStatusBlock, share uint32, disposition uint32, options uint32, typ uint32, readMode uint32, completionMode uint32, maxInstances uint32, inboundQuota uint32, outputQuota uint32, timeout *int64) (status ntStatus) = ntdll.NtCreateNamedPipeFile +//sys connectNamedPipe(pipe windows.Handle, o *windows.Overlapped) (err error) = ConnectNamedPipe +//sys createNamedPipe(name string, flags uint32, pipeMode uint32, maxInstances uint32, outSize uint32, inSize uint32, defaultTimeout uint32, sa *windows.SecurityAttributes) (handle windows.Handle, err error) [failretval==windows.InvalidHandle] = CreateNamedPipeW +//sys disconnectNamedPipe(pipe windows.Handle) (err error) = DisconnectNamedPipe +//sys getNamedPipeInfo(pipe windows.Handle, flags *uint32, outSize *uint32, inSize *uint32, maxInstances *uint32) (err error) = GetNamedPipeInfo +//sys getNamedPipeHandleState(pipe windows.Handle, state *uint32, curInstances *uint32, maxCollectionCount *uint32, collectDataTimeout *uint32, userName *uint16, maxUserNameSize uint32) (err error) = GetNamedPipeHandleStateW +//sys ntCreateNamedPipeFile(pipe *windows.Handle, access ntAccessMask, oa *objectAttributes, iosb *ioStatusBlock, share ntFileShareMode, disposition ntFileCreationDisposition, options ntFileOptions, typ uint32, readMode uint32, completionMode uint32, maxInstances uint32, inboundQuota uint32, outputQuota uint32, timeout *int64) (status ntStatus) = ntdll.NtCreateNamedPipeFile //sys rtlNtStatusToDosError(status ntStatus) (winerr error) = ntdll.RtlNtStatusToDosErrorNoTeb //sys rtlDosPathNameToNtPathName(name *uint16, ntName *unicodeString, filePart uintptr, reserved uintptr) (status ntStatus) = ntdll.RtlDosPathNameToNtPathName_U //sys rtlDefaultNpAcl(dacl *uintptr) (status ntStatus) = ntdll.RtlDefaultNpAcl +type PipeConn interface { + net.Conn + Disconnect() error + Flush() error +} + +// type aliases for mkwinsyscall code +type ( + ntAccessMask = fs.AccessMask + ntFileShareMode = fs.FileShareMode + ntFileCreationDisposition = fs.NTFileCreationDisposition + ntFileOptions = fs.NTCreateOptions +) + type ioStatusBlock struct { Status, Information uintptr } +// typedef struct _OBJECT_ATTRIBUTES { +// ULONG Length; +// HANDLE RootDirectory; +// PUNICODE_STRING ObjectName; +// ULONG Attributes; +// PVOID SecurityDescriptor; +// PVOID SecurityQualityOfService; +// } OBJECT_ATTRIBUTES; +// +// https://learn.microsoft.com/en-us/windows/win32/api/ntdef/ns-ntdef-_object_attributes type objectAttributes struct { Length uintptr RootDirectory uintptr @@ -49,6 +72,17 @@ type unicodeString struct { Buffer uintptr } +// typedef struct _SECURITY_DESCRIPTOR { +// BYTE Revision; +// BYTE Sbz1; +// SECURITY_DESCRIPTOR_CONTROL Control; +// PSID Owner; +// PSID Group; +// PACL Sacl; +// PACL Dacl; +// } SECURITY_DESCRIPTOR, *PISECURITY_DESCRIPTOR; +// +// https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-security_descriptor type securityDescriptor struct { Revision byte Sbz1 byte @@ -80,6 +114,8 @@ type win32Pipe struct { path string } +var _ PipeConn = (*win32Pipe)(nil) + type win32MessageBytePipe struct { win32Pipe writeClosed bool @@ -103,6 +139,10 @@ func (f *win32Pipe) SetDeadline(t time.Time) error { return f.SetWriteDeadline(t) } +func (f *win32Pipe) Disconnect() error { + return disconnectNamedPipe(f.win32File.handle) +} + // CloseWrite closes the write side of a message pipe in byte mode. func (f *win32MessageBytePipe) CloseWrite() error { if f.writeClosed { @@ -146,7 +186,7 @@ func (f *win32MessageBytePipe) Read(b []byte) (int, error) { // zero-byte message, ensure that all future Read() calls // also return EOF. f.readEOF = true - } else if err == syscall.ERROR_MORE_DATA { //nolint:errorlint // err is Errno + } else if err == windows.ERROR_MORE_DATA { //nolint:errorlint // err is Errno // ERROR_MORE_DATA indicates that the pipe's read mode is message mode // and the message still has more bytes. Treat this as a success, since // this package presents all named pipes as byte streams. @@ -164,21 +204,20 @@ func (s pipeAddress) String() string { } // tryDialPipe attempts to dial the pipe at `path` until `ctx` cancellation or timeout. -func tryDialPipe(ctx context.Context, path *string, access fs.AccessMask) (syscall.Handle, error) { +func tryDialPipe(ctx context.Context, path *string, access fs.AccessMask, impLevel PipeImpLevel) (windows.Handle, error) { for { select { case <-ctx.Done(): - return syscall.Handle(0), ctx.Err() + return windows.Handle(0), ctx.Err() default: - wh, err := fs.CreateFile(*path, + h, err := fs.CreateFile(*path, access, 0, // mode nil, // security attributes fs.OPEN_EXISTING, - fs.FILE_FLAG_OVERLAPPED|fs.SECURITY_SQOS_PRESENT|fs.SECURITY_ANONYMOUS, + fs.FILE_FLAG_OVERLAPPED|fs.SECURITY_SQOS_PRESENT|fs.FileSQSFlag(impLevel), 0, // template file handle ) - h := syscall.Handle(wh) if err == nil { return h, nil } @@ -214,15 +253,33 @@ func DialPipe(path string, timeout *time.Duration) (net.Conn, error) { // DialPipeContext attempts to connect to a named pipe by `path` until `ctx` // cancellation or timeout. func DialPipeContext(ctx context.Context, path string) (net.Conn, error) { - return DialPipeAccess(ctx, path, syscall.GENERIC_READ|syscall.GENERIC_WRITE) + return DialPipeAccess(ctx, path, uint32(fs.GENERIC_READ|fs.GENERIC_WRITE)) } +// PipeImpLevel is an enumeration of impersonation levels that may be set +// when calling DialPipeAccessImpersonation. +type PipeImpLevel uint32 + +const ( + PipeImpLevelAnonymous = PipeImpLevel(fs.SECURITY_ANONYMOUS) + PipeImpLevelIdentification = PipeImpLevel(fs.SECURITY_IDENTIFICATION) + PipeImpLevelImpersonation = PipeImpLevel(fs.SECURITY_IMPERSONATION) + PipeImpLevelDelegation = PipeImpLevel(fs.SECURITY_DELEGATION) +) + // DialPipeAccess attempts to connect to a named pipe by `path` with `access` until `ctx` // cancellation or timeout. func DialPipeAccess(ctx context.Context, path string, access uint32) (net.Conn, error) { + return DialPipeAccessImpLevel(ctx, path, access, PipeImpLevelAnonymous) +} + +// DialPipeAccessImpLevel attempts to connect to a named pipe by `path` with +// `access` at `impLevel` until `ctx` cancellation or timeout. The other +// DialPipe* implementations use PipeImpLevelAnonymous. +func DialPipeAccessImpLevel(ctx context.Context, path string, access uint32, impLevel PipeImpLevel) (net.Conn, error) { var err error - var h syscall.Handle - h, err = tryDialPipe(ctx, &path, fs.AccessMask(access)) + var h windows.Handle + h, err = tryDialPipe(ctx, &path, fs.AccessMask(access), impLevel) if err != nil { return nil, err } @@ -235,7 +292,7 @@ func DialPipeAccess(ctx context.Context, path string, access uint32) (net.Conn, f, err := makeWin32File(h) if err != nil { - syscall.Close(h) + windows.Close(h) return nil, err } @@ -255,7 +312,7 @@ type acceptResponse struct { } type win32PipeListener struct { - firstHandle syscall.Handle + firstHandle windows.Handle path string config PipeConfig acceptCh chan (chan acceptResponse) @@ -263,8 +320,8 @@ type win32PipeListener struct { doneCh chan int } -func makeServerPipeHandle(path string, sd []byte, c *PipeConfig, first bool) (syscall.Handle, error) { - path16, err := syscall.UTF16FromString(path) +func makeServerPipeHandle(path string, sd []byte, c *PipeConfig, first bool) (windows.Handle, error) { + path16, err := windows.UTF16FromString(path) if err != nil { return 0, &os.PathError{Op: "open", Path: path, Err: err} } @@ -280,16 +337,20 @@ func makeServerPipeHandle(path string, sd []byte, c *PipeConfig, first bool) (sy ).Err(); err != nil { return 0, &os.PathError{Op: "open", Path: path, Err: err} } - defer localFree(ntPath.Buffer) + defer windows.LocalFree(windows.Handle(ntPath.Buffer)) //nolint:errcheck oa.ObjectName = &ntPath oa.Attributes = windows.OBJ_CASE_INSENSITIVE // The security descriptor is only needed for the first pipe. if first { if sd != nil { + //todo: does `sdb` need to be allocated on the heap, or can go allocate it? l := uint32(len(sd)) - sdb := localAlloc(0, l) - defer localFree(sdb) + sdb, err := windows.LocalAlloc(0, l) + if err != nil { + return 0, fmt.Errorf("LocalAlloc for security descriptor with of length %d: %w", l, err) + } + defer windows.LocalFree(windows.Handle(sdb)) //nolint:errcheck copy((*[0xffff]byte)(unsafe.Pointer(sdb))[:], sd) oa.SecurityDescriptor = (*securityDescriptor)(unsafe.Pointer(sdb)) } else { @@ -298,7 +359,7 @@ func makeServerPipeHandle(path string, sd []byte, c *PipeConfig, first bool) (sy if err := rtlDefaultNpAcl(&dacl).Err(); err != nil { return 0, fmt.Errorf("getting default named pipe ACL: %w", err) } - defer localFree(dacl) + defer windows.LocalFree(windows.Handle(dacl)) //nolint:errcheck sdb := &securityDescriptor{ Revision: 1, @@ -314,27 +375,27 @@ func makeServerPipeHandle(path string, sd []byte, c *PipeConfig, first bool) (sy typ |= windows.FILE_PIPE_MESSAGE_TYPE } - disposition := uint32(windows.FILE_OPEN) - access := uint32(syscall.GENERIC_READ | syscall.GENERIC_WRITE | syscall.SYNCHRONIZE) + disposition := fs.FILE_OPEN + access := fs.GENERIC_READ | fs.GENERIC_WRITE | fs.SYNCHRONIZE if first { - disposition = windows.FILE_CREATE + disposition = fs.FILE_CREATE // By not asking for read or write access, the named pipe file system // will put this pipe into an initially disconnected state, blocking // client connections until the next call with first == false. - access = syscall.SYNCHRONIZE + access = fs.SYNCHRONIZE } timeout := int64(-50 * 10000) // 50ms var ( - h syscall.Handle + h windows.Handle iosb ioStatusBlock ) err = ntCreateNamedPipeFile(&h, access, &oa, &iosb, - syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE, + fs.FILE_SHARE_READ|fs.FILE_SHARE_WRITE, disposition, 0, typ, @@ -359,7 +420,7 @@ func (l *win32PipeListener) makeServerPipe() (*win32File, error) { } f, err := makeWin32File(h) if err != nil { - syscall.Close(h) + windows.Close(h) return nil, err } return f, nil @@ -418,7 +479,7 @@ func (l *win32PipeListener) listenerRoutine() { closed = err == ErrPipeListenerClosed //nolint:errorlint // err is Errno } } - syscall.Close(l.firstHandle) + windows.Close(l.firstHandle) l.firstHandle = 0 // Notify Close() and Accept() callers that the handle has been closed. close(l.doneCh) diff --git a/vendor/github.com/Microsoft/go-winio/privilege.go b/vendor/github.com/Microsoft/go-winio/privilege.go index 0ff9dac906..d9b90b6e86 100644 --- a/vendor/github.com/Microsoft/go-winio/privilege.go +++ b/vendor/github.com/Microsoft/go-winio/privilege.go @@ -9,7 +9,6 @@ import ( "fmt" "runtime" "sync" - "syscall" "unicode/utf16" "golang.org/x/sys/windows" @@ -18,8 +17,8 @@ import ( //sys adjustTokenPrivileges(token windows.Token, releaseAll bool, input *byte, outputSize uint32, output *byte, requiredSize *uint32) (success bool, err error) [true] = advapi32.AdjustTokenPrivileges //sys impersonateSelf(level uint32) (err error) = advapi32.ImpersonateSelf //sys revertToSelf() (err error) = advapi32.RevertToSelf -//sys openThreadToken(thread syscall.Handle, accessMask uint32, openAsSelf bool, token *windows.Token) (err error) = advapi32.OpenThreadToken -//sys getCurrentThread() (h syscall.Handle) = GetCurrentThread +//sys openThreadToken(thread windows.Handle, accessMask uint32, openAsSelf bool, token *windows.Token) (err error) = advapi32.OpenThreadToken +//sys getCurrentThread() (h windows.Handle) = GetCurrentThread //sys lookupPrivilegeValue(systemName string, name string, luid *uint64) (err error) = advapi32.LookupPrivilegeValueW //sys lookupPrivilegeName(systemName string, luid *uint64, buffer *uint16, size *uint32) (err error) = advapi32.LookupPrivilegeNameW //sys lookupPrivilegeDisplayName(systemName string, name *uint16, buffer *uint16, size *uint32, languageId *uint32) (err error) = advapi32.LookupPrivilegeDisplayNameW @@ -29,7 +28,7 @@ const ( SE_PRIVILEGE_ENABLED = windows.SE_PRIVILEGE_ENABLED //revive:disable-next-line:var-naming ALL_CAPS - ERROR_NOT_ALL_ASSIGNED syscall.Errno = windows.ERROR_NOT_ALL_ASSIGNED + ERROR_NOT_ALL_ASSIGNED windows.Errno = windows.ERROR_NOT_ALL_ASSIGNED SeBackupPrivilege = "SeBackupPrivilege" SeRestorePrivilege = "SeRestorePrivilege" @@ -177,7 +176,7 @@ func newThreadToken() (windows.Token, error) { } var token windows.Token - err = openThreadToken(getCurrentThread(), syscall.TOKEN_ADJUST_PRIVILEGES|syscall.TOKEN_QUERY, false, &token) + err = openThreadToken(getCurrentThread(), windows.TOKEN_ADJUST_PRIVILEGES|windows.TOKEN_QUERY, false, &token) if err != nil { rerr := revertToSelf() if rerr != nil { diff --git a/vendor/github.com/Microsoft/go-winio/sd.go b/vendor/github.com/Microsoft/go-winio/sd.go index 5550ef6b61..c3685e98e1 100644 --- a/vendor/github.com/Microsoft/go-winio/sd.go +++ b/vendor/github.com/Microsoft/go-winio/sd.go @@ -5,7 +5,7 @@ package winio import ( "errors" - "syscall" + "fmt" "unsafe" "golang.org/x/sys/windows" @@ -15,10 +15,6 @@ import ( //sys lookupAccountSid(systemName *uint16, sid *byte, name *uint16, nameSize *uint32, refDomain *uint16, refDomainSize *uint32, sidNameUse *uint32) (err error) = advapi32.LookupAccountSidW //sys convertSidToStringSid(sid *byte, str **uint16) (err error) = advapi32.ConvertSidToStringSidW //sys convertStringSidToSid(str *uint16, sid **byte) (err error) = advapi32.ConvertStringSidToSidW -//sys convertStringSecurityDescriptorToSecurityDescriptor(str string, revision uint32, sd *uintptr, size *uint32) (err error) = advapi32.ConvertStringSecurityDescriptorToSecurityDescriptorW -//sys convertSecurityDescriptorToStringSecurityDescriptor(sd *byte, revision uint32, secInfo uint32, sddl **uint16, sddlSize *uint32) (err error) = advapi32.ConvertSecurityDescriptorToStringSecurityDescriptorW -//sys localFree(mem uintptr) = LocalFree -//sys getSecurityDescriptorLength(sd uintptr) (len uint32) = advapi32.GetSecurityDescriptorLength type AccountLookupError struct { Name string @@ -64,7 +60,7 @@ func LookupSidByName(name string) (sid string, err error) { var sidSize, sidNameUse, refDomainSize uint32 err = lookupAccountName(nil, name, nil, &sidSize, nil, &refDomainSize, &sidNameUse) - if err != nil && err != syscall.ERROR_INSUFFICIENT_BUFFER { //nolint:errorlint // err is Errno + if err != nil && err != windows.ERROR_INSUFFICIENT_BUFFER { //nolint:errorlint // err is Errno return "", &AccountLookupError{name, err} } sidBuffer := make([]byte, sidSize) @@ -78,8 +74,8 @@ func LookupSidByName(name string) (sid string, err error) { if err != nil { return "", &AccountLookupError{name, err} } - sid = syscall.UTF16ToString((*[0xffff]uint16)(unsafe.Pointer(strBuffer))[:]) - localFree(uintptr(unsafe.Pointer(strBuffer))) + sid = windows.UTF16ToString((*[0xffff]uint16)(unsafe.Pointer(strBuffer))[:]) + _, _ = windows.LocalFree(windows.Handle(unsafe.Pointer(strBuffer))) return sid, nil } @@ -100,7 +96,7 @@ func LookupNameBySid(sid string) (name string, err error) { if err = convertStringSidToSid(sidBuffer, &sidPtr); err != nil { return "", &AccountLookupError{sid, err} } - defer localFree(uintptr(unsafe.Pointer(sidPtr))) + defer windows.LocalFree(windows.Handle(unsafe.Pointer(sidPtr))) //nolint:errcheck var nameSize, refDomainSize, sidNameUse uint32 err = lookupAccountSid(nil, sidPtr, nil, &nameSize, nil, &refDomainSize, &sidNameUse) @@ -120,25 +116,18 @@ func LookupNameBySid(sid string) (name string, err error) { } func SddlToSecurityDescriptor(sddl string) ([]byte, error) { - var sdBuffer uintptr - err := convertStringSecurityDescriptorToSecurityDescriptor(sddl, 1, &sdBuffer, nil) + sd, err := windows.SecurityDescriptorFromString(sddl) if err != nil { - return nil, &SddlConversionError{sddl, err} + return nil, &SddlConversionError{Sddl: sddl, Err: err} } - defer localFree(sdBuffer) - sd := make([]byte, getSecurityDescriptorLength(sdBuffer)) - copy(sd, (*[0xffff]byte)(unsafe.Pointer(sdBuffer))[:len(sd)]) - return sd, nil + b := unsafe.Slice((*byte)(unsafe.Pointer(sd)), sd.Length()) + return b, nil } func SecurityDescriptorToSddl(sd []byte) (string, error) { - var sddl *uint16 - // The returned string length seems to include an arbitrary number of terminating NULs. - // Don't use it. - err := convertSecurityDescriptorToStringSecurityDescriptor(&sd[0], 1, 0xff, &sddl, nil) - if err != nil { - return "", err + if l := int(unsafe.Sizeof(windows.SECURITY_DESCRIPTOR{})); len(sd) < l { + return "", fmt.Errorf("SecurityDescriptor (%d) smaller than expected (%d): %w", len(sd), l, windows.ERROR_INCORRECT_SIZE) } - defer localFree(uintptr(unsafe.Pointer(sddl))) - return syscall.UTF16ToString((*[0xffff]uint16)(unsafe.Pointer(sddl))[:]), nil + s := (*windows.SECURITY_DESCRIPTOR)(unsafe.Pointer(&sd[0])) + return s.String(), nil } diff --git a/vendor/github.com/Microsoft/go-winio/tools.go b/vendor/github.com/Microsoft/go-winio/tools.go deleted file mode 100644 index 2aa045843e..0000000000 --- a/vendor/github.com/Microsoft/go-winio/tools.go +++ /dev/null @@ -1,5 +0,0 @@ -//go:build tools - -package winio - -import _ "golang.org/x/tools/cmd/stringer" diff --git a/vendor/github.com/Microsoft/go-winio/zsyscall_windows.go b/vendor/github.com/Microsoft/go-winio/zsyscall_windows.go index 469b16f639..89b66eda8c 100644 --- a/vendor/github.com/Microsoft/go-winio/zsyscall_windows.go +++ b/vendor/github.com/Microsoft/go-winio/zsyscall_windows.go @@ -33,9 +33,6 @@ func errnoErr(e syscall.Errno) error { case errnoERROR_IO_PENDING: return errERROR_IO_PENDING } - // TODO: add more here, after collecting data on the common - // error values see on Windows. (perhaps when running - // all.bat?) return e } @@ -45,38 +42,34 @@ var ( modntdll = windows.NewLazySystemDLL("ntdll.dll") modws2_32 = windows.NewLazySystemDLL("ws2_32.dll") - procAdjustTokenPrivileges = modadvapi32.NewProc("AdjustTokenPrivileges") - procConvertSecurityDescriptorToStringSecurityDescriptorW = modadvapi32.NewProc("ConvertSecurityDescriptorToStringSecurityDescriptorW") - procConvertSidToStringSidW = modadvapi32.NewProc("ConvertSidToStringSidW") - procConvertStringSecurityDescriptorToSecurityDescriptorW = modadvapi32.NewProc("ConvertStringSecurityDescriptorToSecurityDescriptorW") - procConvertStringSidToSidW = modadvapi32.NewProc("ConvertStringSidToSidW") - procGetSecurityDescriptorLength = modadvapi32.NewProc("GetSecurityDescriptorLength") - procImpersonateSelf = modadvapi32.NewProc("ImpersonateSelf") - procLookupAccountNameW = modadvapi32.NewProc("LookupAccountNameW") - procLookupAccountSidW = modadvapi32.NewProc("LookupAccountSidW") - procLookupPrivilegeDisplayNameW = modadvapi32.NewProc("LookupPrivilegeDisplayNameW") - procLookupPrivilegeNameW = modadvapi32.NewProc("LookupPrivilegeNameW") - procLookupPrivilegeValueW = modadvapi32.NewProc("LookupPrivilegeValueW") - procOpenThreadToken = modadvapi32.NewProc("OpenThreadToken") - procRevertToSelf = modadvapi32.NewProc("RevertToSelf") - procBackupRead = modkernel32.NewProc("BackupRead") - procBackupWrite = modkernel32.NewProc("BackupWrite") - procCancelIoEx = modkernel32.NewProc("CancelIoEx") - procConnectNamedPipe = modkernel32.NewProc("ConnectNamedPipe") - procCreateIoCompletionPort = modkernel32.NewProc("CreateIoCompletionPort") - procCreateNamedPipeW = modkernel32.NewProc("CreateNamedPipeW") - procGetCurrentThread = modkernel32.NewProc("GetCurrentThread") - procGetNamedPipeHandleStateW = modkernel32.NewProc("GetNamedPipeHandleStateW") - procGetNamedPipeInfo = modkernel32.NewProc("GetNamedPipeInfo") - procGetQueuedCompletionStatus = modkernel32.NewProc("GetQueuedCompletionStatus") - procLocalAlloc = modkernel32.NewProc("LocalAlloc") - procLocalFree = modkernel32.NewProc("LocalFree") - procSetFileCompletionNotificationModes = modkernel32.NewProc("SetFileCompletionNotificationModes") - procNtCreateNamedPipeFile = modntdll.NewProc("NtCreateNamedPipeFile") - procRtlDefaultNpAcl = modntdll.NewProc("RtlDefaultNpAcl") - procRtlDosPathNameToNtPathName_U = modntdll.NewProc("RtlDosPathNameToNtPathName_U") - procRtlNtStatusToDosErrorNoTeb = modntdll.NewProc("RtlNtStatusToDosErrorNoTeb") - procWSAGetOverlappedResult = modws2_32.NewProc("WSAGetOverlappedResult") + procAdjustTokenPrivileges = modadvapi32.NewProc("AdjustTokenPrivileges") + procConvertSidToStringSidW = modadvapi32.NewProc("ConvertSidToStringSidW") + procConvertStringSidToSidW = modadvapi32.NewProc("ConvertStringSidToSidW") + procImpersonateSelf = modadvapi32.NewProc("ImpersonateSelf") + procLookupAccountNameW = modadvapi32.NewProc("LookupAccountNameW") + procLookupAccountSidW = modadvapi32.NewProc("LookupAccountSidW") + procLookupPrivilegeDisplayNameW = modadvapi32.NewProc("LookupPrivilegeDisplayNameW") + procLookupPrivilegeNameW = modadvapi32.NewProc("LookupPrivilegeNameW") + procLookupPrivilegeValueW = modadvapi32.NewProc("LookupPrivilegeValueW") + procOpenThreadToken = modadvapi32.NewProc("OpenThreadToken") + procRevertToSelf = modadvapi32.NewProc("RevertToSelf") + procBackupRead = modkernel32.NewProc("BackupRead") + procBackupWrite = modkernel32.NewProc("BackupWrite") + procCancelIoEx = modkernel32.NewProc("CancelIoEx") + procConnectNamedPipe = modkernel32.NewProc("ConnectNamedPipe") + procCreateIoCompletionPort = modkernel32.NewProc("CreateIoCompletionPort") + procCreateNamedPipeW = modkernel32.NewProc("CreateNamedPipeW") + procDisconnectNamedPipe = modkernel32.NewProc("DisconnectNamedPipe") + procGetCurrentThread = modkernel32.NewProc("GetCurrentThread") + procGetNamedPipeHandleStateW = modkernel32.NewProc("GetNamedPipeHandleStateW") + procGetNamedPipeInfo = modkernel32.NewProc("GetNamedPipeInfo") + procGetQueuedCompletionStatus = modkernel32.NewProc("GetQueuedCompletionStatus") + procSetFileCompletionNotificationModes = modkernel32.NewProc("SetFileCompletionNotificationModes") + procNtCreateNamedPipeFile = modntdll.NewProc("NtCreateNamedPipeFile") + procRtlDefaultNpAcl = modntdll.NewProc("RtlDefaultNpAcl") + procRtlDosPathNameToNtPathName_U = modntdll.NewProc("RtlDosPathNameToNtPathName_U") + procRtlNtStatusToDosErrorNoTeb = modntdll.NewProc("RtlNtStatusToDosErrorNoTeb") + procWSAGetOverlappedResult = modws2_32.NewProc("WSAGetOverlappedResult") ) func adjustTokenPrivileges(token windows.Token, releaseAll bool, input *byte, outputSize uint32, output *byte, requiredSize *uint32) (success bool, err error) { @@ -84,7 +77,7 @@ func adjustTokenPrivileges(token windows.Token, releaseAll bool, input *byte, ou if releaseAll { _p0 = 1 } - r0, _, e1 := syscall.Syscall6(procAdjustTokenPrivileges.Addr(), 6, uintptr(token), uintptr(_p0), uintptr(unsafe.Pointer(input)), uintptr(outputSize), uintptr(unsafe.Pointer(output)), uintptr(unsafe.Pointer(requiredSize))) + r0, _, e1 := syscall.SyscallN(procAdjustTokenPrivileges.Addr(), uintptr(token), uintptr(_p0), uintptr(unsafe.Pointer(input)), uintptr(outputSize), uintptr(unsafe.Pointer(output)), uintptr(unsafe.Pointer(requiredSize))) success = r0 != 0 if true { err = errnoErr(e1) @@ -92,33 +85,8 @@ func adjustTokenPrivileges(token windows.Token, releaseAll bool, input *byte, ou return } -func convertSecurityDescriptorToStringSecurityDescriptor(sd *byte, revision uint32, secInfo uint32, sddl **uint16, sddlSize *uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procConvertSecurityDescriptorToStringSecurityDescriptorW.Addr(), 5, uintptr(unsafe.Pointer(sd)), uintptr(revision), uintptr(secInfo), uintptr(unsafe.Pointer(sddl)), uintptr(unsafe.Pointer(sddlSize)), 0) - if r1 == 0 { - err = errnoErr(e1) - } - return -} - func convertSidToStringSid(sid *byte, str **uint16) (err error) { - r1, _, e1 := syscall.Syscall(procConvertSidToStringSidW.Addr(), 2, uintptr(unsafe.Pointer(sid)), uintptr(unsafe.Pointer(str)), 0) - if r1 == 0 { - err = errnoErr(e1) - } - return -} - -func convertStringSecurityDescriptorToSecurityDescriptor(str string, revision uint32, sd *uintptr, size *uint32) (err error) { - var _p0 *uint16 - _p0, err = syscall.UTF16PtrFromString(str) - if err != nil { - return - } - return _convertStringSecurityDescriptorToSecurityDescriptor(_p0, revision, sd, size) -} - -func _convertStringSecurityDescriptorToSecurityDescriptor(str *uint16, revision uint32, sd *uintptr, size *uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procConvertStringSecurityDescriptorToSecurityDescriptorW.Addr(), 4, uintptr(unsafe.Pointer(str)), uintptr(revision), uintptr(unsafe.Pointer(sd)), uintptr(unsafe.Pointer(size)), 0, 0) + r1, _, e1 := syscall.SyscallN(procConvertSidToStringSidW.Addr(), uintptr(unsafe.Pointer(sid)), uintptr(unsafe.Pointer(str))) if r1 == 0 { err = errnoErr(e1) } @@ -126,21 +94,15 @@ func _convertStringSecurityDescriptorToSecurityDescriptor(str *uint16, revision } func convertStringSidToSid(str *uint16, sid **byte) (err error) { - r1, _, e1 := syscall.Syscall(procConvertStringSidToSidW.Addr(), 2, uintptr(unsafe.Pointer(str)), uintptr(unsafe.Pointer(sid)), 0) + r1, _, e1 := syscall.SyscallN(procConvertStringSidToSidW.Addr(), uintptr(unsafe.Pointer(str)), uintptr(unsafe.Pointer(sid))) if r1 == 0 { err = errnoErr(e1) } return } -func getSecurityDescriptorLength(sd uintptr) (len uint32) { - r0, _, _ := syscall.Syscall(procGetSecurityDescriptorLength.Addr(), 1, uintptr(sd), 0, 0) - len = uint32(r0) - return -} - func impersonateSelf(level uint32) (err error) { - r1, _, e1 := syscall.Syscall(procImpersonateSelf.Addr(), 1, uintptr(level), 0, 0) + r1, _, e1 := syscall.SyscallN(procImpersonateSelf.Addr(), uintptr(level)) if r1 == 0 { err = errnoErr(e1) } @@ -157,7 +119,7 @@ func lookupAccountName(systemName *uint16, accountName string, sid *byte, sidSiz } func _lookupAccountName(systemName *uint16, accountName *uint16, sid *byte, sidSize *uint32, refDomain *uint16, refDomainSize *uint32, sidNameUse *uint32) (err error) { - r1, _, e1 := syscall.Syscall9(procLookupAccountNameW.Addr(), 7, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(accountName)), uintptr(unsafe.Pointer(sid)), uintptr(unsafe.Pointer(sidSize)), uintptr(unsafe.Pointer(refDomain)), uintptr(unsafe.Pointer(refDomainSize)), uintptr(unsafe.Pointer(sidNameUse)), 0, 0) + r1, _, e1 := syscall.SyscallN(procLookupAccountNameW.Addr(), uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(accountName)), uintptr(unsafe.Pointer(sid)), uintptr(unsafe.Pointer(sidSize)), uintptr(unsafe.Pointer(refDomain)), uintptr(unsafe.Pointer(refDomainSize)), uintptr(unsafe.Pointer(sidNameUse))) if r1 == 0 { err = errnoErr(e1) } @@ -165,7 +127,7 @@ func _lookupAccountName(systemName *uint16, accountName *uint16, sid *byte, sidS } func lookupAccountSid(systemName *uint16, sid *byte, name *uint16, nameSize *uint32, refDomain *uint16, refDomainSize *uint32, sidNameUse *uint32) (err error) { - r1, _, e1 := syscall.Syscall9(procLookupAccountSidW.Addr(), 7, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(sid)), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(nameSize)), uintptr(unsafe.Pointer(refDomain)), uintptr(unsafe.Pointer(refDomainSize)), uintptr(unsafe.Pointer(sidNameUse)), 0, 0) + r1, _, e1 := syscall.SyscallN(procLookupAccountSidW.Addr(), uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(sid)), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(nameSize)), uintptr(unsafe.Pointer(refDomain)), uintptr(unsafe.Pointer(refDomainSize)), uintptr(unsafe.Pointer(sidNameUse))) if r1 == 0 { err = errnoErr(e1) } @@ -182,7 +144,7 @@ func lookupPrivilegeDisplayName(systemName string, name *uint16, buffer *uint16, } func _lookupPrivilegeDisplayName(systemName *uint16, name *uint16, buffer *uint16, size *uint32, languageId *uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procLookupPrivilegeDisplayNameW.Addr(), 5, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(buffer)), uintptr(unsafe.Pointer(size)), uintptr(unsafe.Pointer(languageId)), 0) + r1, _, e1 := syscall.SyscallN(procLookupPrivilegeDisplayNameW.Addr(), uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(buffer)), uintptr(unsafe.Pointer(size)), uintptr(unsafe.Pointer(languageId))) if r1 == 0 { err = errnoErr(e1) } @@ -199,7 +161,7 @@ func lookupPrivilegeName(systemName string, luid *uint64, buffer *uint16, size * } func _lookupPrivilegeName(systemName *uint16, luid *uint64, buffer *uint16, size *uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procLookupPrivilegeNameW.Addr(), 4, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(luid)), uintptr(unsafe.Pointer(buffer)), uintptr(unsafe.Pointer(size)), 0, 0) + r1, _, e1 := syscall.SyscallN(procLookupPrivilegeNameW.Addr(), uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(luid)), uintptr(unsafe.Pointer(buffer)), uintptr(unsafe.Pointer(size))) if r1 == 0 { err = errnoErr(e1) } @@ -221,19 +183,19 @@ func lookupPrivilegeValue(systemName string, name string, luid *uint64) (err err } func _lookupPrivilegeValue(systemName *uint16, name *uint16, luid *uint64) (err error) { - r1, _, e1 := syscall.Syscall(procLookupPrivilegeValueW.Addr(), 3, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(luid))) + r1, _, e1 := syscall.SyscallN(procLookupPrivilegeValueW.Addr(), uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(luid))) if r1 == 0 { err = errnoErr(e1) } return } -func openThreadToken(thread syscall.Handle, accessMask uint32, openAsSelf bool, token *windows.Token) (err error) { +func openThreadToken(thread windows.Handle, accessMask uint32, openAsSelf bool, token *windows.Token) (err error) { var _p0 uint32 if openAsSelf { _p0 = 1 } - r1, _, e1 := syscall.Syscall6(procOpenThreadToken.Addr(), 4, uintptr(thread), uintptr(accessMask), uintptr(_p0), uintptr(unsafe.Pointer(token)), 0, 0) + r1, _, e1 := syscall.SyscallN(procOpenThreadToken.Addr(), uintptr(thread), uintptr(accessMask), uintptr(_p0), uintptr(unsafe.Pointer(token))) if r1 == 0 { err = errnoErr(e1) } @@ -241,14 +203,14 @@ func openThreadToken(thread syscall.Handle, accessMask uint32, openAsSelf bool, } func revertToSelf() (err error) { - r1, _, e1 := syscall.Syscall(procRevertToSelf.Addr(), 0, 0, 0, 0) + r1, _, e1 := syscall.SyscallN(procRevertToSelf.Addr()) if r1 == 0 { err = errnoErr(e1) } return } -func backupRead(h syscall.Handle, b []byte, bytesRead *uint32, abort bool, processSecurity bool, context *uintptr) (err error) { +func backupRead(h windows.Handle, b []byte, bytesRead *uint32, abort bool, processSecurity bool, context *uintptr) (err error) { var _p0 *byte if len(b) > 0 { _p0 = &b[0] @@ -261,14 +223,14 @@ func backupRead(h syscall.Handle, b []byte, bytesRead *uint32, abort bool, proce if processSecurity { _p2 = 1 } - r1, _, e1 := syscall.Syscall9(procBackupRead.Addr(), 7, uintptr(h), uintptr(unsafe.Pointer(_p0)), uintptr(len(b)), uintptr(unsafe.Pointer(bytesRead)), uintptr(_p1), uintptr(_p2), uintptr(unsafe.Pointer(context)), 0, 0) + r1, _, e1 := syscall.SyscallN(procBackupRead.Addr(), uintptr(h), uintptr(unsafe.Pointer(_p0)), uintptr(len(b)), uintptr(unsafe.Pointer(bytesRead)), uintptr(_p1), uintptr(_p2), uintptr(unsafe.Pointer(context))) if r1 == 0 { err = errnoErr(e1) } return } -func backupWrite(h syscall.Handle, b []byte, bytesWritten *uint32, abort bool, processSecurity bool, context *uintptr) (err error) { +func backupWrite(h windows.Handle, b []byte, bytesWritten *uint32, abort bool, processSecurity bool, context *uintptr) (err error) { var _p0 *byte if len(b) > 0 { _p0 = &b[0] @@ -281,39 +243,39 @@ func backupWrite(h syscall.Handle, b []byte, bytesWritten *uint32, abort bool, p if processSecurity { _p2 = 1 } - r1, _, e1 := syscall.Syscall9(procBackupWrite.Addr(), 7, uintptr(h), uintptr(unsafe.Pointer(_p0)), uintptr(len(b)), uintptr(unsafe.Pointer(bytesWritten)), uintptr(_p1), uintptr(_p2), uintptr(unsafe.Pointer(context)), 0, 0) + r1, _, e1 := syscall.SyscallN(procBackupWrite.Addr(), uintptr(h), uintptr(unsafe.Pointer(_p0)), uintptr(len(b)), uintptr(unsafe.Pointer(bytesWritten)), uintptr(_p1), uintptr(_p2), uintptr(unsafe.Pointer(context))) if r1 == 0 { err = errnoErr(e1) } return } -func cancelIoEx(file syscall.Handle, o *syscall.Overlapped) (err error) { - r1, _, e1 := syscall.Syscall(procCancelIoEx.Addr(), 2, uintptr(file), uintptr(unsafe.Pointer(o)), 0) +func cancelIoEx(file windows.Handle, o *windows.Overlapped) (err error) { + r1, _, e1 := syscall.SyscallN(procCancelIoEx.Addr(), uintptr(file), uintptr(unsafe.Pointer(o))) if r1 == 0 { err = errnoErr(e1) } return } -func connectNamedPipe(pipe syscall.Handle, o *syscall.Overlapped) (err error) { - r1, _, e1 := syscall.Syscall(procConnectNamedPipe.Addr(), 2, uintptr(pipe), uintptr(unsafe.Pointer(o)), 0) +func connectNamedPipe(pipe windows.Handle, o *windows.Overlapped) (err error) { + r1, _, e1 := syscall.SyscallN(procConnectNamedPipe.Addr(), uintptr(pipe), uintptr(unsafe.Pointer(o))) if r1 == 0 { err = errnoErr(e1) } return } -func createIoCompletionPort(file syscall.Handle, port syscall.Handle, key uintptr, threadCount uint32) (newport syscall.Handle, err error) { - r0, _, e1 := syscall.Syscall6(procCreateIoCompletionPort.Addr(), 4, uintptr(file), uintptr(port), uintptr(key), uintptr(threadCount), 0, 0) - newport = syscall.Handle(r0) +func createIoCompletionPort(file windows.Handle, port windows.Handle, key uintptr, threadCount uint32) (newport windows.Handle, err error) { + r0, _, e1 := syscall.SyscallN(procCreateIoCompletionPort.Addr(), uintptr(file), uintptr(port), uintptr(key), uintptr(threadCount)) + newport = windows.Handle(r0) if newport == 0 { err = errnoErr(e1) } return } -func createNamedPipe(name string, flags uint32, pipeMode uint32, maxInstances uint32, outSize uint32, inSize uint32, defaultTimeout uint32, sa *syscall.SecurityAttributes) (handle syscall.Handle, err error) { +func createNamedPipe(name string, flags uint32, pipeMode uint32, maxInstances uint32, outSize uint32, inSize uint32, defaultTimeout uint32, sa *windows.SecurityAttributes) (handle windows.Handle, err error) { var _p0 *uint16 _p0, err = syscall.UTF16PtrFromString(name) if err != nil { @@ -322,96 +284,93 @@ func createNamedPipe(name string, flags uint32, pipeMode uint32, maxInstances ui return _createNamedPipe(_p0, flags, pipeMode, maxInstances, outSize, inSize, defaultTimeout, sa) } -func _createNamedPipe(name *uint16, flags uint32, pipeMode uint32, maxInstances uint32, outSize uint32, inSize uint32, defaultTimeout uint32, sa *syscall.SecurityAttributes) (handle syscall.Handle, err error) { - r0, _, e1 := syscall.Syscall9(procCreateNamedPipeW.Addr(), 8, uintptr(unsafe.Pointer(name)), uintptr(flags), uintptr(pipeMode), uintptr(maxInstances), uintptr(outSize), uintptr(inSize), uintptr(defaultTimeout), uintptr(unsafe.Pointer(sa)), 0) - handle = syscall.Handle(r0) - if handle == syscall.InvalidHandle { +func _createNamedPipe(name *uint16, flags uint32, pipeMode uint32, maxInstances uint32, outSize uint32, inSize uint32, defaultTimeout uint32, sa *windows.SecurityAttributes) (handle windows.Handle, err error) { + r0, _, e1 := syscall.SyscallN(procCreateNamedPipeW.Addr(), uintptr(unsafe.Pointer(name)), uintptr(flags), uintptr(pipeMode), uintptr(maxInstances), uintptr(outSize), uintptr(inSize), uintptr(defaultTimeout), uintptr(unsafe.Pointer(sa))) + handle = windows.Handle(r0) + if handle == windows.InvalidHandle { err = errnoErr(e1) } return } -func getCurrentThread() (h syscall.Handle) { - r0, _, _ := syscall.Syscall(procGetCurrentThread.Addr(), 0, 0, 0, 0) - h = syscall.Handle(r0) - return -} - -func getNamedPipeHandleState(pipe syscall.Handle, state *uint32, curInstances *uint32, maxCollectionCount *uint32, collectDataTimeout *uint32, userName *uint16, maxUserNameSize uint32) (err error) { - r1, _, e1 := syscall.Syscall9(procGetNamedPipeHandleStateW.Addr(), 7, uintptr(pipe), uintptr(unsafe.Pointer(state)), uintptr(unsafe.Pointer(curInstances)), uintptr(unsafe.Pointer(maxCollectionCount)), uintptr(unsafe.Pointer(collectDataTimeout)), uintptr(unsafe.Pointer(userName)), uintptr(maxUserNameSize), 0, 0) +func disconnectNamedPipe(pipe windows.Handle) (err error) { + r1, _, e1 := syscall.SyscallN(procDisconnectNamedPipe.Addr(), uintptr(pipe)) if r1 == 0 { err = errnoErr(e1) } return } -func getNamedPipeInfo(pipe syscall.Handle, flags *uint32, outSize *uint32, inSize *uint32, maxInstances *uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procGetNamedPipeInfo.Addr(), 5, uintptr(pipe), uintptr(unsafe.Pointer(flags)), uintptr(unsafe.Pointer(outSize)), uintptr(unsafe.Pointer(inSize)), uintptr(unsafe.Pointer(maxInstances)), 0) - if r1 == 0 { - err = errnoErr(e1) - } +func getCurrentThread() (h windows.Handle) { + r0, _, _ := syscall.SyscallN(procGetCurrentThread.Addr()) + h = windows.Handle(r0) return } -func getQueuedCompletionStatus(port syscall.Handle, bytes *uint32, key *uintptr, o **ioOperation, timeout uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procGetQueuedCompletionStatus.Addr(), 5, uintptr(port), uintptr(unsafe.Pointer(bytes)), uintptr(unsafe.Pointer(key)), uintptr(unsafe.Pointer(o)), uintptr(timeout), 0) +func getNamedPipeHandleState(pipe windows.Handle, state *uint32, curInstances *uint32, maxCollectionCount *uint32, collectDataTimeout *uint32, userName *uint16, maxUserNameSize uint32) (err error) { + r1, _, e1 := syscall.SyscallN(procGetNamedPipeHandleStateW.Addr(), uintptr(pipe), uintptr(unsafe.Pointer(state)), uintptr(unsafe.Pointer(curInstances)), uintptr(unsafe.Pointer(maxCollectionCount)), uintptr(unsafe.Pointer(collectDataTimeout)), uintptr(unsafe.Pointer(userName)), uintptr(maxUserNameSize)) if r1 == 0 { err = errnoErr(e1) } return } -func localAlloc(uFlags uint32, length uint32) (ptr uintptr) { - r0, _, _ := syscall.Syscall(procLocalAlloc.Addr(), 2, uintptr(uFlags), uintptr(length), 0) - ptr = uintptr(r0) +func getNamedPipeInfo(pipe windows.Handle, flags *uint32, outSize *uint32, inSize *uint32, maxInstances *uint32) (err error) { + r1, _, e1 := syscall.SyscallN(procGetNamedPipeInfo.Addr(), uintptr(pipe), uintptr(unsafe.Pointer(flags)), uintptr(unsafe.Pointer(outSize)), uintptr(unsafe.Pointer(inSize)), uintptr(unsafe.Pointer(maxInstances))) + if r1 == 0 { + err = errnoErr(e1) + } return } -func localFree(mem uintptr) { - syscall.Syscall(procLocalFree.Addr(), 1, uintptr(mem), 0, 0) +func getQueuedCompletionStatus(port windows.Handle, bytes *uint32, key *uintptr, o **ioOperation, timeout uint32) (err error) { + r1, _, e1 := syscall.SyscallN(procGetQueuedCompletionStatus.Addr(), uintptr(port), uintptr(unsafe.Pointer(bytes)), uintptr(unsafe.Pointer(key)), uintptr(unsafe.Pointer(o)), uintptr(timeout)) + if r1 == 0 { + err = errnoErr(e1) + } return } -func setFileCompletionNotificationModes(h syscall.Handle, flags uint8) (err error) { - r1, _, e1 := syscall.Syscall(procSetFileCompletionNotificationModes.Addr(), 2, uintptr(h), uintptr(flags), 0) +func setFileCompletionNotificationModes(h windows.Handle, flags uint8) (err error) { + r1, _, e1 := syscall.SyscallN(procSetFileCompletionNotificationModes.Addr(), uintptr(h), uintptr(flags)) if r1 == 0 { err = errnoErr(e1) } return } -func ntCreateNamedPipeFile(pipe *syscall.Handle, access uint32, oa *objectAttributes, iosb *ioStatusBlock, share uint32, disposition uint32, options uint32, typ uint32, readMode uint32, completionMode uint32, maxInstances uint32, inboundQuota uint32, outputQuota uint32, timeout *int64) (status ntStatus) { - r0, _, _ := syscall.Syscall15(procNtCreateNamedPipeFile.Addr(), 14, uintptr(unsafe.Pointer(pipe)), uintptr(access), uintptr(unsafe.Pointer(oa)), uintptr(unsafe.Pointer(iosb)), uintptr(share), uintptr(disposition), uintptr(options), uintptr(typ), uintptr(readMode), uintptr(completionMode), uintptr(maxInstances), uintptr(inboundQuota), uintptr(outputQuota), uintptr(unsafe.Pointer(timeout)), 0) +func ntCreateNamedPipeFile(pipe *windows.Handle, access ntAccessMask, oa *objectAttributes, iosb *ioStatusBlock, share ntFileShareMode, disposition ntFileCreationDisposition, options ntFileOptions, typ uint32, readMode uint32, completionMode uint32, maxInstances uint32, inboundQuota uint32, outputQuota uint32, timeout *int64) (status ntStatus) { + r0, _, _ := syscall.SyscallN(procNtCreateNamedPipeFile.Addr(), uintptr(unsafe.Pointer(pipe)), uintptr(access), uintptr(unsafe.Pointer(oa)), uintptr(unsafe.Pointer(iosb)), uintptr(share), uintptr(disposition), uintptr(options), uintptr(typ), uintptr(readMode), uintptr(completionMode), uintptr(maxInstances), uintptr(inboundQuota), uintptr(outputQuota), uintptr(unsafe.Pointer(timeout))) status = ntStatus(r0) return } func rtlDefaultNpAcl(dacl *uintptr) (status ntStatus) { - r0, _, _ := syscall.Syscall(procRtlDefaultNpAcl.Addr(), 1, uintptr(unsafe.Pointer(dacl)), 0, 0) + r0, _, _ := syscall.SyscallN(procRtlDefaultNpAcl.Addr(), uintptr(unsafe.Pointer(dacl))) status = ntStatus(r0) return } func rtlDosPathNameToNtPathName(name *uint16, ntName *unicodeString, filePart uintptr, reserved uintptr) (status ntStatus) { - r0, _, _ := syscall.Syscall6(procRtlDosPathNameToNtPathName_U.Addr(), 4, uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(ntName)), uintptr(filePart), uintptr(reserved), 0, 0) + r0, _, _ := syscall.SyscallN(procRtlDosPathNameToNtPathName_U.Addr(), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(ntName)), uintptr(filePart), uintptr(reserved)) status = ntStatus(r0) return } func rtlNtStatusToDosError(status ntStatus) (winerr error) { - r0, _, _ := syscall.Syscall(procRtlNtStatusToDosErrorNoTeb.Addr(), 1, uintptr(status), 0, 0) + r0, _, _ := syscall.SyscallN(procRtlNtStatusToDosErrorNoTeb.Addr(), uintptr(status)) if r0 != 0 { winerr = syscall.Errno(r0) } return } -func wsaGetOverlappedResult(h syscall.Handle, o *syscall.Overlapped, bytes *uint32, wait bool, flags *uint32) (err error) { +func wsaGetOverlappedResult(h windows.Handle, o *windows.Overlapped, bytes *uint32, wait bool, flags *uint32) (err error) { var _p0 uint32 if wait { _p0 = 1 } - r1, _, e1 := syscall.Syscall6(procWSAGetOverlappedResult.Addr(), 5, uintptr(h), uintptr(unsafe.Pointer(o)), uintptr(unsafe.Pointer(bytes)), uintptr(_p0), uintptr(unsafe.Pointer(flags)), 0) + r1, _, e1 := syscall.SyscallN(procWSAGetOverlappedResult.Addr(), uintptr(h), uintptr(unsafe.Pointer(o)), uintptr(unsafe.Pointer(bytes)), uintptr(_p0), uintptr(unsafe.Pointer(flags))) if r1 == 0 { err = errnoErr(e1) } diff --git a/vendor/github.com/ProtonMail/go-crypto/internal/byteutil/byteutil.go b/vendor/github.com/ProtonMail/go-crypto/internal/byteutil/byteutil.go index affb74a764..d558b9bd82 100644 --- a/vendor/github.com/ProtonMail/go-crypto/internal/byteutil/byteutil.go +++ b/vendor/github.com/ProtonMail/go-crypto/internal/byteutil/byteutil.go @@ -49,16 +49,16 @@ func ShiftNBytesLeft(dst, x []byte, n int) { dst = append(dst, make([]byte, n/8)...) } -// XorBytesMut assumes equal input length, replaces X with X XOR Y +// XorBytesMut replaces X with X XOR Y. len(X) must be >= len(Y). func XorBytesMut(X, Y []byte) { - for i := 0; i < len(X); i++ { + for i := 0; i < len(Y); i++ { X[i] ^= Y[i] } } -// XorBytes assumes equal input length, puts X XOR Y into Z +// XorBytes puts X XOR Y into Z. len(Z) and len(X) must be >= len(Y). func XorBytes(Z, X, Y []byte) { - for i := 0; i < len(X); i++ { + for i := 0; i < len(Y); i++ { Z[i] = X[i] ^ Y[i] } } diff --git a/vendor/github.com/ProtonMail/go-crypto/ocb/ocb.go b/vendor/github.com/ProtonMail/go-crypto/ocb/ocb.go index 5022285b44..24f893017b 100644 --- a/vendor/github.com/ProtonMail/go-crypto/ocb/ocb.go +++ b/vendor/github.com/ProtonMail/go-crypto/ocb/ocb.go @@ -109,8 +109,10 @@ func (o *ocb) Seal(dst, nonce, plaintext, adata []byte) []byte { if len(nonce) > o.nonceSize { panic("crypto/ocb: Incorrect nonce length given to OCB") } - ret, out := byteutil.SliceForAppend(dst, len(plaintext)+o.tagSize) - o.crypt(enc, out, nonce, adata, plaintext) + sep := len(plaintext) + ret, out := byteutil.SliceForAppend(dst, sep+o.tagSize) + tag := o.crypt(enc, out[:sep], nonce, adata, plaintext) + copy(out[sep:], tag) return ret } @@ -122,12 +124,10 @@ func (o *ocb) Open(dst, nonce, ciphertext, adata []byte) ([]byte, error) { return nil, ocbError("Ciphertext shorter than tag length") } sep := len(ciphertext) - o.tagSize - ret, out := byteutil.SliceForAppend(dst, len(ciphertext)) + ret, out := byteutil.SliceForAppend(dst, sep) ciphertextData := ciphertext[:sep] - tag := ciphertext[sep:] - o.crypt(dec, out, nonce, adata, ciphertextData) - if subtle.ConstantTimeCompare(ret[sep:], tag) == 1 { - ret = ret[:sep] + tag := o.crypt(dec, out, nonce, adata, ciphertextData) + if subtle.ConstantTimeCompare(tag, ciphertext[sep:]) == 1 { return ret, nil } for i := range out { @@ -137,7 +137,8 @@ func (o *ocb) Open(dst, nonce, ciphertext, adata []byte) ([]byte, error) { } // On instruction enc (resp. dec), crypt is the encrypt (resp. decrypt) -// function. It returns the resulting plain/ciphertext with the tag appended. +// function. It writes the resulting plain/ciphertext into Y and returns +// the tag. func (o *ocb) crypt(instruction int, Y, nonce, adata, X []byte) []byte { // // Consider X as a sequence of 128-bit blocks @@ -194,13 +195,14 @@ func (o *ocb) crypt(instruction int, Y, nonce, adata, X []byte) []byte { byteutil.XorBytesMut(offset, o.mask.L[bits.TrailingZeros(uint(i+1))]) blockX := X[i*blockSize : (i+1)*blockSize] blockY := Y[i*blockSize : (i+1)*blockSize] - byteutil.XorBytes(blockY, blockX, offset) switch instruction { case enc: + byteutil.XorBytesMut(checksum, blockX) + byteutil.XorBytes(blockY, blockX, offset) o.block.Encrypt(blockY, blockY) byteutil.XorBytesMut(blockY, offset) - byteutil.XorBytesMut(checksum, blockX) case dec: + byteutil.XorBytes(blockY, blockX, offset) o.block.Decrypt(blockY, blockY) byteutil.XorBytesMut(blockY, offset) byteutil.XorBytesMut(checksum, blockY) @@ -216,31 +218,24 @@ func (o *ocb) crypt(instruction int, Y, nonce, adata, X []byte) []byte { o.block.Encrypt(pad, offset) chunkX := X[blockSize*m:] chunkY := Y[blockSize*m : len(X)] - byteutil.XorBytes(chunkY, chunkX, pad[:len(chunkX)]) - // P_* || bit(1) || zeroes(127) - len(P_*) switch instruction { case enc: - paddedY := append(chunkX, byte(128)) - paddedY = append(paddedY, make([]byte, blockSize-len(chunkX)-1)...) - byteutil.XorBytesMut(checksum, paddedY) + byteutil.XorBytesMut(checksum, chunkX) + checksum[len(chunkX)] ^= 128 + byteutil.XorBytes(chunkY, chunkX, pad[:len(chunkX)]) + // P_* || bit(1) || zeroes(127) - len(P_*) case dec: - paddedX := append(chunkY, byte(128)) - paddedX = append(paddedX, make([]byte, blockSize-len(chunkY)-1)...) - byteutil.XorBytesMut(checksum, paddedX) + byteutil.XorBytes(chunkY, chunkX, pad[:len(chunkX)]) + // P_* || bit(1) || zeroes(127) - len(P_*) + byteutil.XorBytesMut(checksum, chunkY) + checksum[len(chunkY)] ^= 128 } - byteutil.XorBytes(tag, checksum, offset) - byteutil.XorBytesMut(tag, o.mask.lDol) - o.block.Encrypt(tag, tag) - byteutil.XorBytesMut(tag, o.hash(adata)) - copy(Y[blockSize*m+len(chunkY):], tag[:o.tagSize]) - } else { - byteutil.XorBytes(tag, checksum, offset) - byteutil.XorBytesMut(tag, o.mask.lDol) - o.block.Encrypt(tag, tag) - byteutil.XorBytesMut(tag, o.hash(adata)) - copy(Y[blockSize*m:], tag[:o.tagSize]) } - return Y + byteutil.XorBytes(tag, checksum, offset) + byteutil.XorBytesMut(tag, o.mask.lDol) + o.block.Encrypt(tag, tag) + byteutil.XorBytesMut(tag, o.hash(adata)) + return tag[:o.tagSize] } // This hash function is used to compute the tag. Per design, on empty input it diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/armor/encode.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/armor/encode.go index 112f98b835..550efddf05 100644 --- a/vendor/github.com/ProtonMail/go-crypto/openpgp/armor/encode.go +++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/armor/encode.go @@ -7,6 +7,7 @@ package armor import ( "encoding/base64" "io" + "sort" ) var armorHeaderSep = []byte(": ") @@ -159,8 +160,15 @@ func encode(out io.Writer, blockType string, headers map[string]string, checksum return } - for k, v := range headers { - err = writeSlices(out, []byte(k), armorHeaderSep, []byte(v), newline) + keys := make([]string, len(headers)) + i := 0 + for k := range headers { + keys[i] = k + i++ + } + sort.Strings(keys) + for _, k := range keys { + err = writeSlices(out, []byte(k), armorHeaderSep, []byte(headers[k]), newline) if err != nil { return } diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/errors/errors.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/errors/errors.go index 0eb3937b39..e44b45734d 100644 --- a/vendor/github.com/ProtonMail/go-crypto/openpgp/errors/errors.go +++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/errors/errors.go @@ -6,6 +6,7 @@ package errors // import "github.com/ProtonMail/go-crypto/openpgp/errors" import ( + "fmt" "strconv" ) @@ -178,3 +179,22 @@ type ErrMalformedMessage string func (dke ErrMalformedMessage) Error() string { return "openpgp: malformed message " + string(dke) } + +// ErrEncryptionKeySelection is returned if encryption key selection fails (v2 API). +type ErrEncryptionKeySelection struct { + PrimaryKeyId string + PrimaryKeyErr error + EncSelectionKeyId *string + EncSelectionErr error +} + +func (eks ErrEncryptionKeySelection) Error() string { + prefix := fmt.Sprintf("openpgp: key selection for primary key %s:", eks.PrimaryKeyId) + if eks.PrimaryKeyErr != nil { + return fmt.Sprintf("%s invalid primary key: %s", prefix, eks.PrimaryKeyErr) + } + if eks.EncSelectionKeyId != nil { + return fmt.Sprintf("%s invalid encryption key %s: %s", prefix, *eks.EncSelectionKeyId, eks.EncSelectionErr) + } + return fmt.Sprintf("%s no encryption key: %s", prefix, eks.EncSelectionErr) +} diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/aead_crypter.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/aead_crypter.go index 2eecd062f5..5e46046563 100644 --- a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/aead_crypter.go +++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/aead_crypter.go @@ -3,7 +3,6 @@ package packet import ( - "bytes" "crypto/cipher" "encoding/binary" "io" @@ -15,12 +14,11 @@ import ( type aeadCrypter struct { aead cipher.AEAD chunkSize int - initialNonce []byte + nonce []byte associatedData []byte // Chunk-independent associated data chunkIndex []byte // Chunk counter packetTag packetType // SEIP packet (v2) or AEAD Encrypted Data packet bytesProcessed int // Amount of plaintext bytes encrypted/decrypted - buffer bytes.Buffer // Buffered bytes across chunks } // computeNonce takes the incremental index and computes an eXclusive OR with @@ -28,12 +26,12 @@ type aeadCrypter struct { // 5.16.1 and 5.16.2). It returns the resulting nonce. func (wo *aeadCrypter) computeNextNonce() (nonce []byte) { if wo.packetTag == packetTypeSymmetricallyEncryptedIntegrityProtected { - return append(wo.initialNonce, wo.chunkIndex...) + return wo.nonce } - nonce = make([]byte, len(wo.initialNonce)) - copy(nonce, wo.initialNonce) - offset := len(wo.initialNonce) - 8 + nonce = make([]byte, len(wo.nonce)) + copy(nonce, wo.nonce) + offset := len(wo.nonce) - 8 for i := 0; i < 8; i++ { nonce[i+offset] ^= wo.chunkIndex[i] } @@ -62,8 +60,9 @@ func (wo *aeadCrypter) incrementIndex() error { type aeadDecrypter struct { aeadCrypter // Embedded ciphertext opener reader io.Reader // 'reader' is a partialLengthReader + chunkBytes []byte peekedBytes []byte // Used to detect last chunk - eof bool + buffer []byte // Buffered decrypted bytes } // Read decrypts bytes and reads them into dst. It decrypts when necessary and @@ -71,59 +70,44 @@ type aeadDecrypter struct { // and an error. func (ar *aeadDecrypter) Read(dst []byte) (n int, err error) { // Return buffered plaintext bytes from previous calls - if ar.buffer.Len() > 0 { - return ar.buffer.Read(dst) - } - - // Return EOF if we've previously validated the final tag - if ar.eof { - return 0, io.EOF + if len(ar.buffer) > 0 { + n = copy(dst, ar.buffer) + ar.buffer = ar.buffer[n:] + return } // Read a chunk tagLen := ar.aead.Overhead() - cipherChunkBuf := new(bytes.Buffer) - _, errRead := io.CopyN(cipherChunkBuf, ar.reader, int64(ar.chunkSize+tagLen)) - cipherChunk := cipherChunkBuf.Bytes() - if errRead != nil && errRead != io.EOF { + copy(ar.chunkBytes, ar.peekedBytes) // Copy bytes peeked in previous chunk or in initialization + bytesRead, errRead := io.ReadFull(ar.reader, ar.chunkBytes[tagLen:]) + if errRead != nil && errRead != io.EOF && errRead != io.ErrUnexpectedEOF { return 0, errRead } - if len(cipherChunk) > 0 { - decrypted, errChunk := ar.openChunk(cipherChunk) + if bytesRead > 0 { + ar.peekedBytes = ar.chunkBytes[bytesRead:bytesRead+tagLen] + + decrypted, errChunk := ar.openChunk(ar.chunkBytes[:bytesRead]) if errChunk != nil { return 0, errChunk } // Return decrypted bytes, buffering if necessary - if len(dst) < len(decrypted) { - n = copy(dst, decrypted[:len(dst)]) - ar.buffer.Write(decrypted[len(dst):]) - } else { - n = copy(dst, decrypted) - } + n = copy(dst, decrypted) + ar.buffer = decrypted[n:] + return } - // Check final authentication tag - if errRead == io.EOF { - errChunk := ar.validateFinalTag(ar.peekedBytes) - if errChunk != nil { - return n, errChunk - } - ar.eof = true // Mark EOF for when we've returned all buffered data - } - return + return 0, io.EOF } -// Close is noOp. The final authentication tag of the stream was already -// checked in the last Read call. In the future, this function could be used to -// wipe the reader and peeked, decrypted bytes, if necessary. +// Close checks the final authentication tag of the stream. +// In the future, this function could also be used to wipe the reader +// and peeked & decrypted bytes, if necessary. func (ar *aeadDecrypter) Close() (err error) { - if !ar.eof { - errChunk := ar.validateFinalTag(ar.peekedBytes) - if errChunk != nil { - return errChunk - } + errChunk := ar.validateFinalTag(ar.peekedBytes) + if errChunk != nil { + return errChunk } return nil } @@ -132,20 +116,13 @@ func (ar *aeadDecrypter) Close() (err error) { // the underlying plaintext and an error. It accesses peeked bytes from next // chunk, to identify the last chunk and decrypt/validate accordingly. func (ar *aeadDecrypter) openChunk(data []byte) ([]byte, error) { - tagLen := ar.aead.Overhead() - // Restore carried bytes from last call - chunkExtra := append(ar.peekedBytes, data...) - // 'chunk' contains encrypted bytes, followed by an authentication tag. - chunk := chunkExtra[:len(chunkExtra)-tagLen] - ar.peekedBytes = chunkExtra[len(chunkExtra)-tagLen:] - adata := ar.associatedData if ar.aeadCrypter.packetTag == packetTypeAEADEncrypted { adata = append(ar.associatedData, ar.chunkIndex...) } nonce := ar.computeNextNonce() - plainChunk, err := ar.aead.Open(nil, nonce, chunk, adata) + plainChunk, err := ar.aead.Open(data[:0:len(data)], nonce, data, adata) if err != nil { return nil, errors.ErrAEADTagVerification } @@ -183,27 +160,29 @@ func (ar *aeadDecrypter) validateFinalTag(tag []byte) error { type aeadEncrypter struct { aeadCrypter // Embedded plaintext sealer writer io.WriteCloser // 'writer' is a partialLengthWriter + chunkBytes []byte + offset int } // Write encrypts and writes bytes. It encrypts when necessary and buffers extra // plaintext bytes for next call. When the stream is finished, Close() MUST be // called to append the final tag. func (aw *aeadEncrypter) Write(plaintextBytes []byte) (n int, err error) { - // Append plaintextBytes to existing buffered bytes - n, err = aw.buffer.Write(plaintextBytes) - if err != nil { - return n, err - } - // Encrypt and write chunks - for aw.buffer.Len() >= aw.chunkSize { - plainChunk := aw.buffer.Next(aw.chunkSize) - encryptedChunk, err := aw.sealChunk(plainChunk) - if err != nil { - return n, err - } - _, err = aw.writer.Write(encryptedChunk) - if err != nil { - return n, err + for n != len(plaintextBytes) { + copied := copy(aw.chunkBytes[aw.offset:aw.chunkSize], plaintextBytes[n:]) + n += copied + aw.offset += copied + + if aw.offset == aw.chunkSize { + encryptedChunk, err := aw.sealChunk(aw.chunkBytes[:aw.offset]) + if err != nil { + return n, err + } + _, err = aw.writer.Write(encryptedChunk) + if err != nil { + return n, err + } + aw.offset = 0 } } return @@ -215,9 +194,8 @@ func (aw *aeadEncrypter) Write(plaintextBytes []byte) (n int, err error) { func (aw *aeadEncrypter) Close() (err error) { // Encrypt and write a chunk if there's buffered data left, or if we haven't // written any chunks yet. - if aw.buffer.Len() > 0 || aw.bytesProcessed == 0 { - plainChunk := aw.buffer.Bytes() - lastEncryptedChunk, err := aw.sealChunk(plainChunk) + if aw.offset > 0 || aw.bytesProcessed == 0 { + lastEncryptedChunk, err := aw.sealChunk(aw.chunkBytes[:aw.offset]) if err != nil { return err } @@ -263,7 +241,7 @@ func (aw *aeadEncrypter) sealChunk(data []byte) ([]byte, error) { } nonce := aw.computeNextNonce() - encrypted := aw.aead.Seal(nil, nonce, data, adata) + encrypted := aw.aead.Seal(data[:0], nonce, data, adata) aw.bytesProcessed += len(data) if err := aw.aeadCrypter.incrementIndex(); err != nil { return nil, err diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/aead_encrypted.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/aead_encrypted.go index 98bd876bf2..583765d87c 100644 --- a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/aead_encrypted.go +++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/aead_encrypted.go @@ -65,24 +65,28 @@ func (ae *AEADEncrypted) decrypt(key []byte) (io.ReadCloser, error) { blockCipher := ae.cipher.new(key) aead := ae.mode.new(blockCipher) // Carry the first tagLen bytes + chunkSize := decodeAEADChunkSize(ae.chunkSizeByte) tagLen := ae.mode.TagLength() - peekedBytes := make([]byte, tagLen) + chunkBytes := make([]byte, chunkSize+tagLen*2) + peekedBytes := chunkBytes[chunkSize+tagLen:] n, err := io.ReadFull(ae.Contents, peekedBytes) if n < tagLen || (err != nil && err != io.EOF) { return nil, errors.AEADError("Not enough data to decrypt:" + err.Error()) } - chunkSize := decodeAEADChunkSize(ae.chunkSizeByte) + return &aeadDecrypter{ aeadCrypter: aeadCrypter{ aead: aead, chunkSize: chunkSize, - initialNonce: ae.initialNonce, + nonce: ae.initialNonce, associatedData: ae.associatedData(), chunkIndex: make([]byte, 8), packetTag: packetTypeAEADEncrypted, }, reader: ae.Contents, - peekedBytes: peekedBytes}, nil + chunkBytes: chunkBytes, + peekedBytes: peekedBytes, + }, nil } // associatedData for chunks: tag, version, cipher, mode, chunk size byte diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/config.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/config.go index 8bf8e6e51f..257398d9dd 100644 --- a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/config.go +++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/config.go @@ -173,6 +173,11 @@ type Config struct { // weaknesses in the hash algo, potentially hindering e.g. some chosen-prefix attacks. // The default behavior, when the config or flag is nil, is to enable the feature. NonDeterministicSignaturesViaNotation *bool + + // InsecureAllowAllKeyFlagsWhenMissing determines how a key without valid key flags is handled. + // When set to true, a key without flags is treated as if all flags are enabled. + // This behavior is consistent with GPG. + InsecureAllowAllKeyFlagsWhenMissing bool } func (c *Config) Random() io.Reader { @@ -403,6 +408,13 @@ func (c *Config) RandomizeSignaturesViaNotation() bool { return *c.NonDeterministicSignaturesViaNotation } +func (c *Config) AllowAllKeyFlagsWhenMissing() bool { + if c == nil { + return false + } + return c.InsecureAllowAllKeyFlagsWhenMissing +} + // BoolPointer is a helper function to set a boolean pointer in the Config. // e.g., config.CheckPacketSequence = BoolPointer(true) func BoolPointer(value bool) *bool { diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/public_key.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/public_key.go index f8da781bbe..e2813396e3 100644 --- a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/public_key.go +++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/public_key.go @@ -1048,12 +1048,17 @@ func (pk *PublicKey) VerifyDirectKeySignature(sig *Signature) (err error) { // KeyIdString returns the public key's fingerprint in capital hex // (e.g. "6C7EE1B8621CC013"). func (pk *PublicKey) KeyIdString() string { - return fmt.Sprintf("%X", pk.Fingerprint[12:20]) + return fmt.Sprintf("%016X", pk.KeyId) } // KeyIdShortString returns the short form of public key's fingerprint // in capital hex, as shown by gpg --list-keys (e.g. "621CC013"). +// This function will return the full key id for v5 and v6 keys +// since the short key id is undefined for them. func (pk *PublicKey) KeyIdShortString() string { + if pk.Version >= 5 { + return pk.KeyIdString() + } return fmt.Sprintf("%X", pk.Fingerprint[16:20]) } diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/signature.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/signature.go index 3a4b366d87..84dd3b86f8 100644 --- a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/signature.go +++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/signature.go @@ -1288,7 +1288,9 @@ func (sig *Signature) buildSubpackets(issuer PublicKey) (subpackets []outputSubp if sig.IssuerKeyId != nil && sig.Version == 4 { keyId := make([]byte, 8) binary.BigEndian.PutUint64(keyId, *sig.IssuerKeyId) - subpackets = append(subpackets, outputSubpacket{true, issuerSubpacket, true, keyId}) + // Note: making this critical breaks RPM <=4.16. + // See: https://github.com/ProtonMail/go-crypto/issues/263 + subpackets = append(subpackets, outputSubpacket{true, issuerSubpacket, false, keyId}) } // Notation Data for _, notation := range sig.Notations { diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/symmetrically_encrypted_aead.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/symmetrically_encrypted_aead.go index 3957b2d53e..3ddc4fe4a9 100644 --- a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/symmetrically_encrypted_aead.go +++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/symmetrically_encrypted_aead.go @@ -70,8 +70,10 @@ func (se *SymmetricallyEncrypted) decryptAead(inputKey []byte) (io.ReadCloser, e aead, nonce := getSymmetricallyEncryptedAeadInstance(se.Cipher, se.Mode, inputKey, se.Salt[:], se.associatedData()) // Carry the first tagLen bytes + chunkSize := decodeAEADChunkSize(se.ChunkSizeByte) tagLen := se.Mode.TagLength() - peekedBytes := make([]byte, tagLen) + chunkBytes := make([]byte, chunkSize+tagLen*2) + peekedBytes := chunkBytes[chunkSize+tagLen:] n, err := io.ReadFull(se.Contents, peekedBytes) if n < tagLen || (err != nil && err != io.EOF) { return nil, errors.StructuralError("not enough data to decrypt:" + err.Error()) @@ -81,12 +83,13 @@ func (se *SymmetricallyEncrypted) decryptAead(inputKey []byte) (io.ReadCloser, e aeadCrypter: aeadCrypter{ aead: aead, chunkSize: decodeAEADChunkSize(se.ChunkSizeByte), - initialNonce: nonce, + nonce: nonce, associatedData: se.associatedData(), - chunkIndex: make([]byte, 8), + chunkIndex: nonce[len(nonce)-8:], packetTag: packetTypeSymmetricallyEncryptedIntegrityProtected, }, reader: se.Contents, + chunkBytes: chunkBytes, peekedBytes: peekedBytes, }, nil } @@ -130,16 +133,20 @@ func serializeSymmetricallyEncryptedAead(ciphertext io.WriteCloser, cipherSuite aead, nonce := getSymmetricallyEncryptedAeadInstance(cipherSuite.Cipher, cipherSuite.Mode, inputKey, salt, prefix) + chunkSize := decodeAEADChunkSize(chunkSizeByte) + tagLen := aead.Overhead() + chunkBytes := make([]byte, chunkSize+tagLen) return &aeadEncrypter{ aeadCrypter: aeadCrypter{ aead: aead, - chunkSize: decodeAEADChunkSize(chunkSizeByte), + chunkSize: chunkSize, associatedData: prefix, - chunkIndex: make([]byte, 8), - initialNonce: nonce, + nonce: nonce, + chunkIndex: nonce[len(nonce)-8:], packetTag: packetTypeSymmetricallyEncryptedIntegrityProtected, }, - writer: ciphertext, + writer: ciphertext, + chunkBytes: chunkBytes, }, nil } @@ -149,10 +156,10 @@ func getSymmetricallyEncryptedAeadInstance(c CipherFunction, mode AEADMode, inpu encryptionKey := make([]byte, c.KeySize()) _, _ = readFull(hkdfReader, encryptionKey) - // Last 64 bits of nonce are the counter - nonce = make([]byte, mode.IvLength()-8) + nonce = make([]byte, mode.IvLength()) - _, _ = readFull(hkdfReader, nonce) + // Last 64 bits of nonce are the counter + _, _ = readFull(hkdfReader, nonce[:len(nonce)-8]) blockCipher := c.new(encryptionKey) aead = mode.new(blockCipher) diff --git a/vendor/github.com/cyphar/filepath-securejoin/CHANGELOG.md b/vendor/github.com/cyphar/filepath-securejoin/CHANGELOG.md index cb1252b53e..ca0e3c62c7 100644 --- a/vendor/github.com/cyphar/filepath-securejoin/CHANGELOG.md +++ b/vendor/github.com/cyphar/filepath-securejoin/CHANGELOG.md @@ -6,6 +6,51 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] ## +## [0.4.1] - 2025-01-28 ## + +### Fixed ### +- The restrictions added for `root` paths passed to `SecureJoin` in 0.4.0 was + found to be too strict and caused some regressions when folks tried to + update, so this restriction has been relaxed to only return an error if the + path contains a `..` component. We still recommend users use `filepath.Clean` + (and even `filepath.EvalSymlinks`) on the `root` path they are using, but at + least you will no longer be punished for "trivial" unclean paths. + +## [0.4.0] - 2025-01-13 ## + +### Breaking #### +- `SecureJoin(VFS)` will now return an error if the provided `root` is not a + `filepath.Clean`'d path. + + While it is ultimately the responsibility of the caller to ensure the root is + a safe path to use, passing a path like `/symlink/..` as a root would result + in the `SecureJoin`'d path being placed in `/` even though `/symlink/..` + might be a different directory, and so we should more strongly discourage + such usage. + + All major users of `securejoin.SecureJoin` already ensure that the paths they + provide are safe (and this is ultimately a question of user error), but + removing this foot-gun is probably a good idea. Of course, this is + necessarily a breaking API change (though we expect no real users to be + affected by it). + + Thanks to [Erik Sjölund](https://github.com/eriksjolund), who initially + reported this issue as a possible security issue. + +- `MkdirAll` and `MkdirHandle` now take an `os.FileMode`-style mode argument + instead of a raw `unix.S_*`-style mode argument, which may cause compile-time + type errors depending on how you use `filepath-securejoin`. For most users, + there will be no change in behaviour aside from the type change (as the + bottom `0o777` bits are the same in both formats, and most users are probably + only using those bits). + + However, if you were using `unix.S_ISVTX` to set the sticky bit with + `MkdirAll(Handle)` you will need to switch to `os.ModeSticky` otherwise you + will get a runtime error with this update. In addition, the error message you + will get from passing `unix.S_ISUID` and `unix.S_ISGID` will be different as + they are treated as invalid bits now (note that previously passing said bits + was also an error). + ## [0.3.6] - 2024-12-17 ## ### Compatibility ### @@ -193,7 +238,9 @@ This is our first release of `github.com/cyphar/filepath-securejoin`, containing a full implementation with a coverage of 93.5% (the only missing cases are the error cases, which are hard to mocktest at the moment). -[Unreleased]: https://github.com/cyphar/filepath-securejoin/compare/v0.3.6...HEAD +[Unreleased]: https://github.com/cyphar/filepath-securejoin/compare/v0.4.1...HEAD +[0.4.1]: https://github.com/cyphar/filepath-securejoin/compare/v0.4.0...v0.4.1 +[0.4.0]: https://github.com/cyphar/filepath-securejoin/compare/v0.3.6...v0.4.0 [0.3.6]: https://github.com/cyphar/filepath-securejoin/compare/v0.3.5...v0.3.6 [0.3.5]: https://github.com/cyphar/filepath-securejoin/compare/v0.3.4...v0.3.5 [0.3.4]: https://github.com/cyphar/filepath-securejoin/compare/v0.3.3...v0.3.4 diff --git a/vendor/github.com/cyphar/filepath-securejoin/VERSION b/vendor/github.com/cyphar/filepath-securejoin/VERSION index 449d7e73a9..267577d47e 100644 --- a/vendor/github.com/cyphar/filepath-securejoin/VERSION +++ b/vendor/github.com/cyphar/filepath-securejoin/VERSION @@ -1 +1 @@ -0.3.6 +0.4.1 diff --git a/vendor/github.com/cyphar/filepath-securejoin/join.go b/vendor/github.com/cyphar/filepath-securejoin/join.go index e0ee3f2b57..e6634d4778 100644 --- a/vendor/github.com/cyphar/filepath-securejoin/join.go +++ b/vendor/github.com/cyphar/filepath-securejoin/join.go @@ -1,5 +1,5 @@ // Copyright (C) 2014-2015 Docker Inc & Go Authors. All rights reserved. -// Copyright (C) 2017-2024 SUSE LLC. All rights reserved. +// Copyright (C) 2017-2025 SUSE LLC. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. @@ -24,6 +24,31 @@ func IsNotExist(err error) bool { return errors.Is(err, os.ErrNotExist) || errors.Is(err, syscall.ENOTDIR) || errors.Is(err, syscall.ENOENT) } +// errUnsafeRoot is returned if the user provides SecureJoinVFS with a path +// that contains ".." components. +var errUnsafeRoot = errors.New("root path provided to SecureJoin contains '..' components") + +// stripVolume just gets rid of the Windows volume included in a path. Based on +// some godbolt tests, the Go compiler is smart enough to make this a no-op on +// Linux. +func stripVolume(path string) string { + return path[len(filepath.VolumeName(path)):] +} + +// hasDotDot checks if the path contains ".." components in a platform-agnostic +// way. +func hasDotDot(path string) bool { + // If we are on Windows, strip any volume letters. It turns out that + // C:..\foo may (or may not) be a valid pathname and we need to handle that + // leading "..". + path = stripVolume(path) + // Look for "/../" in the path, but we need to handle leading and trailing + // ".."s by adding separators. Doing this with filepath.Separator is ugly + // so just convert to Unix-style "/" first. + path = filepath.ToSlash(path) + return strings.Contains("/"+path+"/", "/../") +} + // SecureJoinVFS joins the two given path components (similar to [filepath.Join]) except // that the returned path is guaranteed to be scoped inside the provided root // path (when evaluated). Any symbolic links in the path are evaluated with the @@ -46,7 +71,22 @@ func IsNotExist(err error) bool { // provided via direct input or when evaluating symlinks. Therefore: // // "C:\Temp" + "D:\path\to\file.txt" results in "C:\Temp\path\to\file.txt" +// +// If the provided root is not [filepath.Clean] then an error will be returned, +// as such root paths are bordering on somewhat unsafe and using such paths is +// not best practice. We also strongly suggest that any root path is first +// fully resolved using [filepath.EvalSymlinks] or otherwise constructed to +// avoid containing symlink components. Of course, the root also *must not* be +// attacker-controlled. func SecureJoinVFS(root, unsafePath string, vfs VFS) (string, error) { + // The root path must not contain ".." components, otherwise when we join + // the subpath we will end up with a weird path. We could work around this + // in other ways but users shouldn't be giving us non-lexical root paths in + // the first place. + if hasDotDot(root) { + return "", errUnsafeRoot + } + // Use the os.* VFS implementation if none was specified. if vfs == nil { vfs = osVFS{} @@ -59,9 +99,10 @@ func SecureJoinVFS(root, unsafePath string, vfs VFS) (string, error) { linksWalked int ) for remainingPath != "" { - if v := filepath.VolumeName(remainingPath); v != "" { - remainingPath = remainingPath[len(v):] - } + // On Windows, if we managed to end up at a path referencing a volume, + // drop the volume to make sure we don't end up with broken paths or + // escaping the root volume. + remainingPath = stripVolume(remainingPath) // Get the next path component. var part string diff --git a/vendor/github.com/cyphar/filepath-securejoin/mkdir_linux.go b/vendor/github.com/cyphar/filepath-securejoin/mkdir_linux.go index 5e559bb7a8..a17ae3b038 100644 --- a/vendor/github.com/cyphar/filepath-securejoin/mkdir_linux.go +++ b/vendor/github.com/cyphar/filepath-securejoin/mkdir_linux.go @@ -21,6 +21,33 @@ var ( errPossibleAttack = errors.New("possible attack detected") ) +// modePermExt is like os.ModePerm except that it also includes the set[ug]id +// and sticky bits. +const modePermExt = os.ModePerm | os.ModeSetuid | os.ModeSetgid | os.ModeSticky + +//nolint:cyclop // this function needs to handle a lot of cases +func toUnixMode(mode os.FileMode) (uint32, error) { + sysMode := uint32(mode.Perm()) + if mode&os.ModeSetuid != 0 { + sysMode |= unix.S_ISUID + } + if mode&os.ModeSetgid != 0 { + sysMode |= unix.S_ISGID + } + if mode&os.ModeSticky != 0 { + sysMode |= unix.S_ISVTX + } + // We don't allow file type bits. + if mode&os.ModeType != 0 { + return 0, fmt.Errorf("%w %+.3o (%s): type bits not permitted", errInvalidMode, mode, mode) + } + // We don't allow other unknown modes. + if mode&^modePermExt != 0 || sysMode&unix.S_IFMT != 0 { + return 0, fmt.Errorf("%w %+.3o (%s): unknown mode bits", errInvalidMode, mode, mode) + } + return sysMode, nil +} + // MkdirAllHandle is equivalent to [MkdirAll], except that it is safer to use // in two respects: // @@ -39,17 +66,17 @@ var ( // a brand new lookup of unsafePath (such as with [SecureJoin] or openat2) after // doing [MkdirAll]. If you intend to open the directory after creating it, you // should use MkdirAllHandle. -func MkdirAllHandle(root *os.File, unsafePath string, mode int) (_ *os.File, Err error) { - // Make sure there are no os.FileMode bits set. - if mode&^0o7777 != 0 { - return nil, fmt.Errorf("%w for mkdir 0o%.3o", errInvalidMode, mode) +func MkdirAllHandle(root *os.File, unsafePath string, mode os.FileMode) (_ *os.File, Err error) { + unixMode, err := toUnixMode(mode) + if err != nil { + return nil, err } // On Linux, mkdirat(2) (and os.Mkdir) silently ignore the suid and sgid // bits. We could also silently ignore them but since we have very few // users it seems more prudent to return an error so users notice that // these bits will not be set. - if mode&^0o1777 != 0 { - return nil, fmt.Errorf("%w for mkdir 0o%.3o: suid and sgid are ignored by mkdir", errInvalidMode, mode) + if unixMode&^0o1777 != 0 { + return nil, fmt.Errorf("%w for mkdir %+.3o: suid and sgid are ignored by mkdir", errInvalidMode, mode) } // Try to open as much of the path as possible. @@ -104,9 +131,6 @@ func MkdirAllHandle(root *os.File, unsafePath string, mode int) (_ *os.File, Err return nil, fmt.Errorf("%w: yet-to-be-created path %q contains '..' components", unix.ENOENT, remainingPath) } - // Make sure the mode doesn't have any type bits. - mode &^= unix.S_IFMT - // Create the remaining components. for _, part := range remainingParts { switch part { @@ -123,7 +147,7 @@ func MkdirAllHandle(root *os.File, unsafePath string, mode int) (_ *os.File, Err // directory at the same time as us. In that case, just continue on as // if we created it (if the created inode is not a directory, the // following open call will fail). - if err := unix.Mkdirat(int(currentDir.Fd()), part, uint32(mode)); err != nil && !errors.Is(err, unix.EEXIST) { + if err := unix.Mkdirat(int(currentDir.Fd()), part, unixMode); err != nil && !errors.Is(err, unix.EEXIST) { err = &os.PathError{Op: "mkdirat", Path: currentDir.Name() + "/" + part, Err: err} // Make the error a bit nicer if the directory is dead. if deadErr := isDeadInode(currentDir); deadErr != nil { @@ -196,10 +220,7 @@ func MkdirAllHandle(root *os.File, unsafePath string, mode int) (_ *os.File, Err // If you plan to open the directory after you have created it or want to use // an open directory handle as the root, you should use [MkdirAllHandle] instead. // This function is a wrapper around [MkdirAllHandle]. -// -// NOTE: The mode argument must be set the unix mode bits (unix.S_I...), not -// the Go generic mode bits ([os.FileMode]...). -func MkdirAll(root, unsafePath string, mode int) error { +func MkdirAll(root, unsafePath string, mode os.FileMode) error { rootDir, err := os.OpenFile(root, unix.O_PATH|unix.O_DIRECTORY|unix.O_CLOEXEC, 0) if err != nil { return err diff --git a/vendor/github.com/go-git/go-git/v5/options.go b/vendor/github.com/go-git/go-git/v5/options.go index 3cd0f952c3..e2c77edca9 100644 --- a/vendor/github.com/go-git/go-git/v5/options.go +++ b/vendor/github.com/go-git/go-git/v5/options.go @@ -8,6 +8,7 @@ import ( "time" "github.com/ProtonMail/go-crypto/openpgp" + "github.com/go-git/go-git/v5/config" "github.com/go-git/go-git/v5/plumbing" formatcfg "github.com/go-git/go-git/v5/plumbing/format/config" @@ -72,9 +73,16 @@ type CloneOptions struct { // Tags describe how the tags will be fetched from the remote repository, // by default is AllTags. Tags TagMode - // InsecureSkipTLS skips ssl verify if protocol is https + // InsecureSkipTLS skips SSL verification if protocol is HTTPS. InsecureSkipTLS bool - // CABundle specify additional ca bundle with system cert pool + // ClientCert is the client certificate to use for mutual TLS authentication + // over the HTTPS protocol. + ClientCert []byte + // ClientKey is the client key to use for mutual TLS authentication over + // the HTTPS protocol. + ClientKey []byte + // CABundle specifies an additional CA bundle to use together with the + // system cert pool. CABundle []byte // ProxyOptions provides info required for connecting to a proxy. ProxyOptions transport.ProxyOptions @@ -153,9 +161,16 @@ type PullOptions struct { // Force allows the pull to update a local branch even when the remote // branch does not descend from it. Force bool - // InsecureSkipTLS skips ssl verify if protocol is https + // InsecureSkipTLS skips SSL verification if protocol is HTTPS. InsecureSkipTLS bool - // CABundle specify additional ca bundle with system cert pool + // ClientCert is the client certificate to use for mutual TLS authentication + // over the HTTPS protocol. + ClientCert []byte + // ClientKey is the client key to use for mutual TLS authentication over + // the HTTPS protocol. + ClientKey []byte + // CABundle specifies an additional CA bundle to use together with the + // system cert pool. CABundle []byte // ProxyOptions provides info required for connecting to a proxy. ProxyOptions transport.ProxyOptions @@ -211,9 +226,16 @@ type FetchOptions struct { // Force allows the fetch to update a local branch even when the remote // branch does not descend from it. Force bool - // InsecureSkipTLS skips ssl verify if protocol is https + // InsecureSkipTLS skips SSL verification if protocol is HTTPS. InsecureSkipTLS bool - // CABundle specify additional ca bundle with system cert pool + // ClientCert is the client certificate to use for mutual TLS authentication + // over the HTTPS protocol. + ClientCert []byte + // ClientKey is the client key to use for mutual TLS authentication over + // the HTTPS protocol. + ClientKey []byte + // CABundle specifies an additional CA bundle to use together with the + // system cert pool. CABundle []byte // ProxyOptions provides info required for connecting to a proxy. ProxyOptions transport.ProxyOptions @@ -267,9 +289,16 @@ type PushOptions struct { // Force allows the push to update a remote branch even when the local // branch does not descend from it. Force bool - // InsecureSkipTLS skips ssl verify if protocol is https + // InsecureSkipTLS skips SSL verification if protocol is HTTPS. InsecureSkipTLS bool - // CABundle specify additional ca bundle with system cert pool + // ClientCert is the client certificate to use for mutual TLS authentication + // over the HTTPS protocol. + ClientCert []byte + // ClientKey is the client key to use for mutual TLS authentication over + // the HTTPS protocol. + ClientKey []byte + // CABundle specifies an additional CA bundle to use together with the + // system cert pool. CABundle []byte // RequireRemoteRefs only allows a remote ref to be updated if its current // value is the one specified here. @@ -693,9 +722,16 @@ func (o *CreateTagOptions) loadConfigTagger(r *Repository) error { type ListOptions struct { // Auth credentials, if required, to use with the remote repository. Auth transport.AuthMethod - // InsecureSkipTLS skips ssl verify if protocol is https + // InsecureSkipTLS skips SSL verification if protocol is HTTPS. InsecureSkipTLS bool - // CABundle specify additional ca bundle with system cert pool + // ClientCert is the client certificate to use for mutual TLS authentication + // over the HTTPS protocol. + ClientCert []byte + // ClientKey is the client key to use for mutual TLS authentication over + // the HTTPS protocol. + ClientKey []byte + // CABundle specifies an additional CA bundle to use together with the + // system cert pool. CABundle []byte // PeelingOption defines how peeled objects are handled during a // remote list. diff --git a/vendor/github.com/go-git/go-git/v5/plumbing/format/idxfile/decoder.go b/vendor/github.com/go-git/go-git/v5/plumbing/format/idxfile/decoder.go index 9afdce3011..867553c681 100644 --- a/vendor/github.com/go-git/go-git/v5/plumbing/format/idxfile/decoder.go +++ b/vendor/github.com/go-git/go-git/v5/plumbing/format/idxfile/decoder.go @@ -1,9 +1,11 @@ package idxfile import ( - "bufio" "bytes" + "crypto" + "encoding/hex" "errors" + "fmt" "io" "github.com/go-git/go-git/v5/plumbing/hash" @@ -25,12 +27,15 @@ const ( // Decoder reads and decodes idx files from an input stream. type Decoder struct { - *bufio.Reader + io.Reader + h hash.Hash } // NewDecoder builds a new idx stream decoder, that reads from r. func NewDecoder(r io.Reader) *Decoder { - return &Decoder{bufio.NewReader(r)} + h := hash.New(crypto.SHA1) + tr := io.TeeReader(r, h) + return &Decoder{tr, h} } // Decode reads from the stream and decode the content into the MemoryIndex struct. @@ -45,7 +50,7 @@ func (d *Decoder) Decode(idx *MemoryIndex) error { readObjectNames, readCRC32, readOffsets, - readChecksums, + readPackChecksum, } for _, f := range flow { @@ -54,11 +59,21 @@ func (d *Decoder) Decode(idx *MemoryIndex) error { } } + actual := d.h.Sum(nil) + if err := readIdxChecksum(idx, d); err != nil { + return err + } + + if !bytes.Equal(actual, idx.IdxChecksum[:]) { + return fmt.Errorf("%w: checksum mismatch: %q instead of %q", + ErrMalformedIdxFile, hex.EncodeToString(idx.IdxChecksum[:]), hex.EncodeToString(actual)) + } + return nil } func validateHeader(r io.Reader) error { - var h = make([]byte, 4) + h := make([]byte, 4) if _, err := io.ReadFull(r, h); err != nil { return err } @@ -165,11 +180,15 @@ func readOffsets(idx *MemoryIndex, r io.Reader) error { return nil } -func readChecksums(idx *MemoryIndex, r io.Reader) error { +func readPackChecksum(idx *MemoryIndex, r io.Reader) error { if _, err := io.ReadFull(r, idx.PackfileChecksum[:]); err != nil { return err } + return nil +} + +func readIdxChecksum(idx *MemoryIndex, r io.Reader) error { if _, err := io.ReadFull(r, idx.IdxChecksum[:]); err != nil { return err } diff --git a/vendor/github.com/go-git/go-git/v5/plumbing/format/idxfile/idxfile.go b/vendor/github.com/go-git/go-git/v5/plumbing/format/idxfile/idxfile.go index 9237a74342..136c3e2aca 100644 --- a/vendor/github.com/go-git/go-git/v5/plumbing/format/idxfile/idxfile.go +++ b/vendor/github.com/go-git/go-git/v5/plumbing/format/idxfile/idxfile.go @@ -4,6 +4,7 @@ import ( "bytes" "io" "sort" + "sync" encbin "encoding/binary" @@ -57,8 +58,9 @@ type MemoryIndex struct { PackfileChecksum [hash.Size]byte IdxChecksum [hash.Size]byte - offsetHash map[int64]plumbing.Hash - offsetHashIsFull bool + offsetHash map[int64]plumbing.Hash + offsetBuildOnce sync.Once + mu sync.RWMutex } var _ Index = (*MemoryIndex)(nil) @@ -126,13 +128,13 @@ func (idx *MemoryIndex) FindOffset(h plumbing.Hash) (int64, error) { offset := idx.getOffset(k, i) - if !idx.offsetHashIsFull { - // Save the offset for reverse lookup - if idx.offsetHash == nil { - idx.offsetHash = make(map[int64]plumbing.Hash) - } - idx.offsetHash[int64(offset)] = h + // Save the offset for reverse lookup + idx.mu.Lock() + if idx.offsetHash == nil { + idx.offsetHash = make(map[int64]plumbing.Hash) } + idx.offsetHash[int64(offset)] = h + idx.mu.Unlock() return int64(offset), nil } @@ -173,20 +175,17 @@ func (idx *MemoryIndex) FindHash(o int64) (plumbing.Hash, error) { var hash plumbing.Hash var ok bool - if idx.offsetHash != nil { - if hash, ok = idx.offsetHash[o]; ok { - return hash, nil - } + var genErr error + idx.offsetBuildOnce.Do(func() { + genErr = idx.genOffsetHash() + }) + if genErr != nil { + return plumbing.ZeroHash, genErr } - // Lazily generate the reverse offset/hash map if required. - if !idx.offsetHashIsFull || idx.offsetHash == nil { - if err := idx.genOffsetHash(); err != nil { - return plumbing.ZeroHash, err - } - - hash, ok = idx.offsetHash[o] - } + idx.mu.RLock() + hash, ok = idx.offsetHash[o] + idx.mu.RUnlock() if !ok { return plumbing.ZeroHash, plumbing.ErrObjectNotFound @@ -202,8 +201,7 @@ func (idx *MemoryIndex) genOffsetHash() error { return err } - idx.offsetHash = make(map[int64]plumbing.Hash, count) - idx.offsetHashIsFull = true + offsetHash := make(map[int64]plumbing.Hash, count) var hash plumbing.Hash i := uint32(0) @@ -212,11 +210,15 @@ func (idx *MemoryIndex) genOffsetHash() error { for secondLevel := uint32(0); i < fanoutValue; i++ { copy(hash[:], idx.Names[mappedFirstLevel][secondLevel*objectIDLength:]) offset := int64(idx.getOffset(mappedFirstLevel, int(secondLevel))) - idx.offsetHash[offset] = hash + offsetHash[offset] = hash secondLevel++ } } + idx.mu.Lock() + idx.offsetHash = offsetHash + idx.mu.Unlock() + return nil } diff --git a/vendor/github.com/go-git/go-git/v5/plumbing/format/objfile/reader.go b/vendor/github.com/go-git/go-git/v5/plumbing/format/objfile/reader.go index d7932f4ea8..621883a67d 100644 --- a/vendor/github.com/go-git/go-git/v5/plumbing/format/objfile/reader.go +++ b/vendor/github.com/go-git/go-git/v5/plumbing/format/objfile/reader.go @@ -30,7 +30,7 @@ type Reader struct { func NewReader(r io.Reader) (*Reader, error) { zlib, err := sync.GetZlibReader(r) if err != nil { - return nil, packfile.ErrZLib.AddDetails(err.Error()) + return nil, packfile.ErrZLib.AddDetails("%s", err.Error()) } return &Reader{ diff --git a/vendor/github.com/go-git/go-git/v5/plumbing/format/packfile/parser.go b/vendor/github.com/go-git/go-git/v5/plumbing/format/packfile/parser.go index 62f1d13cb8..2659c27e5f 100644 --- a/vendor/github.com/go-git/go-git/v5/plumbing/format/packfile/parser.go +++ b/vendor/github.com/go-git/go-git/v5/plumbing/format/packfile/parser.go @@ -47,7 +47,6 @@ type Parser struct { oi []*objectInfo oiByHash map[plumbing.Hash]*objectInfo oiByOffset map[int64]*objectInfo - checksum plumbing.Hash cache *cache.BufferLRU // delta content by offset, only used if source is not seekable @@ -133,28 +132,27 @@ func (p *Parser) onFooter(h plumbing.Hash) error { // Parse start decoding phase of the packfile. func (p *Parser) Parse() (plumbing.Hash, error) { if err := p.init(); err != nil { - return plumbing.ZeroHash, err + return plumbing.ZeroHash, wrapEOF(err) } if err := p.indexObjects(); err != nil { - return plumbing.ZeroHash, err + return plumbing.ZeroHash, wrapEOF(err) } - var err error - p.checksum, err = p.scanner.Checksum() + checksum, err := p.scanner.Checksum() if err != nil && err != io.EOF { - return plumbing.ZeroHash, err + return plumbing.ZeroHash, wrapEOF(err) } if err := p.resolveDeltas(); err != nil { - return plumbing.ZeroHash, err + return plumbing.ZeroHash, wrapEOF(err) } - if err := p.onFooter(p.checksum); err != nil { - return plumbing.ZeroHash, err + if err := p.onFooter(checksum); err != nil { + return plumbing.ZeroHash, wrapEOF(err) } - return p.checksum, nil + return checksum, nil } func (p *Parser) init() error { @@ -218,7 +216,7 @@ func (p *Parser) indexObjects() error { if !ok { // can't find referenced object in this pack file // this must be a "thin" pack. - parent = &objectInfo{ //Placeholder parent + parent = &objectInfo{ // Placeholder parent SHA1: oh.Reference, ExternalRef: true, // mark as an external reference that must be resolved Type: plumbing.AnyObject, @@ -531,6 +529,13 @@ func (p *Parser) readData(w io.Writer, o *objectInfo) error { return nil } +func wrapEOF(err error) error { + if err == io.ErrUnexpectedEOF || err == io.EOF { + return fmt.Errorf("%w: %w", ErrMalformedPackFile, err) + } + return err +} + // applyPatchBase applies the patch to target. // // Note that ota will be updated based on the description in resolveObject. @@ -558,15 +563,6 @@ func applyPatchBase(ota *objectInfo, base io.ReaderAt, delta io.Reader, target i return nil } -func getSHA1(t plumbing.ObjectType, data []byte) (plumbing.Hash, error) { - hasher := plumbing.NewHasher(t, int64(len(data))) - if _, err := hasher.Write(data); err != nil { - return plumbing.ZeroHash, err - } - - return hasher.Sum(), nil -} - type objectInfo struct { Offset int64 Length int64 diff --git a/vendor/github.com/go-git/go-git/v5/plumbing/format/packfile/scanner.go b/vendor/github.com/go-git/go-git/v5/plumbing/format/packfile/scanner.go index 730343ee39..8318aae40d 100644 --- a/vendor/github.com/go-git/go-git/v5/plumbing/format/packfile/scanner.go +++ b/vendor/github.com/go-git/go-git/v5/plumbing/format/packfile/scanner.go @@ -3,12 +3,15 @@ package packfile import ( "bufio" "bytes" + "crypto" + "errors" "fmt" - "hash" + gohash "hash" "hash/crc32" "io" "github.com/go-git/go-git/v5/plumbing" + "github.com/go-git/go-git/v5/plumbing/hash" "github.com/go-git/go-git/v5/utils/binary" "github.com/go-git/go-git/v5/utils/ioutil" "github.com/go-git/go-git/v5/utils/sync" @@ -24,6 +27,8 @@ var ( ErrUnsupportedVersion = NewError("unsupported packfile version") // ErrSeekNotSupported returned if seek is not support ErrSeekNotSupported = NewError("not seek support") + // ErrMalformedPackFile is returned by the parser when the pack file is corrupted. + ErrMalformedPackFile = errors.New("malformed PACK file") ) // ObjectHeader contains the information related to the object, this information @@ -37,8 +42,9 @@ type ObjectHeader struct { } type Scanner struct { - r *scannerReader - crc hash.Hash32 + r *scannerReader + crc gohash.Hash32 + packHasher hash.Hash // pendingObject is used to detect if an object has been read, or still // is waiting to be read @@ -56,10 +62,12 @@ func NewScanner(r io.Reader) *Scanner { _, ok := r.(io.ReadSeeker) crc := crc32.NewIEEE() + hasher := hash.New(crypto.SHA1) return &Scanner{ - r: newScannerReader(r, crc), + r: newScannerReader(r, io.MultiWriter(crc, hasher)), crc: crc, IsSeekable: ok, + packHasher: hasher, } } @@ -68,6 +76,7 @@ func (s *Scanner) Reset(r io.Reader) { s.r.Reset(r) s.crc.Reset() + s.packHasher.Reset() s.IsSeekable = ok s.pendingObject = nil s.version = 0 @@ -114,7 +123,7 @@ func (s *Scanner) Header() (version, objects uint32, err error) { // readSignature reads a returns the signature field in the packfile. func (s *Scanner) readSignature() ([]byte, error) { - var sig = make([]byte, 4) + sig := make([]byte, 4) if _, err := io.ReadFull(s.r, sig); err != nil { return []byte{}, err } @@ -322,7 +331,6 @@ func (s *Scanner) NextObject(w io.Writer) (written int64, crc32 uint32, err erro func (s *Scanner) ReadObject() (io.ReadCloser, error) { s.pendingObject = nil zr, err := sync.GetZlibReader(s.r) - if err != nil { return nil, fmt.Errorf("zlib reset error: %s", err) } @@ -374,7 +382,18 @@ func (s *Scanner) Checksum() (plumbing.Hash, error) { return plumbing.ZeroHash, err } - return binary.ReadHash(s.r) + s.r.Flush() + actual := plumbing.Hash(s.packHasher.Sum(nil)) + packChecksum, err := binary.ReadHash(s.r) + if err != nil { + return plumbing.ZeroHash, err + } + + if actual != packChecksum { + return plumbing.ZeroHash, fmt.Errorf("%w: checksum mismatch: %q instead of %q", ErrMalformedPackFile, packChecksum, actual) + } + + return packChecksum, nil } // Close reads the reader until io.EOF @@ -401,17 +420,17 @@ func (s *Scanner) Flush() error { // to the crc32 hash writer. type scannerReader struct { reader io.Reader - crc io.Writer + writer io.Writer rbuf *bufio.Reader wbuf *bufio.Writer offset int64 } -func newScannerReader(r io.Reader, h io.Writer) *scannerReader { +func newScannerReader(r io.Reader, w io.Writer) *scannerReader { sr := &scannerReader{ - rbuf: bufio.NewReader(nil), - wbuf: bufio.NewWriterSize(nil, 64), - crc: h, + rbuf: bufio.NewReader(nil), + wbuf: bufio.NewWriterSize(nil, 64), + writer: w, } sr.Reset(r) @@ -421,7 +440,7 @@ func newScannerReader(r io.Reader, h io.Writer) *scannerReader { func (r *scannerReader) Reset(reader io.Reader) { r.reader = reader r.rbuf.Reset(r.reader) - r.wbuf.Reset(r.crc) + r.wbuf.Reset(r.writer) r.offset = 0 if seeker, ok := r.reader.(io.ReadSeeker); ok { diff --git a/vendor/github.com/go-git/go-git/v5/plumbing/object/commit.go b/vendor/github.com/go-git/go-git/v5/plumbing/object/commit.go index 3d096e18b8..78627b065d 100644 --- a/vendor/github.com/go-git/go-git/v5/plumbing/object/commit.go +++ b/vendor/github.com/go-git/go-git/v5/plumbing/object/commit.go @@ -62,10 +62,55 @@ type Commit struct { ParentHashes []plumbing.Hash // Encoding is the encoding of the commit. Encoding MessageEncoding + // List of extra headers of the commit + ExtraHeaders []ExtraHeader s storer.EncodedObjectStorer } +// ExtraHeader holds any non-standard header +type ExtraHeader struct { + // Header name + Key string + // Value of the header + Value string +} + +// Implement fmt.Formatter for ExtraHeader +func (h ExtraHeader) Format(f fmt.State, verb rune) { + switch verb { + case 'v': + fmt.Fprintf(f, "ExtraHeader{Key: %v, Value: %v}", h.Key, h.Value) + default: + fmt.Fprintf(f, "%s", h.Key) + if len(h.Value) > 0 { + fmt.Fprint(f, " ") + // Content may be spread on multiple lines, if so we need to + // prepend each of them with a space for "continuation". + value := strings.TrimSuffix(h.Value, "\n") + lines := strings.Split(value, "\n") + fmt.Fprint(f, strings.Join(lines, "\n ")) + } + } +} + +// Parse an extra header and indicate whether it may be continue on the next line +func parseExtraHeader(line []byte) (ExtraHeader, bool) { + split := bytes.SplitN(line, []byte{' '}, 2) + + out := ExtraHeader { + Key: string(bytes.TrimRight(split[0], "\n")), + Value: "", + } + + if len(split) == 2 { + out.Value += string(split[1]) + return out, true + } else { + return out, false + } +} + // GetCommit gets a commit from an object storer and decodes it. func GetCommit(s storer.EncodedObjectStorer, h plumbing.Hash) (*Commit, error) { o, err := s.EncodedObject(plumbing.CommitObject, h) @@ -204,6 +249,7 @@ func (c *Commit) Decode(o plumbing.EncodedObject) (err error) { var mergetag bool var pgpsig bool var msgbuf bytes.Buffer + var extraheader *ExtraHeader = nil for { line, err := r.ReadBytes('\n') if err != nil && err != io.EOF { @@ -230,7 +276,19 @@ func (c *Commit) Decode(o plumbing.EncodedObject) (err error) { } } + if extraheader != nil { + if len(line) > 0 && line[0] == ' ' { + extraheader.Value += string(line[1:]) + continue + } else { + extraheader.Value = strings.TrimRight(extraheader.Value, "\n") + c.ExtraHeaders = append(c.ExtraHeaders, *extraheader) + extraheader = nil + } + } + if !message { + original_line := line line = bytes.TrimSpace(line) if len(line) == 0 { message = true @@ -261,6 +319,13 @@ func (c *Commit) Decode(o plumbing.EncodedObject) (err error) { case headerpgp: c.PGPSignature += string(data) + "\n" pgpsig = true + default: + h, maybecontinued := parseExtraHeader(original_line) + if maybecontinued { + extraheader = &h + } else { + c.ExtraHeaders = append(c.ExtraHeaders, h) + } } } else { msgbuf.Write(line) @@ -341,6 +406,13 @@ func (c *Commit) encode(o plumbing.EncodedObject, includeSig bool) (err error) { } } + for _, header := range c.ExtraHeaders { + + if _, err = fmt.Fprintf(w, "\n%s", header); err != nil { + return err + } + } + if c.PGPSignature != "" && includeSig { if _, err = fmt.Fprint(w, "\n"+headerpgp+" "); err != nil { return err diff --git a/vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/advrefs_decode.go b/vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/advrefs_decode.go index f8d26a28e4..2a94083f06 100644 --- a/vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/advrefs_decode.go +++ b/vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/advrefs_decode.go @@ -262,9 +262,8 @@ func decodeShallow(p *advRefsDecoder) decoderStateFn { p.line = bytes.TrimPrefix(p.line, shallow) if len(p.line) != hashSize { - p.error(fmt.Sprintf( - "malformed shallow hash: wrong length, expected 40 bytes, read %d bytes", - len(p.line))) + p.error("malformed shallow hash: wrong length, expected 40 bytes, read %d bytes", + len(p.line)) return nil } diff --git a/vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/updreq_encode.go b/vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/updreq_encode.go index 1205cfaf18..157fa56906 100644 --- a/vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/updreq_encode.go +++ b/vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/updreq_encode.go @@ -62,7 +62,7 @@ func (req *ReferenceUpdateRequest) encodeCommands(e *pktline.Encoder, } for _, cmd := range cmds[1:] { - if err := e.Encodef(formatCommand(cmd)); err != nil { + if err := e.Encodef("%s", formatCommand(cmd)); err != nil { return err } } diff --git a/vendor/github.com/go-git/go-git/v5/plumbing/transport/common.go b/vendor/github.com/go-git/go-git/v5/plumbing/transport/common.go index fae1aa98ca..b4c5e98bee 100644 --- a/vendor/github.com/go-git/go-git/v5/plumbing/transport/common.go +++ b/vendor/github.com/go-git/go-git/v5/plumbing/transport/common.go @@ -113,9 +113,17 @@ type Endpoint struct { Port int // Path is the repository path. Path string - // InsecureSkipTLS skips ssl verify if protocol is https + // InsecureSkipTLS skips SSL verification if Protocol is HTTPS. InsecureSkipTLS bool - // CaBundle specify additional ca bundle with system cert pool + // ClientCert specifies an optional client certificate to use for mutual + // TLS authentication if Protocol is HTTPS. + ClientCert []byte + // ClientKey specifies an optional client key to use for mutual TLS + // authentication if Protocol is HTTPS. + ClientKey []byte + // CaBundle specifies an optional CA bundle to use for SSL verification + // if Protocol is HTTPS. The bundle is added in addition to the system + // CA bundle. CaBundle []byte // Proxy provides info required for connecting to a proxy. Proxy ProxyOptions diff --git a/vendor/github.com/go-git/go-git/v5/plumbing/transport/http/common.go b/vendor/github.com/go-git/go-git/v5/plumbing/transport/http/common.go index 120008db1c..5dd2e311fa 100644 --- a/vendor/github.com/go-git/go-git/v5/plumbing/transport/http/common.go +++ b/vendor/github.com/go-git/go-git/v5/plumbing/transport/http/common.go @@ -15,16 +15,18 @@ import ( "strings" "sync" + "github.com/golang/groupcache/lru" + "github.com/go-git/go-git/v5/plumbing" "github.com/go-git/go-git/v5/plumbing/protocol/packp" + "github.com/go-git/go-git/v5/plumbing/protocol/packp/capability" "github.com/go-git/go-git/v5/plumbing/transport" "github.com/go-git/go-git/v5/utils/ioutil" - "github.com/golang/groupcache/lru" ) // it requires a bytes.Buffer, because we need to know the length func applyHeadersToRequest(req *http.Request, content *bytes.Buffer, host string, requestType string) { - req.Header.Add("User-Agent", "git/1.0") + req.Header.Add("User-Agent", capability.DefaultAgent()) req.Header.Add("Host", host) // host:port if content == nil { @@ -184,6 +186,18 @@ func transportWithInsecureTLS(transport *http.Transport) { transport.TLSClientConfig.InsecureSkipVerify = true } +func transportWithClientCert(transport *http.Transport, cert, key []byte) error { + keyPair, err := tls.X509KeyPair(cert, key) + if err != nil { + return err + } + if transport.TLSClientConfig == nil { + transport.TLSClientConfig = &tls.Config{} + } + transport.TLSClientConfig.Certificates = []tls.Certificate{keyPair} + return nil +} + func transportWithCABundle(transport *http.Transport, caBundle []byte) error { rootCAs, err := x509.SystemCertPool() if err != nil { @@ -205,6 +219,11 @@ func transportWithProxy(transport *http.Transport, proxyURL *url.URL) { } func configureTransport(transport *http.Transport, ep *transport.Endpoint) error { + if len(ep.ClientCert) > 0 && len(ep.ClientKey) > 0 { + if err := transportWithClientCert(transport, ep.ClientCert, ep.ClientKey); err != nil { + return err + } + } if len(ep.CaBundle) > 0 { if err := transportWithCABundle(transport, ep.CaBundle); err != nil { return err @@ -229,7 +248,7 @@ func newSession(c *client, ep *transport.Endpoint, auth transport.AuthMethod) (* // We need to configure the http transport if there are transport specific // options present in the endpoint. - if len(ep.CaBundle) > 0 || ep.InsecureSkipTLS || ep.Proxy.URL != "" { + if len(ep.ClientKey) > 0 || len(ep.ClientCert) > 0 || len(ep.CaBundle) > 0 || ep.InsecureSkipTLS || ep.Proxy.URL != "" { var transport *http.Transport // if the client wasn't configured to have a cache for transports then just configure // the transport and use it directly, otherwise try to use the cache. @@ -241,9 +260,13 @@ func newSession(c *client, ep *transport.Endpoint, auth transport.AuthMethod) (* } transport = tr.Clone() - configureTransport(transport, ep) + if err := configureTransport(transport, ep); err != nil { + return nil, err + } } else { transportOpts := transportOptions{ + clientCert: string(ep.ClientCert), + clientKey: string(ep.ClientKey), caBundle: string(ep.CaBundle), insecureSkipTLS: ep.InsecureSkipTLS, } @@ -259,7 +282,9 @@ func newSession(c *client, ep *transport.Endpoint, auth transport.AuthMethod) (* if !found { transport = c.client.Transport.(*http.Transport).Clone() - configureTransport(transport, ep) + if err := configureTransport(transport, ep); err != nil { + return nil, err + } c.addTransport(transportOpts, transport) } } diff --git a/vendor/github.com/go-git/go-git/v5/plumbing/transport/http/transport.go b/vendor/github.com/go-git/go-git/v5/plumbing/transport/http/transport.go index c8db389204..1991d0512c 100644 --- a/vendor/github.com/go-git/go-git/v5/plumbing/transport/http/transport.go +++ b/vendor/github.com/go-git/go-git/v5/plumbing/transport/http/transport.go @@ -9,8 +9,10 @@ import ( type transportOptions struct { insecureSkipTLS bool // []byte is not comparable. - caBundle string - proxyURL url.URL + clientCert string + clientKey string + caBundle string + proxyURL url.URL } func (c *client) addTransport(opts transportOptions, transport *http.Transport) { diff --git a/vendor/github.com/go-git/go-git/v5/plumbing/transport/ssh/auth_method.go b/vendor/github.com/go-git/go-git/v5/plumbing/transport/ssh/auth_method.go index ac4e3583c8..a616106019 100644 --- a/vendor/github.com/go-git/go-git/v5/plumbing/transport/ssh/auth_method.go +++ b/vendor/github.com/go-git/go-git/v5/plumbing/transport/ssh/auth_method.go @@ -54,7 +54,7 @@ func (a *KeyboardInteractive) String() string { } func (a *KeyboardInteractive) ClientConfig() (*ssh.ClientConfig, error) { - return a.SetHostKeyCallback(&ssh.ClientConfig{ + return a.SetHostKeyCallbackAndAlgorithms(&ssh.ClientConfig{ User: a.User, Auth: []ssh.AuthMethod{ a.Challenge, @@ -78,7 +78,7 @@ func (a *Password) String() string { } func (a *Password) ClientConfig() (*ssh.ClientConfig, error) { - return a.SetHostKeyCallback(&ssh.ClientConfig{ + return a.SetHostKeyCallbackAndAlgorithms(&ssh.ClientConfig{ User: a.User, Auth: []ssh.AuthMethod{ssh.Password(a.Password)}, }) @@ -101,7 +101,7 @@ func (a *PasswordCallback) String() string { } func (a *PasswordCallback) ClientConfig() (*ssh.ClientConfig, error) { - return a.SetHostKeyCallback(&ssh.ClientConfig{ + return a.SetHostKeyCallbackAndAlgorithms(&ssh.ClientConfig{ User: a.User, Auth: []ssh.AuthMethod{ssh.PasswordCallback(a.Callback)}, }) @@ -150,7 +150,7 @@ func (a *PublicKeys) String() string { } func (a *PublicKeys) ClientConfig() (*ssh.ClientConfig, error) { - return a.SetHostKeyCallback(&ssh.ClientConfig{ + return a.SetHostKeyCallbackAndAlgorithms(&ssh.ClientConfig{ User: a.User, Auth: []ssh.AuthMethod{ssh.PublicKeys(a.Signer)}, }) @@ -211,7 +211,7 @@ func (a *PublicKeysCallback) String() string { } func (a *PublicKeysCallback) ClientConfig() (*ssh.ClientConfig, error) { - return a.SetHostKeyCallback(&ssh.ClientConfig{ + return a.SetHostKeyCallbackAndAlgorithms(&ssh.ClientConfig{ User: a.User, Auth: []ssh.AuthMethod{ssh.PublicKeysCallback(a.Callback)}, }) @@ -230,11 +230,26 @@ func (a *PublicKeysCallback) ClientConfig() (*ssh.ClientConfig, error) { // ~/.ssh/known_hosts // /etc/ssh/ssh_known_hosts func NewKnownHostsCallback(files ...string) (ssh.HostKeyCallback, error) { - kh, err := newKnownHosts(files...) - return ssh.HostKeyCallback(kh), err + kh, err := NewKnownHostsDb(files...) + if err != nil { + return nil, err + } + return kh.HostKeyCallback(), nil } -func newKnownHosts(files ...string) (knownhosts.HostKeyCallback, error) { +// NewKnownHostsDb returns knownhosts.HostKeyDB based on a file based on a +// known_hosts file. http://man.openbsd.org/sshd#SSH_KNOWN_HOSTS_FILE_FORMAT +// +// If list of files is empty, then it will be read from the SSH_KNOWN_HOSTS +// environment variable, example: +// +// /home/foo/custom_known_hosts_file:/etc/custom_known/hosts_file +// +// If SSH_KNOWN_HOSTS is not set the following file locations will be used: +// +// ~/.ssh/known_hosts +// /etc/ssh/ssh_known_hosts +func NewKnownHostsDb(files ...string) (*knownhosts.HostKeyDB, error) { var err error if len(files) == 0 { @@ -247,7 +262,7 @@ func newKnownHosts(files ...string) (knownhosts.HostKeyCallback, error) { return nil, err } - return knownhosts.New(files...) + return knownhosts.NewDB(files...) } func getDefaultKnownHostsFiles() ([]string, error) { @@ -289,25 +304,50 @@ func filterKnownHostsFiles(files ...string) ([]string, error) { } // HostKeyCallbackHelper is a helper that provides common functionality to -// configure HostKeyCallback into a ssh.ClientConfig. +// configure HostKeyCallback and HostKeyAlgorithms into a ssh.ClientConfig. type HostKeyCallbackHelper struct { // HostKeyCallback is the function type used for verifying server keys. - // If nil default callback will be create using NewKnownHostsCallback + // If nil, a default callback will be created using NewKnownHostsDb // without argument. HostKeyCallback ssh.HostKeyCallback + + // HostKeyAlgorithms is a list of supported host key algorithms that will + // be used for host key verification. + HostKeyAlgorithms []string + + // fallback allows for injecting the fallback call, which is called + // when a HostKeyCallback is not set. + fallback func(files ...string) (ssh.HostKeyCallback, error) } -// SetHostKeyCallback sets the field HostKeyCallback in the given cfg. If -// HostKeyCallback is empty a default callback is created using -// NewKnownHostsCallback. -func (m *HostKeyCallbackHelper) SetHostKeyCallback(cfg *ssh.ClientConfig) (*ssh.ClientConfig, error) { - var err error +// SetHostKeyCallbackAndAlgorithms sets the field HostKeyCallback and HostKeyAlgorithms in the given cfg. +// If the host key callback or algorithms is empty it is left empty. It will be handled by the dial method, +// falling back to knownhosts. +func (m *HostKeyCallbackHelper) SetHostKeyCallbackAndAlgorithms(cfg *ssh.ClientConfig) (*ssh.ClientConfig, error) { + if cfg == nil { + cfg = &ssh.ClientConfig{} + } + if m.HostKeyCallback == nil { - if m.HostKeyCallback, err = NewKnownHostsCallback(); err != nil { - return cfg, err + if m.fallback == nil { + m.fallback = NewKnownHostsCallback } + + hkcb, err := m.fallback() + if err != nil { + return nil, fmt.Errorf("cannot create known hosts callback: %w", err) + } + + cfg.HostKeyCallback = hkcb + cfg.HostKeyAlgorithms = m.HostKeyAlgorithms + return cfg, err } cfg.HostKeyCallback = m.HostKeyCallback + cfg.HostKeyAlgorithms = m.HostKeyAlgorithms return cfg, nil } + +func (m *HostKeyCallbackHelper) SetHostKeyCallback(cfg *ssh.ClientConfig) (*ssh.ClientConfig, error) { + return m.SetHostKeyCallbackAndAlgorithms(cfg) +} diff --git a/vendor/github.com/go-git/go-git/v5/plumbing/transport/ssh/common.go b/vendor/github.com/go-git/go-git/v5/plumbing/transport/ssh/common.go index 05dea448f8..ae6f2174a0 100644 --- a/vendor/github.com/go-git/go-git/v5/plumbing/transport/ssh/common.go +++ b/vendor/github.com/go-git/go-git/v5/plumbing/transport/ssh/common.go @@ -11,7 +11,6 @@ import ( "github.com/go-git/go-git/v5/plumbing/transport" "github.com/go-git/go-git/v5/plumbing/transport/internal/common" - "github.com/skeema/knownhosts" "github.com/kevinburke/ssh_config" "golang.org/x/crypto/ssh" @@ -127,17 +126,17 @@ func (c *command) connect() error { } hostWithPort := c.getHostWithPort() if config.HostKeyCallback == nil { - kh, err := newKnownHosts() + db, err := NewKnownHostsDb() if err != nil { return err } - config.HostKeyCallback = kh.HostKeyCallback() - config.HostKeyAlgorithms = kh.HostKeyAlgorithms(hostWithPort) - } else if len(config.HostKeyAlgorithms) == 0 { - // Set the HostKeyAlgorithms based on HostKeyCallback. - // For background see https://github.com/go-git/go-git/issues/411 as well as - // https://github.com/golang/go/issues/29286 for root cause. - config.HostKeyAlgorithms = knownhosts.HostKeyAlgorithms(config.HostKeyCallback, hostWithPort) + config.HostKeyCallback = db.HostKeyCallback() + config.HostKeyAlgorithms = db.HostKeyAlgorithms(hostWithPort) + } else { + // If the user gave a custom HostKeyCallback, we do not try to detect host key algorithms + // based on knownhosts functionality, as the user may be requesting a FixedKey or using a + // different key approval strategy. In that case, the user is responsible for populating + // HostKeyAlgorithms appropriately } overrideConfig(c.config, config) diff --git a/vendor/github.com/go-git/go-git/v5/remote.go b/vendor/github.com/go-git/go-git/v5/remote.go index e2c734e751..7308127970 100644 --- a/vendor/github.com/go-git/go-git/v5/remote.go +++ b/vendor/github.com/go-git/go-git/v5/remote.go @@ -114,7 +114,7 @@ func (r *Remote) PushContext(ctx context.Context, o *PushOptions) (err error) { o.RemoteURL = r.c.URLs[len(r.c.URLs)-1] } - s, err := newSendPackSession(o.RemoteURL, o.Auth, o.InsecureSkipTLS, o.CABundle, o.ProxyOptions) + s, err := newSendPackSession(o.RemoteURL, o.Auth, o.InsecureSkipTLS, o.ClientCert, o.ClientKey, o.CABundle, o.ProxyOptions) if err != nil { return err } @@ -416,7 +416,7 @@ func (r *Remote) fetch(ctx context.Context, o *FetchOptions) (sto storer.Referen o.RemoteURL = r.c.URLs[0] } - s, err := newUploadPackSession(o.RemoteURL, o.Auth, o.InsecureSkipTLS, o.CABundle, o.ProxyOptions) + s, err := newUploadPackSession(o.RemoteURL, o.Auth, o.InsecureSkipTLS, o.ClientCert, o.ClientKey, o.CABundle, o.ProxyOptions) if err != nil { return nil, err } @@ -532,8 +532,8 @@ func depthChanged(before []plumbing.Hash, s storage.Storer) (bool, error) { return false, nil } -func newUploadPackSession(url string, auth transport.AuthMethod, insecure bool, cabundle []byte, proxyOpts transport.ProxyOptions) (transport.UploadPackSession, error) { - c, ep, err := newClient(url, insecure, cabundle, proxyOpts) +func newUploadPackSession(url string, auth transport.AuthMethod, insecure bool, clientCert, clientKey, caBundle []byte, proxyOpts transport.ProxyOptions) (transport.UploadPackSession, error) { + c, ep, err := newClient(url, insecure, clientCert, clientKey, caBundle, proxyOpts) if err != nil { return nil, err } @@ -541,8 +541,8 @@ func newUploadPackSession(url string, auth transport.AuthMethod, insecure bool, return c.NewUploadPackSession(ep, auth) } -func newSendPackSession(url string, auth transport.AuthMethod, insecure bool, cabundle []byte, proxyOpts transport.ProxyOptions) (transport.ReceivePackSession, error) { - c, ep, err := newClient(url, insecure, cabundle, proxyOpts) +func newSendPackSession(url string, auth transport.AuthMethod, insecure bool, clientCert, clientKey, caBundle []byte, proxyOpts transport.ProxyOptions) (transport.ReceivePackSession, error) { + c, ep, err := newClient(url, insecure, clientCert, clientKey, caBundle, proxyOpts) if err != nil { return nil, err } @@ -550,13 +550,15 @@ func newSendPackSession(url string, auth transport.AuthMethod, insecure bool, ca return c.NewReceivePackSession(ep, auth) } -func newClient(url string, insecure bool, cabundle []byte, proxyOpts transport.ProxyOptions) (transport.Transport, *transport.Endpoint, error) { +func newClient(url string, insecure bool, clientCert, clientKey, caBundle []byte, proxyOpts transport.ProxyOptions) (transport.Transport, *transport.Endpoint, error) { ep, err := transport.NewEndpoint(url) if err != nil { return nil, nil, err } ep.InsecureSkipTLS = insecure - ep.CaBundle = cabundle + ep.ClientCert = clientCert + ep.ClientKey = clientKey + ep.CaBundle = caBundle ep.Proxy = proxyOpts c, err := client.NewClient(ep) @@ -1356,7 +1358,7 @@ func (r *Remote) list(ctx context.Context, o *ListOptions) (rfs []*plumbing.Refe return nil, ErrEmptyUrls } - s, err := newUploadPackSession(r.c.URLs[0], o.Auth, o.InsecureSkipTLS, o.CABundle, o.ProxyOptions) + s, err := newUploadPackSession(r.c.URLs[0], o.Auth, o.InsecureSkipTLS, o.ClientCert, o.ClientKey, o.CABundle, o.ProxyOptions) if err != nil { return nil, err } diff --git a/vendor/github.com/go-git/go-git/v5/repository.go b/vendor/github.com/go-git/go-git/v5/repository.go index 200098e7a0..4015905448 100644 --- a/vendor/github.com/go-git/go-git/v5/repository.go +++ b/vendor/github.com/go-git/go-git/v5/repository.go @@ -19,6 +19,7 @@ import ( "github.com/go-git/go-billy/v5" "github.com/go-git/go-billy/v5/osfs" "github.com/go-git/go-billy/v5/util" + "github.com/go-git/go-git/v5/config" "github.com/go-git/go-git/v5/internal/path_util" "github.com/go-git/go-git/v5/internal/revision" @@ -930,6 +931,8 @@ func (r *Repository) clone(ctx context.Context, o *CloneOptions) error { Tags: o.Tags, RemoteName: o.RemoteName, InsecureSkipTLS: o.InsecureSkipTLS, + ClientCert: o.ClientCert, + ClientKey: o.ClientKey, CABundle: o.CABundle, ProxyOptions: o.ProxyOptions, }, o.ReferenceName) diff --git a/vendor/github.com/go-git/go-git/v5/storage/filesystem/object.go b/vendor/github.com/go-git/go-git/v5/storage/filesystem/object.go index 91b4aceae1..db82fefde1 100644 --- a/vendor/github.com/go-git/go-git/v5/storage/filesystem/object.go +++ b/vendor/github.com/go-git/go-git/v5/storage/filesystem/object.go @@ -2,6 +2,8 @@ package filesystem import ( "bytes" + "encoding/hex" + "fmt" "io" "os" "sync" @@ -87,6 +89,11 @@ func (s *ObjectStorage) loadIdxFile(h plumbing.Hash) (err error) { return err } + if !bytes.Equal(idxf.PackfileChecksum[:], h[:]) { + return fmt.Errorf("%w: packfile mismatch: target is %q not %q", + idxfile.ErrMalformedIdxFile, hex.EncodeToString(idxf.PackfileChecksum[:]), h.String()) + } + s.index[h] = idxf return err } @@ -186,7 +193,8 @@ func (s *ObjectStorage) HasEncodedObject(h plumbing.Hash) (err error) { } func (s *ObjectStorage) encodedObjectSizeFromUnpacked(h plumbing.Hash) ( - size int64, err error) { + size int64, err error, +) { f, err := s.dir.Object(h) if err != nil { if os.IsNotExist(err) { @@ -274,7 +282,8 @@ func (s *ObjectStorage) storePackfileInCache(hash plumbing.Hash, p *packfile.Pac } func (s *ObjectStorage) encodedObjectSizeFromPackfile(h plumbing.Hash) ( - size int64, err error) { + size int64, err error, +) { if err := s.requireIndex(); err != nil { return 0, err } @@ -310,7 +319,8 @@ func (s *ObjectStorage) encodedObjectSizeFromPackfile(h plumbing.Hash) ( // EncodedObjectSize returns the plaintext size of the given object, // without actually reading the full object data from storage. func (s *ObjectStorage) EncodedObjectSize(h plumbing.Hash) ( - size int64, err error) { + size int64, err error, +) { size, err = s.encodedObjectSizeFromUnpacked(h) if err != nil && err != plumbing.ErrObjectNotFound { return 0, err @@ -371,7 +381,8 @@ func (s *ObjectStorage) EncodedObject(t plumbing.ObjectType, h plumbing.Hash) (p // DeltaObject returns the object with the given hash, by searching for // it in the packfile and the git object directories. func (s *ObjectStorage) DeltaObject(t plumbing.ObjectType, - h plumbing.Hash) (plumbing.EncodedObject, error) { + h plumbing.Hash, +) (plumbing.EncodedObject, error) { obj, err := s.getFromUnpacked(h) if err == plumbing.ErrObjectNotFound { obj, err = s.getFromPackfile(h, true) @@ -451,8 +462,8 @@ var copyBufferPool = sync.Pool{ // Get returns the object with the given hash, by searching for it in // the packfile. func (s *ObjectStorage) getFromPackfile(h plumbing.Hash, canBeDelta bool) ( - plumbing.EncodedObject, error) { - + plumbing.EncodedObject, error, +) { if err := s.requireIndex(); err != nil { return nil, err } @@ -509,9 +520,7 @@ func (s *ObjectStorage) decodeDeltaObjectAt( return nil, err } - var ( - base plumbing.Hash - ) + var base plumbing.Hash switch header.Type { case plumbing.REFDeltaObject: diff --git a/vendor/github.com/go-git/go-git/v5/utils/merkletrie/change.go b/vendor/github.com/go-git/go-git/v5/utils/merkletrie/change.go index 450feb4bac..d32b5a7d46 100644 --- a/vendor/github.com/go-git/go-git/v5/utils/merkletrie/change.go +++ b/vendor/github.com/go-git/go-git/v5/utils/merkletrie/change.go @@ -131,7 +131,9 @@ func (l *Changes) addRecursive(root noder.Path, ctor noderToChangeFn) error { } if !root.IsDir() { - l.Add(ctor(root)) + if !root.Skip() { + l.Add(ctor(root)) + } return nil } @@ -148,7 +150,7 @@ func (l *Changes) addRecursive(root noder.Path, ctor noderToChangeFn) error { } return err } - if current.IsDir() { + if current.IsDir() || current.Skip() { continue } l.Add(ctor(current)) diff --git a/vendor/github.com/go-git/go-git/v5/utils/merkletrie/difftree.go b/vendor/github.com/go-git/go-git/v5/utils/merkletrie/difftree.go index 4ef2d9907a..7fc8d02d75 100644 --- a/vendor/github.com/go-git/go-git/v5/utils/merkletrie/difftree.go +++ b/vendor/github.com/go-git/go-git/v5/utils/merkletrie/difftree.go @@ -297,18 +297,16 @@ func DiffTreeContext(ctx context.Context, fromTree, toTree noder.Noder, case noMoreNoders: return ret, nil case onlyFromRemains: - if err = ret.AddRecursiveDelete(from); err != nil { - return nil, err + if !from.Skip() { + if err = ret.AddRecursiveDelete(from); err != nil { + return nil, err + } } if err = ii.nextFrom(); err != nil { return nil, err } case onlyToRemains: - if to.Skip() { - if err = ret.AddRecursiveDelete(to); err != nil { - return nil, err - } - } else { + if !to.Skip() { if err = ret.AddRecursiveInsert(to); err != nil { return nil, err } @@ -317,26 +315,25 @@ func DiffTreeContext(ctx context.Context, fromTree, toTree noder.Noder, return nil, err } case bothHaveNodes: - if from.Skip() { - if err = ret.AddRecursiveDelete(from); err != nil { - return nil, err - } - if err := ii.nextBoth(); err != nil { - return nil, err + var err error + switch { + case from.Skip(): + if from.Name() == to.Name() { + err = ii.nextBoth() + } else { + err = ii.nextFrom() } - break - } - if to.Skip() { - if err = ret.AddRecursiveDelete(to); err != nil { - return nil, err - } - if err := ii.nextBoth(); err != nil { - return nil, err + case to.Skip(): + if from.Name() == to.Name() { + err = ii.nextBoth() + } else { + err = ii.nextTo() } - break + default: + err = diffNodes(&ret, ii) } - if err = diffNodes(&ret, ii); err != nil { + if err != nil { return nil, err } default: diff --git a/vendor/github.com/go-git/go-git/v5/utils/merkletrie/index/node.go b/vendor/github.com/go-git/go-git/v5/utils/merkletrie/index/node.go index c1809f7ecd..5bc63f8b27 100644 --- a/vendor/github.com/go-git/go-git/v5/utils/merkletrie/index/node.go +++ b/vendor/github.com/go-git/go-git/v5/utils/merkletrie/index/node.go @@ -36,7 +36,15 @@ func NewRootNode(idx *index.Index) noder.Noder { parent := fullpath fullpath = path.Join(fullpath, part) - if _, ok := m[fullpath]; ok { + // It's possible that the first occurrence of subdirectory is skipped. + // The parent node can be created with SkipWorktree set to true, but + // if any future children do not skip their subtree, the entire lineage + // of the tree needs to have this value set to false so that subdirectories + // are not ignored. + if parentNode, ok := m[fullpath]; ok { + if e.SkipWorktree == false { + parentNode.skip = false + } continue } diff --git a/vendor/github.com/go-git/go-git/v5/worktree.go b/vendor/github.com/go-git/go-git/v5/worktree.go index 8dfa50b1b3..5e9cd7bd95 100644 --- a/vendor/github.com/go-git/go-git/v5/worktree.go +++ b/vendor/github.com/go-git/go-git/v5/worktree.go @@ -12,6 +12,7 @@ import ( "github.com/go-git/go-billy/v5" "github.com/go-git/go-billy/v5/util" + "github.com/go-git/go-git/v5/config" "github.com/go-git/go-git/v5/plumbing" "github.com/go-git/go-git/v5/plumbing/filemode" @@ -79,6 +80,8 @@ func (w *Worktree) PullContext(ctx context.Context, o *PullOptions) error { Progress: o.Progress, Force: o.Force, InsecureSkipTLS: o.InsecureSkipTLS, + ClientCert: o.ClientCert, + ClientKey: o.ClientKey, CABundle: o.CABundle, ProxyOptions: o.ProxyOptions, }) @@ -307,13 +310,20 @@ func (w *Worktree) ResetSparsely(opts *ResetOptions, dirs []string) error { return err } + var removedFiles []string if opts.Mode == MixedReset || opts.Mode == MergeReset || opts.Mode == HardReset { - if err := w.resetIndex(t, dirs, opts.Files); err != nil { + if removedFiles, err = w.resetIndex(t, dirs, opts.Files); err != nil { return err } } - if opts.Mode == MergeReset || opts.Mode == HardReset { + if opts.Mode == MergeReset && len(removedFiles) > 0 { + if err := w.resetWorktree(t, removedFiles); err != nil { + return err + } + } + + if opts.Mode == HardReset { if err := w.resetWorktree(t, opts.Files); err != nil { return err } @@ -362,23 +372,24 @@ func (w *Worktree) Reset(opts *ResetOptions) error { return w.ResetSparsely(opts, nil) } -func (w *Worktree) resetIndex(t *object.Tree, dirs []string, files []string) error { +func (w *Worktree) resetIndex(t *object.Tree, dirs []string, files []string) ([]string, error) { idx, err := w.r.Storer.Index() if err != nil { - return err + return nil, err } b := newIndexBuilder(idx) changes, err := w.diffTreeWithStaging(t, true) if err != nil { - return err + return nil, err } + var removedFiles []string for _, ch := range changes { a, err := ch.Action() if err != nil { - return err + return nil, err } var name string @@ -389,7 +400,7 @@ func (w *Worktree) resetIndex(t *object.Tree, dirs []string, files []string) err name = ch.To.String() e, err = t.FindEntry(name) if err != nil { - return err + return nil, err } case merkletrie.Delete: name = ch.From.String() @@ -403,6 +414,7 @@ func (w *Worktree) resetIndex(t *object.Tree, dirs []string, files []string) err } b.Remove(name) + removedFiles = append(removedFiles, name) if e == nil { continue } @@ -421,12 +433,13 @@ func (w *Worktree) resetIndex(t *object.Tree, dirs []string, files []string) err idx.SkipUnless(dirs) } - return w.r.Storer.SetIndex(idx) + return removedFiles, w.r.Storer.SetIndex(idx) } func inFiles(files []string, v string) bool { + v = filepath.Clean(v) for _, s := range files { - if s == v { + if filepath.Clean(s) == v { return true } } diff --git a/vendor/github.com/go-git/go-git/v5/worktree_status.go b/vendor/github.com/go-git/go-git/v5/worktree_status.go index 6e72db9744..7870d138d3 100644 --- a/vendor/github.com/go-git/go-git/v5/worktree_status.go +++ b/vendor/github.com/go-git/go-git/v5/worktree_status.go @@ -370,6 +370,8 @@ func (w *Worktree) doAdd(path string, ignorePattern []gitignore.Pattern, skipSta } } + path = filepath.Clean(path) + if err != nil || !fi.IsDir() { added, h, err = w.doAddFile(idx, s, path, ignorePattern) } else { diff --git a/vendor/github.com/pjbgf/sha1cd/Dockerfile.arm b/vendor/github.com/pjbgf/sha1cd/Dockerfile.arm index 99761296fb..4230fba011 100644 --- a/vendor/github.com/pjbgf/sha1cd/Dockerfile.arm +++ b/vendor/github.com/pjbgf/sha1cd/Dockerfile.arm @@ -1,4 +1,4 @@ -FROM golang:1.20@sha256:2edf6aab2d57644f3fe7407132a0d1770846867465a39c2083770cf62734b05d +FROM golang:1.23@sha256:51a6466e8dbf3e00e422eb0f7a97ac450b2d57b33617bbe8d2ee0bddcd9d0d37 ENV GOOS=linux ENV GOARCH=arm @@ -10,7 +10,6 @@ ENV PKG_CONFIG_PATH=/usr/lib/arm-linux-gnueabihf/pkgconfig RUN dpkg --add-architecture armhf \ && apt update \ && apt install -y --no-install-recommends \ - upx \ gcc-arm-linux-gnueabihf \ libc6-dev-armhf-cross \ pkg-config \ diff --git a/vendor/github.com/pjbgf/sha1cd/Dockerfile.arm64 b/vendor/github.com/pjbgf/sha1cd/Dockerfile.arm64 index 66bd09474f..59928252a1 100644 --- a/vendor/github.com/pjbgf/sha1cd/Dockerfile.arm64 +++ b/vendor/github.com/pjbgf/sha1cd/Dockerfile.arm64 @@ -1,4 +1,4 @@ -FROM golang:1.20@sha256:2edf6aab2d57644f3fe7407132a0d1770846867465a39c2083770cf62734b05d +FROM golang:1.23@sha256:51a6466e8dbf3e00e422eb0f7a97ac450b2d57b33617bbe8d2ee0bddcd9d0d37 ENV GOOS=linux ENV GOARCH=arm64 diff --git a/vendor/github.com/pjbgf/sha1cd/LICENSE b/vendor/github.com/pjbgf/sha1cd/LICENSE index 261eeb9e9f..c8ff622ffa 100644 --- a/vendor/github.com/pjbgf/sha1cd/LICENSE +++ b/vendor/github.com/pjbgf/sha1cd/LICENSE @@ -186,7 +186,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright [yyyy] [name of copyright owner] + Copyright 2023 pjbgf Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/vendor/github.com/pjbgf/sha1cd/Makefile b/vendor/github.com/pjbgf/sha1cd/Makefile index b24f2cbad6..278a109d82 100644 --- a/vendor/github.com/pjbgf/sha1cd/Makefile +++ b/vendor/github.com/pjbgf/sha1cd/Makefile @@ -32,8 +32,7 @@ build-nocgo: cross-build: build-arm build-arm64 build-nocgo generate: - go run sha1cdblock_amd64_asm.go -out sha1cdblock_amd64.s - sed -i 's;&\samd64;&\n// +build !noasm,gc,amd64;g' sha1cdblock_amd64.s + go generate -x ./... verify: generate git diff --exit-code diff --git a/vendor/github.com/pjbgf/sha1cd/sha1cd.go b/vendor/github.com/pjbgf/sha1cd/sha1cd.go index a69e480ee9..509569f66c 100644 --- a/vendor/github.com/pjbgf/sha1cd/sha1cd.go +++ b/vendor/github.com/pjbgf/sha1cd/sha1cd.go @@ -20,6 +20,8 @@ import ( shared "github.com/pjbgf/sha1cd/internal" ) +//go:generate go run -C asm . -out ../sha1cdblock_amd64.s -pkg $GOPACKAGE + func init() { crypto.RegisterHash(crypto.SHA1, New) } diff --git a/vendor/github.com/pjbgf/sha1cd/sha1cdblock_amd64.s b/vendor/github.com/pjbgf/sha1cd/sha1cdblock_amd64.s index 86f9821cab..e5e213a523 100644 --- a/vendor/github.com/pjbgf/sha1cd/sha1cdblock_amd64.s +++ b/vendor/github.com/pjbgf/sha1cd/sha1cdblock_amd64.s @@ -1,7 +1,6 @@ -// Code generated by command: go run sha1cdblock_amd64_asm.go -out sha1cdblock_amd64.s. DO NOT EDIT. +// Code generated by command: go run asm.go -out ../sha1cdblock_amd64.s -pkg sha1cd. DO NOT EDIT. //go:build !noasm && gc && amd64 -// +build !noasm,gc,amd64 #include "textflag.h" diff --git a/vendor/github.com/pjbgf/sha1cd/ubc/doc.go b/vendor/github.com/pjbgf/sha1cd/ubc/ubc.go similarity index 68% rename from vendor/github.com/pjbgf/sha1cd/ubc/doc.go rename to vendor/github.com/pjbgf/sha1cd/ubc/ubc.go index 0090e36b90..b0b4d76e37 100644 --- a/vendor/github.com/pjbgf/sha1cd/ubc/doc.go +++ b/vendor/github.com/pjbgf/sha1cd/ubc/ubc.go @@ -1,3 +1,5 @@ // ubc package provides ways for SHA1 blocks to be checked for // Unavoidable Bit Conditions that arise from crypto analysis attacks. package ubc + +//go:generate go run -C asm . -out ../ubc_amd64.s -pkg $GOPACKAGE diff --git a/vendor/github.com/pjbgf/sha1cd/ubc/ubc_amd64.go b/vendor/github.com/pjbgf/sha1cd/ubc/ubc_amd64.go new file mode 100644 index 0000000000..09159bb5b7 --- /dev/null +++ b/vendor/github.com/pjbgf/sha1cd/ubc/ubc_amd64.go @@ -0,0 +1,14 @@ +//go:build !noasm && gc && amd64 +// +build !noasm,gc,amd64 + +package ubc + +func CalculateDvMaskAMD64(W [80]uint32) uint32 + +// Check takes as input an expanded message block and verifies the unavoidable bitconditions +// for all listed DVs. It returns a dvmask where each bit belonging to a DV is set if all +// unavoidable bitconditions for that DV have been met. +// Thus, one needs to do the recompression check for each DV that has its bit set. +func CalculateDvMask(W [80]uint32) uint32 { + return CalculateDvMaskAMD64(W) +} diff --git a/vendor/github.com/pjbgf/sha1cd/ubc/ubc_amd64.s b/vendor/github.com/pjbgf/sha1cd/ubc/ubc_amd64.s new file mode 100644 index 0000000000..c77ea77ec4 --- /dev/null +++ b/vendor/github.com/pjbgf/sha1cd/ubc/ubc_amd64.s @@ -0,0 +1,1897 @@ +// Code generated by command: go run asm.go -out ../ubc_amd64.s -pkg ubc. DO NOT EDIT. + +//go:build !noasm && gc && amd64 + +#include "textflag.h" + +// func CalculateDvMaskAMD64(W [80]uint32) uint32 +TEXT ·CalculateDvMaskAMD64(SB), NOSPLIT, $0-324 + MOVL $0xffffffff, AX + + // (((((W[44] ^ W[45]) >> 29) & 1) - 1) | ^(DV_I_48_0_bit | DV_I_51_0_bit | DV_I_52_0_bit | DV_II_45_0_bit | DV_II_46_0_bit | DV_II_50_0_bit | DV_II_51_0_bit)) + MOVL W_44+176(FP), CX + MOVL W_45+180(FP), DX + XORL DX, CX + SHRL $0x1d, CX + ANDL $0x00000001, CX + DECL CX + ORL $0xfd7c5f7f, CX + ANDL CX, AX + + // mask &= (((((W[49] ^ W[50]) >> 29) & 1) - 1) | ^(DV_I_46_0_bit | DV_II_45_0_bit | DV_II_50_0_bit | DV_II_51_0_bit | DV_II_55_0_bit | DV_II_56_0_bit)) + MOVL W_49+196(FP), CX + MOVL W_50+200(FP), DX + XORL DX, CX + SHRL $0x1d, CX + ANDL $0x00000001, CX + DECL CX + ORL $0x3d7efff7, CX + ANDL CX, AX + + // mask &= (((((W[48] ^ W[49]) >> 29) & 1) - 1) | ^(DV_I_45_0_bit | DV_I_52_0_bit | DV_II_49_0_bit | DV_II_50_0_bit | DV_II_54_0_bit | DV_II_55_0_bit)) + MOVL W_48+192(FP), CX + MOVL W_49+196(FP), DX + XORL DX, CX + SHRL $0x1d, CX + ANDL $0x00000001, CX + DECL CX + ORL $0x9f5f7ffb, CX + ANDL CX, AX + + // mask &= ((((W[47] ^ (W[50] >> 25)) & (1 << 4)) - (1 << 4)) | ^(DV_I_47_0_bit | DV_I_49_0_bit | DV_I_51_0_bit | DV_II_45_0_bit | DV_II_51_0_bit | DV_II_56_0_bit)) + MOVL W_47+188(FP), CX + MOVL W_50+200(FP), DX + SHRL $0x19, DX + XORL DX, CX + ANDL $0x00000010, CX + SUBL $0x00000010, CX + ORL $0x7dfedddf, CX + ANDL CX, AX + + // mask &= (((((W[47] ^ W[48]) >> 29) & 1) - 1) | ^(DV_I_44_0_bit | DV_I_51_0_bit | DV_II_48_0_bit | DV_II_49_0_bit | DV_II_53_0_bit | DV_II_54_0_bit)) + MOVL W_47+188(FP), CX + MOVL W_48+192(FP), DX + XORL DX, CX + SHRL $0x1d, CX + ANDL $0x00000001, CX + DECL CX + ORL $0xcfcfdffd, CX + ANDL CX, AX + + // mask &= (((((W[46] >> 4) ^ (W[49] >> 29)) & 1) - 1) | ^(DV_I_46_0_bit | DV_I_48_0_bit | DV_I_50_0_bit | DV_I_52_0_bit | DV_II_50_0_bit | DV_II_55_0_bit)) + MOVL W_46+184(FP), CX + SHRL $0x04, CX + MOVL W_49+196(FP), DX + SHRL $0x1d, DX + XORL DX, CX + ANDL $0x00000001, CX + DECL CX + ORL $0xbf7f7777, CX + ANDL CX, AX + + // mask &= (((((W[46] ^ W[47]) >> 29) & 1) - 1) | ^(DV_I_43_0_bit | DV_I_50_0_bit | DV_II_47_0_bit | DV_II_48_0_bit | DV_II_52_0_bit | DV_II_53_0_bit)) + MOVL W_46+184(FP), CX + MOVL W_47+188(FP), DX + XORL DX, CX + SHRL $0x1d, CX + ANDL $0x00000001, CX + DECL CX + ORL $0xe7e7f7fe, CX + ANDL CX, AX + + // mask &= (((((W[45] >> 4) ^ (W[48] >> 29)) & 1) - 1) | ^(DV_I_45_0_bit | DV_I_47_0_bit | DV_I_49_0_bit | DV_I_51_0_bit | DV_II_49_0_bit | DV_II_54_0_bit)) + MOVL W_45+180(FP), CX + SHRL $0x04, CX + MOVL W_48+192(FP), DX + SHRL $0x1d, DX + XORL DX, CX + ANDL $0x00000001, CX + DECL CX + ORL $0xdfdfdddb, CX + ANDL CX, AX + + // mask &= (((((W[45] ^ W[46]) >> 29) & 1) - 1) | ^(DV_I_49_0_bit | DV_I_52_0_bit | DV_II_46_0_bit | DV_II_47_0_bit | DV_II_51_0_bit | DV_II_52_0_bit)) + MOVL W_45+180(FP), CX + MOVL W_46+184(FP), DX + XORL DX, CX + SHRL $0x1d, CX + ANDL $0x00000001, CX + DECL CX + ORL $0xf5f57dff, CX + ANDL CX, AX + + // mask &= (((((W[44] >> 4) ^ (W[47] >> 29)) & 1) - 1) | ^(DV_I_44_0_bit | DV_I_46_0_bit | DV_I_48_0_bit | DV_I_50_0_bit | DV_II_48_0_bit | DV_II_53_0_bit)) + MOVL W_44+176(FP), CX + SHRL $0x04, CX + MOVL W_47+188(FP), DX + SHRL $0x1d, DX + XORL DX, CX + ANDL $0x00000001, CX + DECL CX + ORL $0xefeff775, CX + ANDL CX, AX + + // mask &= (((((W[43] >> 4) ^ (W[46] >> 29)) & 1) - 1) | ^(DV_I_43_0_bit | DV_I_45_0_bit | DV_I_47_0_bit | DV_I_49_0_bit | DV_II_47_0_bit | DV_II_52_0_bit)) + MOVL W_43+172(FP), CX + SHRL $0x04, CX + MOVL W_46+184(FP), DX + SHRL $0x1d, DX + XORL DX, CX + ANDL $0x00000001, CX + DECL CX + ORL $0xf7f7fdda, CX + ANDL CX, AX + + // mask &= (((((W[43] ^ W[44]) >> 29) & 1) - 1) | ^(DV_I_47_0_bit | DV_I_50_0_bit | DV_I_51_0_bit | DV_II_45_0_bit | DV_II_49_0_bit | DV_II_50_0_bit)) + MOVL W_43+172(FP), CX + MOVL W_44+176(FP), DX + XORL DX, CX + SHRL $0x1d, CX + ANDL $0x00000001, CX + DECL CX + ORL $0xff5ed7df, CX + ANDL CX, AX + + // mask &= (((((W[42] >> 4) ^ (W[45] >> 29)) & 1) - 1) | ^(DV_I_44_0_bit | DV_I_46_0_bit | DV_I_48_0_bit | DV_I_52_0_bit | DV_II_46_0_bit | DV_II_51_0_bit)) + MOVL W_42+168(FP), CX + SHRL $0x04, CX + MOVL W_45+180(FP), DX + SHRL $0x1d, DX + XORL DX, CX + ANDL $0x00000001, CX + DECL CX + ORL $0xfdfd7f75, CX + ANDL CX, AX + + // mask &= (((((W[41] >> 4) ^ (W[44] >> 29)) & 1) - 1) | ^(DV_I_43_0_bit | DV_I_45_0_bit | DV_I_47_0_bit | DV_I_51_0_bit | DV_II_45_0_bit | DV_II_50_0_bit)) + MOVL W_41+164(FP), CX + SHRL $0x04, CX + MOVL W_44+176(FP), DX + SHRL $0x1d, DX + XORL DX, CX + ANDL $0x00000001, CX + DECL CX + ORL $0xff7edfda, CX + ANDL CX, AX + + // mask &= (((((W[40] ^ W[41]) >> 29) & 1) - 1) | ^(DV_I_44_0_bit | DV_I_47_0_bit | DV_I_48_0_bit | DV_II_46_0_bit | DV_II_47_0_bit | DV_II_56_0_bit)) + MOVL W_40+160(FP), CX + MOVL W_41+164(FP), DX + XORL DX, CX + SHRL $0x1d, CX + ANDL $0x00000001, CX + DECL CX + ORL $0x7ff5ff5d, CX + ANDL CX, AX + + // mask &= (((((W[54] ^ W[55]) >> 29) & 1) - 1) | ^(DV_I_51_0_bit | DV_II_47_0_bit | DV_II_50_0_bit | DV_II_55_0_bit | DV_II_56_0_bit)) + MOVL W_54+216(FP), CX + MOVL W_55+220(FP), DX + XORL DX, CX + SHRL $0x1d, CX + ANDL $0x00000001, CX + DECL CX + ORL $0x3f77dfff, CX + ANDL CX, AX + + // mask &= (((((W[53] ^ W[54]) >> 29) & 1) - 1) | ^(DV_I_50_0_bit | DV_II_46_0_bit | DV_II_49_0_bit | DV_II_54_0_bit | DV_II_55_0_bit)) + MOVL W_53+212(FP), CX + MOVL W_54+216(FP), DX + XORL DX, CX + SHRL $0x1d, CX + ANDL $0x00000001, CX + DECL CX + ORL $0x9fddf7ff, CX + ANDL CX, AX + + // mask &= (((((W[52] ^ W[53]) >> 29) & 1) - 1) | ^(DV_I_49_0_bit | DV_II_45_0_bit | DV_II_48_0_bit | DV_II_53_0_bit | DV_II_54_0_bit)) + MOVL W_52+208(FP), CX + MOVL W_53+212(FP), DX + XORL DX, CX + SHRL $0x1d, CX + ANDL $0x00000001, CX + DECL CX + ORL $0xcfeefdff, CX + ANDL CX, AX + + // mask &= ((((W[50] ^ (W[53] >> 25)) & (1 << 4)) - (1 << 4)) | ^(DV_I_50_0_bit | DV_I_52_0_bit | DV_II_46_0_bit | DV_II_48_0_bit | DV_II_54_0_bit)) + MOVL W_50+200(FP), CX + MOVL W_53+212(FP), DX + SHRL $0x19, DX + XORL DX, CX + ANDL $0x00000010, CX + SUBL $0x00000010, CX + ORL $0xdfed77ff, CX + ANDL CX, AX + + // mask &= (((((W[50] ^ W[51]) >> 29) & 1) - 1) | ^(DV_I_47_0_bit | DV_II_46_0_bit | DV_II_51_0_bit | DV_II_52_0_bit | DV_II_56_0_bit)) + MOVL W_50+200(FP), CX + MOVL W_51+204(FP), DX + XORL DX, CX + SHRL $0x1d, CX + ANDL $0x00000001, CX + DECL CX + ORL $0x75fdffdf, CX + ANDL CX, AX + + // mask &= ((((W[49] ^ (W[52] >> 25)) & (1 << 4)) - (1 << 4)) | ^(DV_I_49_0_bit | DV_I_51_0_bit | DV_II_45_0_bit | DV_II_47_0_bit | DV_II_53_0_bit)) + MOVL W_49+196(FP), CX + MOVL W_52+208(FP), DX + SHRL $0x19, DX + XORL DX, CX + ANDL $0x00000010, CX + SUBL $0x00000010, CX + ORL $0xeff6ddff, CX + ANDL CX, AX + + // mask &= ((((W[48] ^ (W[51] >> 25)) & (1 << 4)) - (1 << 4)) | ^(DV_I_48_0_bit | DV_I_50_0_bit | DV_I_52_0_bit | DV_II_46_0_bit | DV_II_52_0_bit)) + MOVL W_48+192(FP), CX + MOVL W_51+204(FP), DX + SHRL $0x19, DX + XORL DX, CX + ANDL $0x00000010, CX + SUBL $0x00000010, CX + ORL $0xf7fd777f, CX + ANDL CX, AX + + // mask &= (((((W[42] ^ W[43]) >> 29) & 1) - 1) | ^(DV_I_46_0_bit | DV_I_49_0_bit | DV_I_50_0_bit | DV_II_48_0_bit | DV_II_49_0_bit)) + MOVL W_42+168(FP), CX + MOVL W_43+172(FP), DX + XORL DX, CX + SHRL $0x1d, CX + ANDL $0x00000001, CX + DECL CX + ORL $0xffcff5f7, CX + ANDL CX, AX + + // mask &= (((((W[41] ^ W[42]) >> 29) & 1) - 1) | ^(DV_I_45_0_bit | DV_I_48_0_bit | DV_I_49_0_bit | DV_II_47_0_bit | DV_II_48_0_bit)) + MOVL W_41+164(FP), CX + MOVL W_42+168(FP), DX + XORL DX, CX + SHRL $0x1d, CX + ANDL $0x00000001, CX + DECL CX + ORL $0xffe7fd7b, CX + ANDL CX, AX + + // mask &= (((((W[40] >> 4) ^ (W[43] >> 29)) & 1) - 1) | ^(DV_I_44_0_bit | DV_I_46_0_bit | DV_I_50_0_bit | DV_II_49_0_bit | DV_II_56_0_bit)) + MOVL W_40+160(FP), CX + MOVL W_43+172(FP), DX + SHRL $0x04, CX + SHRL $0x1d, DX + XORL DX, CX + ANDL $0x00000001, CX + DECL CX + ORL $0x7fdff7f5, CX + ANDL CX, AX + + // mask &= (((((W[39] >> 4) ^ (W[42] >> 29)) & 1) - 1) | ^(DV_I_43_0_bit | DV_I_45_0_bit | DV_I_49_0_bit | DV_II_48_0_bit | DV_II_55_0_bit)) + MOVL W_39+156(FP), CX + MOVL W_42+168(FP), DX + SHRL $0x04, CX + SHRL $0x1d, DX + XORL DX, CX + ANDL $0x00000001, CX + DECL CX + ORL $0xbfeffdfa, CX + ANDL CX, AX + + // if (mask & (DV_I_44_0_bit | DV_I_48_0_bit | DV_II_47_0_bit | DV_II_54_0_bit | DV_II_56_0_bit)) != 0 { + // mask &= (((((W[38] >> 4) ^ (W[41] >> 29)) & 1) - 1) | ^(DV_I_44_0_bit | DV_I_48_0_bit | DV_II_47_0_bit | DV_II_54_0_bit | DV_II_56_0_bit)) + // } + TESTL $0xa0080082, AX + JE f1 + MOVL W_38+152(FP), CX + MOVL W_41+164(FP), DX + SHRL $0x04, CX + SHRL $0x1d, DX + XORL DX, CX + ANDL $0x00000001, CX + DECL CX + ORL $0x5ff7ff7d, CX + ANDL CX, AX + +f1: + // mask &= (((((W[37] >> 4) ^ (W[40] >> 29)) & 1) - 1) | ^(DV_I_43_0_bit | DV_I_47_0_bit | DV_II_46_0_bit | DV_II_53_0_bit | DV_II_55_0_bit)) + MOVL W_37+148(FP), CX + MOVL W_40+160(FP), DX + SHRL $0x04, CX + SHRL $0x1d, DX + XORL DX, CX + ANDL $0x00000001, CX + DECL CX + ORL $0xaffdffde, CX + ANDL CX, AX + + // if (mask & (DV_I_52_0_bit | DV_II_48_0_bit | DV_II_51_0_bit | DV_II_56_0_bit)) != 0 { + // mask &= (((((W[55] ^ W[56]) >> 29) & 1) - 1) | ^(DV_I_52_0_bit | DV_II_48_0_bit | DV_II_51_0_bit | DV_II_56_0_bit)) + // } + TESTL $0x82108000, AX + JE f2 + MOVL W_55+220(FP), CX + MOVL W_56+224(FP), DX + XORL DX, CX + SHRL $0x1d, CX + ANDL $0x00000001, CX + DECL CX + ORL $0x7def7fff, CX + ANDL CX, AX + +f2: + // if (mask & (DV_I_52_0_bit | DV_II_48_0_bit | DV_II_50_0_bit | DV_II_56_0_bit)) != 0 { + // mask &= ((((W[52] ^ (W[55] >> 25)) & (1 << 4)) - (1 << 4)) | ^(DV_I_52_0_bit | DV_II_48_0_bit | DV_II_50_0_bit | DV_II_56_0_bit)) + // } + TESTL $0x80908000, AX + JE f3 + MOVL W_52+208(FP), CX + MOVL W_55+220(FP), DX + SHRL $0x19, DX + XORL DX, CX + ANDL $0x00000010, CX + SUBL $0x00000010, CX + ORL $0x7f6f7fff, CX + ANDL CX, AX + +f3: + // if (mask & (DV_I_51_0_bit | DV_II_47_0_bit | DV_II_49_0_bit | DV_II_55_0_bit)) != 0 { + // mask &= ((((W[51] ^ (W[54] >> 25)) & (1 << 4)) - (1 << 4)) | ^(DV_I_51_0_bit | DV_II_47_0_bit | DV_II_49_0_bit | DV_II_55_0_bit)) + // } + TESTL $0x40282000, AX + JE f4 + MOVL W_51+204(FP), CX + MOVL W_54+216(FP), DX + SHRL $0x19, DX + XORL DX, CX + ANDL $0x00000010, CX + SUBL $0x00000010, CX + ORL $0xbfd7dfff, CX + ANDL CX, AX + +f4: + // if (mask & (DV_I_48_0_bit | DV_II_47_0_bit | DV_II_52_0_bit | DV_II_53_0_bit)) != 0 { + // mask &= (((((W[51] ^ W[52]) >> 29) & 1) - 1) | ^(DV_I_48_0_bit | DV_II_47_0_bit | DV_II_52_0_bit | DV_II_53_0_bit)) + // } + TESTL $0x18080080, AX + JE f5 + MOVL W_51+204(FP), CX + MOVL W_52+208(FP), DX + XORL DX, CX + SHRL $0x1d, CX + ANDL $0x00000001, CX + DECL CX + ORL $0xe7f7ff7f, CX + ANDL CX, AX + +f5: + // if (mask & (DV_I_46_0_bit | DV_I_49_0_bit | DV_II_45_0_bit | DV_II_48_0_bit)) != 0 { + // mask &= (((((W[36] >> 4) ^ (W[40] >> 29)) & 1) - 1) | ^(DV_I_46_0_bit | DV_I_49_0_bit | DV_II_45_0_bit | DV_II_48_0_bit)) + // } + TESTL $0x00110208, AX + JE f6 + MOVL W_36+144(FP), CX + SHRL $0x04, CX + MOVL W_40+160(FP), DX + SHRL $0x1d, DX + XORL DX, CX + ANDL $0x00000001, CX + DECL CX + ORL $0xffeefdf7, CX + ANDL CX, AX + +f6: + // if (mask & (DV_I_52_0_bit | DV_II_48_0_bit | DV_II_49_0_bit)) != 0 { + // mask &= ((0 - (((W[53] ^ W[56]) >> 29) & 1)) | ^(DV_I_52_0_bit | DV_II_48_0_bit | DV_II_49_0_bit)) + // } + TESTL $0x00308000, AX + JE f7 + MOVL W_53+212(FP), CX + MOVL W_56+224(FP), DX + XORL DX, CX + SHRL $0x1d, CX + ANDL $0x00000001, CX + NEGL CX + ORL $0xffcf7fff, CX + ANDL CX, AX + +f7: + // if (mask & (DV_I_50_0_bit | DV_II_46_0_bit | DV_II_47_0_bit)) != 0 { + // mask &= ((0 - (((W[51] ^ W[54]) >> 29) & 1)) | ^(DV_I_50_0_bit | DV_II_46_0_bit | DV_II_47_0_bit)) + // } + TESTL $0x000a0800, AX + JE f8 + MOVL W_51+204(FP), CX + MOVL W_54+216(FP), DX + XORL DX, CX + SHRL $0x1d, CX + ANDL $0x00000001, CX + NEGL CX + ORL $0xfff5f7ff, CX + ANDL CX, AX + +f8: + // if (mask & (DV_I_49_0_bit | DV_I_51_0_bit | DV_II_45_0_bit)) != 0 { + // mask &= ((0 - (((W[50] ^ W[52]) >> 29) & 1)) | ^(DV_I_49_0_bit | DV_I_51_0_bit | DV_II_45_0_bit)) + // } + TESTL $0x00012200, AX + JE f9 + MOVL W_50+200(FP), CX + MOVL W_52+208(FP), DX + XORL DX, CX + SHRL $0x1d, CX + ANDL $0x00000001, CX + NEGL CX + ORL $0xfffeddff, CX + ANDL CX, AX + +f9: + // if (mask & (DV_I_48_0_bit | DV_I_50_0_bit | DV_I_52_0_bit)) != 0 { + // mask &= ((0 - (((W[49] ^ W[51]) >> 29) & 1)) | ^(DV_I_48_0_bit | DV_I_50_0_bit | DV_I_52_0_bit)) + // } + TESTL $0x00008880, AX + JE f10 + MOVL W_49+196(FP), CX + MOVL W_51+204(FP), DX + XORL DX, CX + SHRL $0x1d, CX + ANDL $0x00000001, CX + NEGL CX + ORL $0xffff777f, CX + ANDL CX, AX + +f10: + // if (mask & (DV_I_47_0_bit | DV_I_49_0_bit | DV_I_51_0_bit)) != 0 { + // mask &= ((0 - (((W[48] ^ W[50]) >> 29) & 1)) | ^(DV_I_47_0_bit | DV_I_49_0_bit | DV_I_51_0_bit)) + // } + TESTL $0x00002220, AX + JE f11 + MOVL W_48+192(FP), CX + MOVL W_50+200(FP), DX + XORL DX, CX + SHRL $0x1d, CX + ANDL $0x00000001, CX + NEGL CX + ORL $0xffffdddf, CX + ANDL CX, AX + +f11: + // if (mask & (DV_I_46_0_bit | DV_I_48_0_bit | DV_I_50_0_bit)) != 0 { + // mask &= ((0 - (((W[47] ^ W[49]) >> 29) & 1)) | ^(DV_I_46_0_bit | DV_I_48_0_bit | DV_I_50_0_bit)) + // } + TESTL $0x00000888, AX + JE f12 + MOVL W_47+188(FP), CX + MOVL W_49+196(FP), DX + XORL DX, CX + SHRL $0x1d, CX + ANDL $0x00000001, CX + NEGL CX + ORL $0xfffff777, CX + ANDL CX, AX + +f12: + // if (mask & (DV_I_45_0_bit | DV_I_47_0_bit | DV_I_49_0_bit)) != 0 { + // mask &= ((0 - (((W[46] ^ W[48]) >> 29) & 1)) | ^(DV_I_45_0_bit | DV_I_47_0_bit | DV_I_49_0_bit)) + // } + TESTL $0x00000224, AX + JE f13 + MOVL W_46+184(FP), CX + MOVL W_48+192(FP), DX + XORL DX, CX + SHRL $0x1d, CX + ANDL $0x00000001, CX + NEGL CX + ORL $0xfffffddb, CX + ANDL CX, AX + +f13: + // mask &= ((((W[45] ^ W[47]) & (1 << 6)) - (1 << 6)) | ^(DV_I_47_2_bit | DV_I_49_2_bit | DV_I_51_2_bit)) + MOVL W_45+180(FP), CX + MOVL W_47+188(FP), DX + XORL DX, CX + ANDL $0x00000040, CX + SUBL $0x00000040, CX + ORL $0xffffbbbf, CX + ANDL CX, AX + + // if (mask & (DV_I_44_0_bit | DV_I_46_0_bit | DV_I_48_0_bit)) != 0 { + // mask &= ((0 - (((W[45] ^ W[47]) >> 29) & 1)) | ^(DV_I_44_0_bit | DV_I_46_0_bit | DV_I_48_0_bit)) + // } + TESTL $0x0000008a, AX + JE f14 + MOVL W_45+180(FP), CX + MOVL W_47+188(FP), DX + XORL DX, CX + SHRL $0x1d, CX + ANDL $0x00000001, CX + NEGL CX + ORL $0xffffff75, CX + ANDL CX, AX + +f14: + // mask &= (((((W[44] ^ W[46]) >> 6) & 1) - 1) | ^(DV_I_46_2_bit | DV_I_48_2_bit | DV_I_50_2_bit)) + MOVL W_44+176(FP), CX + MOVL W_46+184(FP), DX + XORL DX, CX + SHRL $0x06, CX + ANDL $0x00000001, CX + DECL CX + ORL $0xffffeeef, CX + ANDL CX, AX + + // if (mask & (DV_I_43_0_bit | DV_I_45_0_bit | DV_I_47_0_bit)) != 0 { + // mask &= ((0 - (((W[44] ^ W[46]) >> 29) & 1)) | ^(DV_I_43_0_bit | DV_I_45_0_bit | DV_I_47_0_bit)) + // } + TESTL $0x00000025, AX + JE f15 + MOVL W_44+176(FP), CX + MOVL W_46+184(FP), DX + XORL DX, CX + SHRL $0x1d, CX + ANDL $0x00000001, CX + NEGL CX + ORL $0xffffffda, CX + ANDL CX, AX + +f15: + // mask &= ((0 - ((W[41] ^ (W[42] >> 5)) & (1 << 1))) | ^(DV_I_48_2_bit | DV_II_46_2_bit | DV_II_51_2_bit)) + MOVL W_41+164(FP), CX + MOVL W_42+168(FP), DX + SHRL $0x05, DX + XORL DX, CX + ANDL $0x00000002, CX + NEGL CX + ORL $0xfbfbfeff, CX + ANDL CX, AX + + // mask &= ((0 - ((W[40] ^ (W[41] >> 5)) & (1 << 1))) | ^(DV_I_47_2_bit | DV_I_51_2_bit | DV_II_50_2_bit)) + MOVL W_40+160(FP), CX + MOVL W_41+164(FP), DX + SHRL $0x05, DX + XORL DX, CX + ANDL $0x00000002, CX + NEGL CX + ORL $0xfeffbfbf, CX + ANDL CX, AX + + // if (mask & (DV_I_44_0_bit | DV_I_46_0_bit | DV_II_56_0_bit)) != 0 { + // mask &= ((0 - (((W[40] ^ W[42]) >> 4) & 1)) | ^(DV_I_44_0_bit | DV_I_46_0_bit | DV_II_56_0_bit)) + // } + TESTL $0x8000000a, AX + JE f16 + MOVL W_40+160(FP), CX + MOVL W_42+168(FP), DX + XORL DX, CX + SHRL $0x04, CX + ANDL $0x00000001, CX + NEGL CX + ORL $0x7ffffff5, CX + ANDL CX, AX + +f16: + // mask &= ((0 - ((W[39] ^ (W[40] >> 5)) & (1 << 1))) | ^(DV_I_46_2_bit | DV_I_50_2_bit | DV_II_49_2_bit)) + MOVL W_39+156(FP), CX + MOVL W_40+160(FP), DX + SHRL $0x05, DX + XORL DX, CX + ANDL $0x00000002, CX + NEGL CX + ORL $0xffbfefef, CX + ANDL CX, AX + + // if (mask & (DV_I_43_0_bit | DV_I_45_0_bit | DV_II_55_0_bit)) != 0 { + // mask &= ((0 - (((W[39] ^ W[41]) >> 4) & 1)) | ^(DV_I_43_0_bit | DV_I_45_0_bit | DV_II_55_0_bit)) + // } + TESTL $0x40000005, AX + JE f17 + MOVL W_39+156(FP), CX + MOVL W_41+164(FP), DX + XORL DX, CX + SHRL $0x04, CX + ANDL $0x00000001, CX + NEGL CX + ORL $0xbffffffa, CX + ANDL CX, AX + +f17: + // if (mask & (DV_I_44_0_bit | DV_II_54_0_bit | DV_II_56_0_bit)) != 0 { + // mask &= ((0 - (((W[38] ^ W[40]) >> 4) & 1)) | ^(DV_I_44_0_bit | DV_II_54_0_bit | DV_II_56_0_bit)) + // } + TESTL $0xa0000002, AX + JE f18 + MOVL W_38+152(FP), CX + MOVL W_40+160(FP), DX + XORL DX, CX + SHRL $0x04, CX + ANDL $0x00000001, CX + NEGL CX + ORL $0x5ffffffd, CX + ANDL CX, AX + +f18: + // if (mask & (DV_I_43_0_bit | DV_II_53_0_bit | DV_II_55_0_bit)) != 0 { + // mask &= ((0 - (((W[37] ^ W[39]) >> 4) & 1)) | ^(DV_I_43_0_bit | DV_II_53_0_bit | DV_II_55_0_bit)) + // } + TESTL $0x50000001, AX + JE f19 + MOVL W_37+148(FP), CX + MOVL W_39+156(FP), DX + XORL DX, CX + SHRL $0x04, CX + ANDL $0x00000001, CX + NEGL CX + ORL $0xaffffffe, CX + ANDL CX, AX + +f19: + // mask &= ((0 - ((W[36] ^ (W[37] >> 5)) & (1 << 1))) | ^(DV_I_47_2_bit | DV_I_50_2_bit | DV_II_46_2_bit)) + MOVL W_36+144(FP), CX + MOVL W_37+148(FP), DX + SHRL $0x05, DX + XORL DX, CX + ANDL $0x00000002, CX + NEGL CX + ORL $0xfffbefbf, CX + ANDL CX, AX + + // if (mask & (DV_I_45_0_bit | DV_I_48_0_bit | DV_II_47_0_bit)) != 0 { + // mask &= (((((W[35] >> 4) ^ (W[39] >> 29)) & 1) - 1) | ^(DV_I_45_0_bit | DV_I_48_0_bit | DV_II_47_0_bit)) + // } + TESTL $0x00080084, AX + JE f20 + MOVL W_35+140(FP), CX + MOVL W_39+156(FP), DX + SHRL $0x04, CX + SHRL $0x1d, DX + XORL DX, CX + ANDL $0x00000001, CX + SUBL $0x00000001, CX + ORL $0xfff7ff7b, CX + ANDL CX, AX + +f20: + // if (mask & (DV_I_48_0_bit | DV_II_48_0_bit)) != 0 { + // mask &= ((0 - ((W[63] ^ (W[64] >> 5)) & (1 << 0))) | ^(DV_I_48_0_bit | DV_II_48_0_bit)) + // } + TESTL $0x00100080, AX + JE f21 + MOVL W_63+252(FP), CX + MOVL W_64+256(FP), DX + SHRL $0x05, DX + XORL DX, CX + ANDL $0x00000001, CX + NEGL CX + ORL $0xffefff7f, CX + ANDL CX, AX + +f21: + // if (mask & (DV_I_45_0_bit | DV_II_45_0_bit)) != 0 { + // mask &= ((0 - ((W[63] ^ (W[64] >> 5)) & (1 << 1))) | ^(DV_I_45_0_bit | DV_II_45_0_bit)) + // } + TESTL $0x00010004, AX + JE f22 + MOVL W_63+252(FP), CX + MOVL W_64+256(FP), DX + SHRL $0x05, DX + XORL DX, CX + ANDL $0x00000002, CX + NEGL CX + ORL $0xfffefffb, CX + ANDL CX, AX + +f22: + // if (mask & (DV_I_47_0_bit | DV_II_47_0_bit)) != 0 { + // mask &= ((0 - ((W[62] ^ (W[63] >> 5)) & (1 << 0))) | ^(DV_I_47_0_bit | DV_II_47_0_bit)) + // } + TESTL $0x00080020, AX + JE f23 + MOVL W_62+248(FP), CX + MOVL W_63+252(FP), DX + SHRL $0x05, DX + XORL DX, CX + ANDL $0x00000001, CX + NEGL CX + ORL $0xfff7ffdf, CX + ANDL CX, AX + +f23: + // if (mask & (DV_I_46_0_bit | DV_II_46_0_bit)) != 0 { + // mask &= ((0 - ((W[61] ^ (W[62] >> 5)) & (1 << 0))) | ^(DV_I_46_0_bit | DV_II_46_0_bit)) + // } + TESTL $0x00020008, AX + JE f24 + MOVL W_61+244(FP), CX + MOVL W_62+248(FP), DX + SHRL $0x05, DX + XORL DX, CX + ANDL $0x00000001, CX + NEGL CX + ORL $0xfffdfff7, CX + ANDL CX, AX + +f24: + // mask &= ((0 - ((W[61] ^ (W[62] >> 5)) & (1 << 2))) | ^(DV_I_46_2_bit | DV_II_46_2_bit)) + MOVL W_61+244(FP), CX + MOVL W_62+248(FP), DX + SHRL $0x05, DX + XORL DX, CX + ANDL $0x00000004, CX + NEGL CX + ORL $0xfffbffef, CX + ANDL CX, AX + + // if (mask & (DV_I_45_0_bit | DV_II_45_0_bit)) != 0 { + // mask &= ((0 - ((W[60] ^ (W[61] >> 5)) & (1 << 0))) | ^(DV_I_45_0_bit | DV_II_45_0_bit)) + // } + TESTL $0x00010004, AX + JE f25 + MOVL W_60+240(FP), CX + MOVL W_61+244(FP), DX + SHRL $0x05, DX + XORL DX, CX + ANDL $0x00000001, CX + NEGL CX + ORL $0xfffefffb, CX + ANDL CX, AX + +f25: + // if (mask & (DV_II_51_0_bit | DV_II_54_0_bit)) != 0 { + // mask &= (((((W[58] ^ W[59]) >> 29) & 1) - 1) | ^(DV_II_51_0_bit | DV_II_54_0_bit)) + // } + TESTL $0x22000000, AX + JE f26 + MOVL W_58+232(FP), CX + MOVL W_59+236(FP), DX + XORL DX, CX + SHRL $0x1d, CX + ANDL $0x00000001, CX + SUBL $0x00000001, CX + ORL $0xddffffff, CX + ANDL CX, AX + +f26: + // if (mask & (DV_II_50_0_bit | DV_II_53_0_bit)) != 0 { + // mask &= (((((W[57] ^ W[58]) >> 29) & 1) - 1) | ^(DV_II_50_0_bit | DV_II_53_0_bit)) + // } + TESTL $0x10800000, AX + JE f27 + MOVL W_57+228(FP), CX + MOVL W_58+232(FP), DX + XORL DX, CX + SHRL $0x1d, CX + ANDL $0x00000001, CX + SUBL $0x00000001, CX + ORL $0xef7fffff, CX + ANDL CX, AX + +f27: + // if (mask & (DV_II_52_0_bit | DV_II_54_0_bit)) != 0 { + // mask &= ((((W[56] ^ (W[59] >> 25)) & (1 << 4)) - (1 << 4)) | ^(DV_II_52_0_bit | DV_II_54_0_bit)) + // } + TESTL $0x28000000, AX + JE f28 + MOVL W_56+224(FP), CX + MOVL W_59+236(FP), DX + SHRL $0x19, DX + XORL DX, CX + ANDL $0x00000010, CX + SUBL $0x00000010, CX + ORL $0xd7ffffff, CX + ANDL CX, AX + +f28: + // if (mask & (DV_II_51_0_bit | DV_II_52_0_bit)) != 0 { + // mask &= ((0 - (((W[56] ^ W[59]) >> 29) & 1)) | ^(DV_II_51_0_bit | DV_II_52_0_bit)) + // } + TESTL $0x0a000000, AX + JE f29 + MOVL W_56+224(FP), CX + MOVL W_59+236(FP), DX + XORL DX, CX + SHRL $0x1d, CX + ANDL $0x00000001, CX + NEGL CX + ORL $0xf5ffffff, CX + ANDL CX, AX + +f29: + // if (mask & (DV_II_49_0_bit | DV_II_52_0_bit)) != 0 { + // mask &= (((((W[56] ^ W[57]) >> 29) & 1) - 1) | ^(DV_II_49_0_bit | DV_II_52_0_bit)) + // } + TESTL $0x08200000, AX + JE f30 + MOVL W_56+224(FP), CX + MOVL W_57+228(FP), DX + XORL DX, CX + SHRL $0x1d, CX + ANDL $0x00000001, CX + SUBL $0x00000001, CX + ORL $0xf7dfffff, CX + ANDL CX, AX + +f30: + // if (mask & (DV_II_51_0_bit | DV_II_53_0_bit)) != 0 { + // mask &= ((((W[55] ^ (W[58] >> 25)) & (1 << 4)) - (1 << 4)) | ^(DV_II_51_0_bit | DV_II_53_0_bit)) + // } + TESTL $0x12000000, AX + JE f31 + MOVL W_55+220(FP), CX + MOVL W_58+232(FP), DX + SHRL $0x19, DX + XORL DX, CX + ANDL $0x00000010, CX + SUBL $0x00000010, CX + ORL $0xedffffff, CX + ANDL CX, AX + +f31: + // if (mask & (DV_II_50_0_bit | DV_II_52_0_bit)) != 0 { + // mask &= ((((W[54] ^ (W[57] >> 25)) & (1 << 4)) - (1 << 4)) | ^(DV_II_50_0_bit | DV_II_52_0_bit)) + // } + TESTL $0x08800000, AX + JE f32 + MOVL W_54+216(FP), CX + MOVL W_57+228(FP), DX + SHRL $0x19, DX + XORL DX, CX + ANDL $0x00000010, CX + SUBL $0x00000010, CX + ORL $0xf77fffff, CX + ANDL CX, AX + +f32: + // if (mask & (DV_II_49_0_bit | DV_II_51_0_bit)) != 0 { + // mask &= ((((W[53] ^ (W[56] >> 25)) & (1 << 4)) - (1 << 4)) | ^(DV_II_49_0_bit | DV_II_51_0_bit)) + // } + TESTL $0x02200000, AX + JE f33 + MOVL W_53+212(FP), CX + MOVL W_56+224(FP), DX + SHRL $0x19, DX + XORL DX, CX + ANDL $0x00000010, CX + SUBL $0x00000010, CX + ORL $0xfddfffff, CX + ANDL CX, AX + +f33: + // mask &= ((((W[51] ^ (W[50] >> 5)) & (1 << 1)) - (1 << 1)) | ^(DV_I_50_2_bit | DV_II_46_2_bit)) + MOVL W_51+204(FP), CX + MOVL W_50+200(FP), DX + SHRL $0x05, DX + XORL DX, CX + ANDL $0x00000002, CX + SUBL $0x00000002, CX + ORL $0xfffbefff, CX + ANDL CX, AX + + // mask &= ((((W[48] ^ W[50]) & (1 << 6)) - (1 << 6)) | ^(DV_I_50_2_bit | DV_II_46_2_bit)) + MOVL W_48+192(FP), CX + MOVL W_50+200(FP), DX + XORL DX, CX + ANDL $0x00000040, CX + SUBL $0x00000040, CX + ORL $0xfffbefff, CX + ANDL CX, AX + + // if (mask & (DV_I_51_0_bit | DV_I_52_0_bit)) != 0 { + // mask &= ((0 - (((W[48] ^ W[55]) >> 29) & 1)) | ^(DV_I_51_0_bit | DV_I_52_0_bit)) + // } + TESTL $0x0000a000, AX + JE f34 + MOVL W_48+192(FP), CX + MOVL W_55+220(FP), DX + XORL DX, CX + SHRL $0x1d, CX + ANDL $0x00000001, CX + NEGL CX + ORL $0xffff5fff, CX + ANDL CX, AX + +f34: + // mask &= ((((W[47] ^ W[49]) & (1 << 6)) - (1 << 6)) | ^(DV_I_49_2_bit | DV_I_51_2_bit)) + MOVL W_47+188(FP), CX + MOVL W_49+196(FP), DX + XORL DX, CX + ANDL $0x00000040, CX + SUBL $0x00000040, CX + ORL $0xffffbbff, CX + ANDL CX, AX + + // mask &= ((((W[48] ^ (W[47] >> 5)) & (1 << 1)) - (1 << 1)) | ^(DV_I_47_2_bit | DV_II_51_2_bit)) + MOVL W_48+192(FP), CX + MOVL W_47+188(FP), DX + SHRL $0x05, DX + XORL DX, CX + ANDL $0x00000002, CX + SUBL $0x00000002, CX + ORL $0xfbffffbf, CX + ANDL CX, AX + + // mask &= ((((W[46] ^ W[48]) & (1 << 6)) - (1 << 6)) | ^(DV_I_48_2_bit | DV_I_50_2_bit)) + MOVL W_46+184(FP), CX + MOVL W_48+192(FP), DX + XORL DX, CX + ANDL $0x00000040, CX + SUBL $0x00000040, CX + ORL $0xffffeeff, CX + ANDL CX, AX + + // mask &= ((((W[47] ^ (W[46] >> 5)) & (1 << 1)) - (1 << 1)) | ^(DV_I_46_2_bit | DV_II_50_2_bit)) + MOVL W_47+188(FP), CX + MOVL W_46+184(FP), DX + SHRL $0x05, DX + XORL DX, CX + ANDL $0x00000002, CX + SUBL $0x00000002, CX + ORL $0xfeffffef, CX + ANDL CX, AX + + // mask &= ((0 - ((W[44] ^ (W[45] >> 5)) & (1 << 1))) | ^(DV_I_51_2_bit | DV_II_49_2_bit)) + MOVL W_44+176(FP), CX + MOVL W_45+180(FP), DX + SHRL $0x05, DX + XORL DX, CX + ANDL $0x00000002, CX + NEGL CX + ORL $0xffbfbfff, CX + ANDL CX, AX + + // mask &= ((((W[43] ^ W[45]) & (1 << 6)) - (1 << 6)) | ^(DV_I_47_2_bit | DV_I_49_2_bit)) + MOVL W_43+172(FP), CX + MOVL W_45+180(FP), DX + XORL DX, CX + ANDL $0x00000040, CX + SUBL $0x00000040, CX + ORL $0xfffffbbf, CX + ANDL CX, AX + + // mask &= (((((W[42] ^ W[44]) >> 6) & 1) - 1) | ^(DV_I_46_2_bit | DV_I_48_2_bit)) + MOVL W_42+168(FP), CX + MOVL W_44+176(FP), DX + XORL DX, CX + SHRL $0x06, CX + ANDL $0x00000001, CX + SUBL $0x00000001, CX + ORL $0xfffffeef, CX + ANDL CX, AX + + // mask &= ((((W[43] ^ (W[42] >> 5)) & (1 << 1)) - (1 << 1)) | ^(DV_II_46_2_bit | DV_II_51_2_bit)) + MOVL W_43+172(FP), CX + MOVL W_42+168(FP), DX + SHRL $0x05, DX + XORL DX, CX + ANDL $0x00000002, CX + SUBL $0x00000002, CX + ORL $0xfbfbffff, CX + ANDL CX, AX + + // mask &= ((((W[42] ^ (W[41] >> 5)) & (1 << 1)) - (1 << 1)) | ^(DV_I_51_2_bit | DV_II_50_2_bit)) + MOVL W_42+168(FP), CX + MOVL W_41+164(FP), DX + SHRL $0x05, DX + XORL DX, CX + ANDL $0x00000002, CX + SUBL $0x00000002, CX + ORL $0xfeffbfff, CX + ANDL CX, AX + + // mask &= ((((W[41] ^ (W[40] >> 5)) & (1 << 1)) - (1 << 1)) | ^(DV_I_50_2_bit | DV_II_49_2_bit)) + MOVL W_41+164(FP), CX + MOVL W_40+160(FP), DX + SHRL $0x05, DX + XORL DX, CX + ANDL $0x00000002, CX + SUBL $0x00000002, CX + ORL $0xffbfefff, CX + ANDL CX, AX + + // if (mask & (DV_I_52_0_bit | DV_II_51_0_bit)) != 0 { + // mask &= ((((W[39] ^ (W[43] >> 25)) & (1 << 4)) - (1 << 4)) | ^(DV_I_52_0_bit | DV_II_51_0_bit)) + // } + TESTL $0x02008000, AX + JE f35 + MOVL W_39+156(FP), CX + MOVL W_43+172(FP), DX + SHRL $0x19, DX + XORL DX, CX + ANDL $0x00000010, CX + SUBL $0x00000010, CX + ORL $0xfdff7fff, CX + ANDL CX, AX + +f35: + // if (mask & (DV_I_51_0_bit | DV_II_50_0_bit)) != 0 { + // mask &= ((((W[38] ^ (W[42] >> 25)) & (1 << 4)) - (1 << 4)) | ^(DV_I_51_0_bit | DV_II_50_0_bit)) + // } + TESTL $0x00802000, AX + JE f36 + MOVL W_38+152(FP), CX + MOVL W_42+168(FP), DX + SHRL $0x19, DX + XORL DX, CX + ANDL $0x00000010, CX + SUBL $0x00000010, CX + ORL $0xff7fdfff, CX + ANDL CX, AX + +f36: + // if (mask & (DV_I_48_2_bit | DV_I_51_2_bit)) != 0 { + // mask &= ((0 - ((W[37] ^ (W[38] >> 5)) & (1 << 1))) | ^(DV_I_48_2_bit | DV_I_51_2_bit)) + // } + TESTL $0x00004100, AX + JE f37 + MOVL W_37+148(FP), CX + MOVL W_38+152(FP), DX + SHRL $0x05, DX + XORL DX, CX + ANDL $0x00000002, CX + NEGL CX + ORL $0xffffbeff, CX + ANDL CX, AX + +f37: + // if (mask & (DV_I_50_0_bit | DV_II_49_0_bit)) != 0 { + // mask &= ((((W[37] ^ (W[41] >> 25)) & (1 << 4)) - (1 << 4)) | ^(DV_I_50_0_bit | DV_II_49_0_bit)) + // } + TESTL $0x00200800, AX + JE f38 + MOVL W_37+148(FP), CX + MOVL W_41+164(FP), DX + SHRL $0x19, DX + XORL DX, CX + ANDL $0x00000010, CX + SUBL $0x00000010, CX + ORL $0xffdff7ff, CX + ANDL CX, AX + +f38: + // if (mask & (DV_II_52_0_bit | DV_II_54_0_bit)) != 0 { + // mask &= ((0 - ((W[36] ^ W[38]) & (1 << 4))) | ^(DV_II_52_0_bit | DV_II_54_0_bit)) + // } + TESTL $0x28000000, AX + JE f39 + MOVL W_36+144(FP), CX + MOVL W_38+152(FP), DX + XORL DX, CX + ANDL $0x00000010, CX + NEGL CX + ORL $0xd7ffffff, CX + ANDL CX, AX + +f39: + // mask &= ((0 - ((W[35] ^ (W[36] >> 5)) & (1 << 1))) | ^(DV_I_46_2_bit | DV_I_49_2_bit)) + MOVL W_35+140(FP), CX + MOVL W_36+144(FP), DX + SHRL $0x05, DX + XORL DX, CX + ANDL $0x00000002, CX + NEGL CX + ORL $0xfffffbef, CX + ANDL CX, AX + + // if (mask & (DV_I_51_0_bit | DV_II_47_0_bit)) != 0 { + // mask &= ((((W[35] ^ (W[39] >> 25)) & (1 << 3)) - (1 << 3)) | ^(DV_I_51_0_bit | DV_II_47_0_bit)) + // } + TESTL $0x00082000, AX + JE f40 + MOVL W_35+140(FP), CX + MOVL W_39+156(FP), DX + SHRL $0x19, DX + XORL DX, CX + ANDL $0x00000008, CX + SUBL $0x00000008, CX + ORL $0xfff7dfff, CX + ANDL CX, AX + +f40: + // if mask != 0 + TESTL $0x00000000, AX + JNE end + + // if (mask & DV_I_43_0_bit) != 0 { + // if not((W[61]^(W[62]>>5))&(1<<1)) != 0 || + // not(not((W[59]^(W[63]>>25))&(1<<5))) != 0 || + // not((W[58]^(W[63]>>30))&(1<<0)) != 0 { + // mask &= ^DV_I_43_0_bit + // } + // } + BTL $0x00, AX + JNC f41_skip + MOVL W_61+244(FP), CX + MOVL W_62+248(FP), DX + SHRL $0x05, DX + XORL DX, CX + ANDL $0x00000002, CX + NEGL CX + CMPL CX, $0x00000000 + JE f41_in + MOVL W_59+236(FP), CX + MOVL W_63+252(FP), DX + SHRL $0x19, DX + XORL DX, CX + ANDL $0x00000020, CX + CMPL CX, $0x00000000 + JNE f41_in + MOVL W_58+232(FP), CX + MOVL W_63+252(FP), DX + SHRL $0x1e, DX + XORL DX, CX + ANDL $0x00000001, CX + NEGL CX + CMPL CX, $0x00000000 + JE f41_in + JMP f41_skip + +f41_in: + ANDL $0xfffffffe, AX + +f41_skip: + // if (mask & DV_I_44_0_bit) != 0 { + // if not((W[62]^(W[63]>>5))&(1<<1)) != 0 || + // not(not((W[60]^(W[64]>>25))&(1<<5))) != 0 || + // not((W[59]^(W[64]>>30))&(1<<0)) != 0 { + // mask &= ^DV_I_44_0_bit + // } + // } + BTL $0x01, AX + JNC f42_skip + MOVL W_62+248(FP), CX + MOVL W_63+252(FP), DX + SHRL $0x05, DX + XORL DX, CX + ANDL $0x00000002, CX + NEGL CX + CMPL CX, $0x00000000 + JE f42_in + MOVL W_60+240(FP), CX + MOVL W_64+256(FP), DX + SHRL $0x19, DX + XORL DX, CX + ANDL $0x00000020, CX + CMPL CX, $0x00000000 + JNE f42_in + MOVL W_59+236(FP), CX + MOVL W_64+256(FP), DX + SHRL $0x1e, DX + XORL DX, CX + ANDL $0x00000001, CX + NEGL CX + CMPL CX, $0x00000000 + JE f42_in + JMP f42_skip + +f42_in: + ANDL $0xfffffffd, AX + +f42_skip: + // if (mask & DV_I_46_2_bit) != 0 { + // mask &= ((^((W[40] ^ W[42]) >> 2)) | ^DV_I_46_2_bit) + // } + BTL $0x04, AX + JNC f43 + MOVL W_40+160(FP), CX + MOVL W_42+168(FP), DX + XORL DX, CX + SHRL $0x02, CX + NOTL CX + ORL $0xffffffef, CX + ANDL CX, AX + +f43: + // if (mask & DV_I_47_2_bit) != 0 { + // if not((W[62]^(W[63]>>5))&(1<<2)) != 0 || + // not(not((W[41]^W[43])&(1<<6))) != 0 { + // mask &= ^DV_I_47_2_bit + // } + // } + BTL $0x06, AX + JNC f44_skip + MOVL W_62+248(FP), CX + MOVL W_63+252(FP), DX + SHRL $0x05, DX + XORL DX, CX + ANDL $0x00000004, CX + NEGL CX + CMPL CX, $0x00000000 + JE f44_in + MOVL W_41+164(FP), CX + MOVL W_43+172(FP), DX + XORL DX, CX + ANDL $0x00000040, CX + CMPL CX, $0x00000000 + JNE f44_in + JMP f44_skip + +f44_in: + ANDL $0xffffffbf, AX + +f44_skip: + // if (mask & DV_I_48_2_bit) != 0 { + // if not((W[63]^(W[64]>>5))&(1<<2)) != 0 || + // not(not((W[48]^(W[49]<<5))&(1<<6))) != 0 { + // mask &= ^DV_I_48_2_bit + // } + // } + BTL $0x08, AX + JNC f45_skip + MOVL W_63+252(FP), CX + MOVL W_64+256(FP), DX + SHRL $0x05, DX + XORL DX, CX + ANDL $0x00000004, CX + NEGL CX + CMPL CX, $0x00000000 + JE f45_in + MOVL W_48+192(FP), CX + MOVL W_49+196(FP), DX + SHLL $0x05, DX + XORL DX, CX + ANDL $0x00000040, CX + CMPL CX, $0x00000000 + JNE f45_in + JMP f45_skip + +f45_in: + ANDL $0xfffffeff, AX + +f45_skip: + // if (mask & DV_I_49_2_bit) != 0 { + // if not(not((W[49]^(W[50]<<5))&(1<<6))) != 0 || + // not((W[42]^W[50])&(1<<1)) != 0 || + // not(not((W[39]^(W[40]<<5))&(1<<6))) != 0 || + // not((W[38]^W[40])&(1<<1)) != 0 { + // mask &= ^DV_I_49_2_bit + // } + // } + BTL $0x0a, AX + JNC f46_skip + MOVL W_49+196(FP), CX + MOVL W_50+200(FP), DX + SHLL $0x05, DX + XORL DX, CX + ANDL $0x00000040, CX + CMPL CX, $0x00000000 + JNE f46_in + MOVL W_42+168(FP), CX + MOVL W_50+200(FP), DX + XORL DX, CX + ANDL $0x00000002, CX + CMPL CX, $0x00000000 + JE f46_in + MOVL W_39+156(FP), CX + MOVL W_40+160(FP), DX + SHLL $0x05, DX + XORL DX, CX + ANDL $0x00000040, CX + CMPL CX, $0x00000000 + JNE f46_in + MOVL W_38+152(FP), CX + MOVL W_40+160(FP), DX + XORL DX, CX + ANDL $0x00000002, CX + CMPL CX, $0x00000000 + JE f46_in + JMP f46_skip + +f46_in: + ANDL $0xfffffbff, AX + +f46_skip: + // if (mask & DV_I_50_0_bit) != 0 { + // mask &= (((W[36] ^ W[37]) << 7) | ^DV_I_50_0_bit) + // } + BTL $0x0b, AX + JNC f47 + MOVL W_36+144(FP), CX + MOVL W_37+148(FP), DX + XORL DX, CX + SHLL $0x07, CX + ORL $0xfffff7ff, CX + ANDL CX, AX + +f47: + // if (mask & DV_I_50_2_bit) != 0 { + // mask &= (((W[43] ^ W[51]) << 11) | ^DV_I_50_2_bit) + // } + BTL $0x0c, AX + JNC f48 + MOVL W_43+172(FP), CX + MOVL W_51+204(FP), DX + XORL DX, CX + SHLL $0x0b, CX + ORL $0xffffefff, CX + ANDL CX, AX + +f48: + // if (mask & DV_I_51_0_bit) != 0 { + // mask &= (((W[37] ^ W[38]) << 9) | ^DV_I_51_0_bit) + // } + BTL $0x0d, AX + JNC f49 + MOVL W_37+148(FP), CX + MOVL W_38+152(FP), DX + XORL DX, CX + SHLL $0x09, CX + ORL $0xffffdfff, CX + ANDL CX, AX + +f49: + // if (mask & DV_I_51_2_bit) != 0 { + // if not(not((W[51]^(W[52]<<5))&(1<<6))) != 0 || + // not(not((W[49]^W[51])&(1<<6))) != 0 || + // not(not((W[37]^(W[37]>>5))&(1<<1))) != 0 || + // not(not((W[35]^(W[39]>>25))&(1<<5))) != 0 { + // mask &= ^DV_I_51_2_bit + // } + // } + BTL $0x0e, AX + JNC f50_skip + MOVL W_51+204(FP), CX + MOVL W_52+208(FP), DX + SHLL $0x05, DX + XORL DX, CX + ANDL $0x00000040, CX + CMPL CX, $0x00000000 + JNE f50_in + MOVL W_49+196(FP), CX + MOVL W_51+204(FP), DX + XORL DX, CX + ANDL $0x00000040, CX + CMPL CX, $0x00000000 + JNE f50_in + MOVL W_37+148(FP), CX + MOVL W_37+148(FP), DX + SHRL $0x05, DX + XORL DX, CX + ANDL $0x00000002, CX + CMPL CX, $0x00000000 + JNE f50_in + MOVL W_35+140(FP), CX + MOVL W_39+156(FP), DX + SHRL $0x19, DX + XORL DX, CX + ANDL $0x00000020, CX + CMPL CX, $0x00000000 + JNE f50_in + JMP f50_skip + +f50_in: + ANDL $0xffffbfff, AX + +f50_skip: + // if (mask & DV_I_52_0_bit) != 0 { + // mask &= (((W[38] ^ W[39]) << 11) | ^DV_I_52_0_bit) + // } + BTL $0x0f, AX + JNC f51 + MOVL W_38+152(FP), CX + MOVL W_39+156(FP), DX + XORL DX, CX + SHLL $0x0b, CX + ORL $0xffff7fff, CX + ANDL CX, AX + +f51: + // if (mask & DV_II_46_2_bit) != 0 { + // mask &= (((W[47] ^ W[51]) << 17) | ^DV_II_46_2_bit) + // } + TESTL $0x00040000, AX + BTL $0x12, AX + JNC f52 + MOVL W_47+188(FP), CX + MOVL W_51+204(FP), DX + XORL DX, CX + SHLL $0x11, CX + ORL $0xfffbffff, CX + ANDL CX, AX + +f52: + // if (mask & DV_II_48_0_bit) != 0 { + // if not(not((W[36]^(W[40]>>25))&(1<<3))) != 0 || + // not((W[35]^(W[40]<<2))&(1<<30)) != 0 { + // mask &= ^DV_II_48_0_bit + // } + // } + BTL $0x14, AX + JNC f53_skip + MOVL W_36+144(FP), CX + MOVL W_40+160(FP), DX + SHRL $0x19, DX + XORL DX, CX + ANDL $0x00000008, CX + CMPL CX, $0x00000000 + JNE f53_in + MOVL W_35+140(FP), CX + MOVL W_40+160(FP), DX + SHLL $0x02, DX + XORL DX, CX + ANDL $0x40000000, CX + CMPL CX, $0x00000000 + JNE f53_in + JMP f53_skip + +f53_in: + ANDL $0xffefffff, AX + +f53_skip: + // if (mask & DV_II_49_0_bit) != 0 { + // if not(not((W[37]^(W[41]>>25))&(1<<3))) != 0 || + // not((W[36]^(W[41]<<2))&(1<<30)) != 0 { + // mask &= ^DV_II_49_0_bit + // } + // } + BTL $0x15, AX + JNC f54_skip + MOVL W_37+148(FP), CX + MOVL W_41+164(FP), DX + SHRL $0x19, DX + XORL DX, CX + ANDL $0x00000008, CX + CMPL CX, $0x00000000 + JNE f54_in + MOVL W_36+144(FP), CX + MOVL W_41+164(FP), DX + SHLL $0x02, DX + XORL DX, CX + ANDL $0x40000000, CX + CMPL CX, $0x00000000 + JNE f54_in + JMP f54_skip + +f54_in: + ANDL $0xffdfffff, AX + +f54_skip: + // if (mask & DV_II_49_2_bit) != 0 { + // if not(not((W[53]^(W[54]<<5))&(1<<6))) != 0 || + // not(not((W[51]^W[53])&(1<<6))) != 0 || + // not((W[50]^W[54])&(1<<1)) != 0 || + // not(not((W[45]^(W[46]<<5))&(1<<6))) != 0 || + // not(not((W[37]^(W[41]>>25))&(1<<5))) != 0 || + // not((W[36]^(W[41]>>30))&(1<<0)) != 0 { + // mask &= ^DV_II_49_2_bit + // } + // } + BTL $0x16, AX + JNC f55_skip + MOVL W_53+212(FP), CX + MOVL W_54+216(FP), DX + SHLL $0x05, DX + XORL DX, CX + ANDL $0x00000040, CX + CMPL CX, $0x00000000 + JNE f55_in + MOVL W_51+204(FP), CX + MOVL W_53+212(FP), DX + XORL DX, CX + ANDL $0x00000040, CX + CMPL CX, $0x00000000 + JNE f55_in + MOVL W_50+200(FP), CX + MOVL W_54+216(FP), DX + XORL DX, CX + ANDL $0x00000002, CX + NEGL CX + CMPL CX, $0x00000000 + JE f55_in + MOVL W_45+180(FP), CX + MOVL W_46+184(FP), DX + SHLL $0x05, DX + XORL DX, CX + ANDL $0x00000040, CX + CMPL CX, $0x00000000 + JNE f55_in + MOVL W_37+148(FP), CX + MOVL W_41+164(FP), DX + SHRL $0x19, DX + XORL DX, CX + ANDL $0x00000020, CX + CMPL CX, $0x00000000 + JNE f55_in + MOVL W_36+144(FP), CX + MOVL W_41+164(FP), DX + SHRL $0x1e, DX + XORL DX, CX + ANDL $0x00000001, CX + NEGL CX + CMPL CX, $0x00000000 + JE f55_in + JMP f55_skip + +f55_in: + ANDL $0xffbfffff, AX + +f55_skip: + // if (mask & DV_II_50_0_bit) != 0 { + // if not((W[55]^W[58])&(1<<29)) != 0 || + // not(not((W[38]^(W[42]>>25))&(1<<3))) != 0 || + // not((W[37]^(W[42]<<2))&(1<<30)) != 0 { + // mask &= ^DV_II_50_0_bit + // } + // } + BTL $0x17, AX + JNC f56_skip + MOVL W_55+220(FP), CX + MOVL W_58+232(FP), DX + XORL DX, CX + ANDL $0x20000000, CX + NEGL CX + CMPL CX, $0x00000000 + JE f56_in + MOVL W_38+152(FP), CX + MOVL W_42+168(FP), DX + SHRL $0x19, DX + XORL DX, CX + ANDL $0x00000008, CX + CMPL CX, $0x00000000 + JNE f56_in + MOVL W_37+148(FP), CX + MOVL W_42+168(FP), DX + SHRL $0x02, DX + XORL DX, CX + ANDL $0x40000000, CX + NEGL CX + CMPL CX, $0x00000000 + JE f56_in + JMP f56_skip + +f56_in: + ANDL $0xff7fffff, AX + +f56_skip: + // if (mask & DV_II_50_2_bit) != 0 { + // if not(not((W[54]^(W[55]<<5))&(1<<6))) != 0 || + // not(not((W[52]^W[54])&(1<<6))) != 0 || + // not((W[51]^W[55])&(1<<1)) != 0 || + // not((W[45]^W[47])&(1<<1)) != 0 || + // not(not((W[38]^(W[42]>>25))&(1<<5))) != 0 || + // not((W[37]^(W[42]>>30))&(1<<0)) != 0 { + // mask &= ^DV_II_50_2_bit + // } + // } + BTL $0x18, AX + JNC f57_skip + MOVL W_54+216(FP), CX + MOVL W_55+220(FP), DX + SHLL $0x05, DX + XORL DX, CX + ANDL $0x00000040, CX + CMPL CX, $0x00000000 + JNE f57_in + MOVL W_52+208(FP), CX + MOVL W_54+216(FP), DX + XORL DX, CX + ANDL $0x00000040, CX + CMPL CX, $0x00000000 + JNE f57_in + MOVL W_51+204(FP), CX + MOVL W_55+220(FP), DX + XORL DX, CX + ANDL $0x00000002, CX + NEGL CX + CMPL CX, $0x00000000 + JE f57_in + MOVL W_45+180(FP), CX + MOVL W_47+188(FP), DX + XORL DX, CX + ANDL $0x00000002, CX + NEGL CX + CMPL CX, $0x00000000 + JE f57_in + MOVL W_38+152(FP), CX + MOVL W_42+168(FP), DX + SHRL $0x19, DX + XORL DX, CX + ANDL $0x00000020, CX + CMPL CX, $0x00000000 + JNE f57_in + MOVL W_37+148(FP), CX + MOVL W_42+168(FP), DX + SHRL $0x1e, DX + XORL DX, CX + ANDL $0x00000001, CX + NEGL CX + CMPL CX, $0x00000000 + JE f57_in + JMP f57_skip + +f57_in: + ANDL $0xfeffffff, AX + +f57_skip: + // if (mask & DV_II_51_0_bit) != 0 { + // if not(not((W[39]^(W[43]>>25))&(1<<3))) != 0 || + // not((W[38]^(W[43]<<2))&(1<<30)) != 0 { + // mask &= ^DV_II_51_0_bit + // } + // } + BTL $0x19, AX + JNC f58_skip + MOVL W_39+156(FP), CX + MOVL W_43+172(FP), DX + SHRL $0x19, DX + XORL DX, CX + ANDL $0x00000008, CX + CMPL CX, $0x00000000 + JNE f58_in + MOVL W_38+152(FP), CX + MOVL W_43+172(FP), DX + SHLL $0x02, DX + XORL DX, CX + ANDL $0x40000000, CX + NEGL CX + CMPL CX, $0x00000000 + JE f58_in + JMP f58_skip + +f58_in: + ANDL $0xfdffffff, AX + +f58_skip: + // if (mask & DV_II_51_2_bit) != 0 { + // if not(not((W[55]^(W[56]<<5))&(1<<6))) != 0 || + // not(not((W[53]^W[55])&(1<<6))) != 0 || + // not((W[52]^W[56])&(1<<1)) != 0 || + // not((W[46]^W[48])&(1<<1)) != 0 || + // not(not((W[39]^(W[43]>>25))&(1<<5))) != 0 || + // not((W[38]^(W[43]>>30))&(1<<0)) != 0 { + // mask &= ^DV_II_51_2_bit + // } + // } + BTL $0x1a, AX + JNC f59_skip + MOVL W_55+220(FP), CX + MOVL W_56+224(FP), DX + SHLL $0x05, DX + XORL DX, CX + ANDL $0x00000040, CX + CMPL CX, $0x00000000 + JNE f59_in + MOVL W_53+212(FP), CX + MOVL W_55+220(FP), DX + XORL DX, CX + ANDL $0x00000040, CX + CMPL CX, $0x00000000 + JNE f59_in + MOVL W_52+208(FP), CX + MOVL W_56+224(FP), DX + XORL DX, CX + ANDL $0x00000002, CX + NEGL CX + CMPL CX, $0x00000000 + JE f59_in + MOVL W_46+184(FP), CX + MOVL W_48+192(FP), DX + XORL DX, CX + ANDL $0x00000002, CX + NEGL CX + CMPL CX, $0x00000000 + JE f59_in + MOVL W_39+156(FP), CX + MOVL W_43+172(FP), DX + SHRL $0x19, DX + XORL DX, CX + ANDL $0x00000020, CX + CMPL CX, $0x00000000 + JNE f59_in + MOVL W_38+152(FP), CX + MOVL W_43+172(FP), DX + SHRL $0x1e, DX + XORL DX, CX + ANDL $0x00000001, CX + NEGL CX + CMPL CX, $0x00000000 + JE f59_in + JMP f59_skip + +f59_in: + ANDL $0xfbffffff, AX + +f59_skip: + // if (mask & DV_II_52_0_bit) != 0 { + // if not(not((W[59]^W[60])&(1<<29))) != 0 || + // not(not((W[40]^(W[44]>>25))&(1<<3))) != 0 || + // not(not((W[40]^(W[44]>>25))&(1<<4))) != 0 || + // not((W[39]^(W[44]<<2))&(1<<30)) != 0 { + // mask &= ^DV_II_52_0_bit + // } + // } + BTL $0x1b, AX + JNC f60_skip + MOVL W_59+236(FP), CX + MOVL W_60+240(FP), DX + XORL DX, CX + ANDL $0x20000000, CX + CMPL CX, $0x00000000 + JNE f60_in + MOVL W_40+160(FP), CX + MOVL W_44+176(FP), DX + SHRL $0x19, DX + XORL DX, CX + ANDL $0x00000008, CX + CMPL CX, $0x00000000 + JNE f60_in + MOVL W_40+160(FP), CX + MOVL W_44+176(FP), DX + SHRL $0x19, DX + XORL DX, CX + ANDL $0x00000010, CX + CMPL CX, $0x00000000 + JNE f60_in + MOVL W_39+156(FP), CX + MOVL W_44+176(FP), DX + SHLL $0x02, DX + XORL DX, CX + ANDL $0x40000000, CX + NEGL CX + CMPL CX, $0x00000000 + JE f60_in + JMP f60_skip + +f60_in: + ANDL $0xf7ffffff, AX + +f60_skip: + // if (mask & DV_II_53_0_bit) != 0 { + // if not((W[58]^W[61])&(1<<29)) != 0 || + // not(not((W[57]^(W[61]>>25))&(1<<4))) != 0 || + // not(not((W[41]^(W[45]>>25))&(1<<3))) != 0 || + // not(not((W[41]^(W[45]>>25))&(1<<4))) != 0 { + // mask &= ^DV_II_53_0_bit + // } + // } + BTL $0x1c, AX + JNC f61_skip + MOVL W_58+232(FP), CX + MOVL W_61+244(FP), DX + XORL DX, CX + ANDL $0x20000000, CX + NEGL CX + CMPL CX, $0x00000000 + JE f61_in + MOVL W_57+228(FP), CX + MOVL W_61+244(FP), DX + SHRL $0x19, DX + XORL DX, CX + ANDL $0x00000010, CX + CMPL CX, $0x00000000 + JNE f61_in + MOVL W_41+164(FP), CX + MOVL W_45+180(FP), DX + SHRL $0x19, DX + XORL DX, CX + ANDL $0x00000008, CX + CMPL CX, $0x00000000 + JNE f61_in + MOVL W_41+164(FP), CX + MOVL W_45+180(FP), DX + SHRL $0x19, DX + XORL DX, CX + ANDL $0x00000010, CX + CMPL CX, $0x00000000 + JNE f61_in + JMP f61_skip + +f61_in: + ANDL $0xefffffff, AX + +f61_skip: + // if (mask & DV_II_54_0_bit) != 0 { + // if not(not((W[58]^(W[62]>>25))&(1<<4))) != 0 || + // not(not((W[42]^(W[46]>>25))&(1<<3))) != 0 || + // not(not((W[42]^(W[46]>>25))&(1<<4))) != 0 { + // mask &= ^DV_II_54_0_bit + // } + // } + BTL $0x1d, AX + JNC f62_skip + MOVL W_58+232(FP), CX + MOVL W_62+248(FP), DX + SHRL $0x19, DX + XORL DX, CX + ANDL $0x00000010, CX + CMPL CX, $0x00000000 + JNE f62_in + MOVL W_42+168(FP), CX + MOVL W_46+184(FP), DX + SHRL $0x19, DX + XORL DX, CX + ANDL $0x00000008, CX + CMPL CX, $0x00000000 + JNE f62_in + MOVL W_42+168(FP), CX + MOVL W_46+184(FP), DX + SHRL $0x19, DX + XORL DX, CX + ANDL $0x00000010, CX + CMPL CX, $0x00000000 + JNE f62_in + JMP f62_skip + +f62_in: + ANDL $0xdfffffff, AX + +f62_skip: + // if (mask & DV_II_55_0_bit) != 0 { + // if not(not((W[59]^(W[63]>>25))&(1<<4))) != 0 || + // not(not((W[57]^(W[59]>>25))&(1<<4))) != 0 || + // not(not((W[43]^(W[47]>>25))&(1<<3))) != 0 || + // not(not((W[43]^(W[47]>>25))&(1<<4))) != 0 { + // mask &= ^DV_II_55_0_bit + // } + // } + BTL $0x1e, AX + JNC f63_skip + MOVL W_59+236(FP), CX + MOVL W_63+252(FP), DX + SHRL $0x19, DX + XORL DX, CX + ANDL $0x00000010, CX + CMPL CX, $0x00000000 + JNE f63_in + MOVL W_57+228(FP), CX + MOVL W_59+236(FP), DX + SHRL $0x19, DX + XORL DX, CX + ANDL $0x00000010, CX + CMPL CX, $0x00000000 + JNE f63_in + MOVL W_43+172(FP), CX + MOVL W_47+188(FP), DX + SHRL $0x19, DX + XORL DX, CX + ANDL $0x00000008, CX + CMPL CX, $0x00000000 + JNE f63_in + MOVL W_43+172(FP), CX + MOVL W_47+188(FP), DX + SHRL $0x19, DX + XORL DX, CX + ANDL $0x00000010, CX + CMPL CX, $0x00000000 + JNE f63_in + JMP f63_skip + +f63_in: + ANDL $0xbfffffff, AX + +f63_skip: + // if (mask & DV_II_56_0_bit) != 0 { + // if not(not((W[60]^(W[64]>>25))&(1<<4))) != 0 || + // not(not((W[44]^(W[48]>>25))&(1<<3))) != 0 || + // not(not((W[44]^(W[48]>>25))&(1<<4))) != 0 { + // mask &= ^DV_II_56_0_bit + // } + // } + BTL $0x1f, AX + JNC f64_skip + MOVL W_60+240(FP), CX + MOVL W_64+256(FP), DX + SHRL $0x19, DX + XORL DX, CX + ANDL $0x00000010, CX + CMPL CX, $0x00000000 + JNE f64_in + MOVL W_44+176(FP), CX + MOVL W_48+192(FP), DX + SHRL $0x19, DX + XORL DX, CX + ANDL $0x00000008, CX + CMPL CX, $0x00000000 + JNE f64_in + MOVL W_44+176(FP), CX + MOVL W_48+192(FP), DX + SHRL $0x19, DX + XORL DX, CX + ANDL $0x00000010, CX + CMPL CX, $0x00000000 + JNE f64_in + JMP f64_skip + +f64_in: + ANDL $0x7fffffff, AX + +f64_skip: +end: + MOVL AX, ret+320(FP) + RET diff --git a/vendor/github.com/pjbgf/sha1cd/ubc/check.go b/vendor/github.com/pjbgf/sha1cd/ubc/ubc_generic.go similarity index 99% rename from vendor/github.com/pjbgf/sha1cd/ubc/check.go rename to vendor/github.com/pjbgf/sha1cd/ubc/ubc_generic.go index 167a5558fd..ee95bd52d9 100644 --- a/vendor/github.com/pjbgf/sha1cd/ubc/check.go +++ b/vendor/github.com/pjbgf/sha1cd/ubc/ubc_generic.go @@ -25,7 +25,7 @@ type DvInfo struct { // for all listed DVs. It returns a dvmask where each bit belonging to a DV is set if all // unavoidable bitconditions for that DV have been met. // Thus, one needs to do the recompression check for each DV that has its bit set. -func CalculateDvMask(W [80]uint32) uint32 { +func CalculateDvMaskGeneric(W [80]uint32) uint32 { mask := uint32(0xFFFFFFFF) mask &= (((((W[44] ^ W[45]) >> 29) & 1) - 1) | ^(DV_I_48_0_bit | DV_I_51_0_bit | DV_I_52_0_bit | DV_II_45_0_bit | DV_II_46_0_bit | DV_II_50_0_bit | DV_II_51_0_bit)) mask &= (((((W[49] ^ W[50]) >> 29) & 1) - 1) | ^(DV_I_46_0_bit | DV_II_45_0_bit | DV_II_50_0_bit | DV_II_51_0_bit | DV_II_55_0_bit | DV_II_56_0_bit)) diff --git a/vendor/github.com/pjbgf/sha1cd/ubc/ubc_noasm.go b/vendor/github.com/pjbgf/sha1cd/ubc/ubc_noasm.go new file mode 100644 index 0000000000..48d6dff169 --- /dev/null +++ b/vendor/github.com/pjbgf/sha1cd/ubc/ubc_noasm.go @@ -0,0 +1,12 @@ +//go:build !amd64 || noasm || !gc +// +build !amd64 noasm !gc + +package ubc + +// Check takes as input an expanded message block and verifies the unavoidable bitconditions +// for all listed DVs. It returns a dvmask where each bit belonging to a DV is set if all +// unavoidable bitconditions for that DV have been met. +// Thus, one needs to do the recompression check for each DV that has its bit set. +func CalculateDvMask(W [80]uint32) uint32 { + return CalculateDvMaskGeneric(W) +} diff --git a/vendor/github.com/skeema/knownhosts/NOTICE b/vendor/github.com/skeema/knownhosts/NOTICE index a92cb34d67..224b202486 100644 --- a/vendor/github.com/skeema/knownhosts/NOTICE +++ b/vendor/github.com/skeema/knownhosts/NOTICE @@ -1,4 +1,4 @@ -Copyright 2024 Skeema LLC and the Skeema Knownhosts authors +Copyright 2025 Skeema LLC and the Skeema Knownhosts authors Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/vendor/github.com/skeema/knownhosts/README.md b/vendor/github.com/skeema/knownhosts/README.md index 046bc0edcb..170e04d140 100644 --- a/vendor/github.com/skeema/knownhosts/README.md +++ b/vendor/github.com/skeema/knownhosts/README.md @@ -116,7 +116,7 @@ config := &ssh.ClientConfig{ ## License -**Source code copyright 2024 Skeema LLC and the Skeema Knownhosts authors** +**Source code copyright 2025 Skeema LLC and the Skeema Knownhosts authors** ```text Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/vendor/golang.org/x/tools/cmd/stringer/stringer.go b/vendor/golang.org/x/tools/cmd/stringer/stringer.go deleted file mode 100644 index 7ff0ee8d0c..0000000000 --- a/vendor/golang.org/x/tools/cmd/stringer/stringer.go +++ /dev/null @@ -1,715 +0,0 @@ -// Copyright 2014 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. - -// Stringer is a tool to automate the creation of methods that satisfy the fmt.Stringer -// interface. Given the name of a (signed or unsigned) integer type T that has constants -// defined, stringer will create a new self-contained Go source file implementing -// -// func (t T) String() string -// -// The file is created in the same package and directory as the package that defines T. -// It has helpful defaults designed for use with go generate. -// -// Stringer works best with constants that are consecutive values such as created using iota, -// but creates good code regardless. In the future it might also provide custom support for -// constant sets that are bit patterns. -// -// For example, given this snippet, -// -// package painkiller -// -// type Pill int -// -// const ( -// Placebo Pill = iota -// Aspirin -// Ibuprofen -// Paracetamol -// Acetaminophen = Paracetamol -// ) -// -// running this command -// -// stringer -type=Pill -// -// in the same directory will create the file pill_string.go, in package painkiller, -// containing a definition of -// -// func (Pill) String() string -// -// That method will translate the value of a Pill constant to the string representation -// of the respective constant name, so that the call fmt.Print(painkiller.Aspirin) will -// print the string "Aspirin". -// -// Typically this process would be run using go generate, like this: -// -// //go:generate stringer -type=Pill -// -// If multiple constants have the same value, the lexically first matching name will -// be used (in the example, Acetaminophen will print as "Paracetamol"). -// -// With no arguments, it processes the package in the current directory. -// Otherwise, the arguments must name a single directory holding a Go package -// or a set of Go source files that represent a single Go package. -// -// The -type flag accepts a comma-separated list of types so a single run can -// generate methods for multiple types. The default output file is t_string.go, -// where t is the lower-cased name of the first type listed. It can be overridden -// with the -output flag. -// -// Types can also be declared in tests, in which case type declarations in the -// non-test package or its test variant are preferred over types defined in the -// package with suffix "_test". -// The default output file for type declarations in tests is t_string_test.go with t picked as above. -// -// The -linecomment flag tells stringer to generate the text of any line comment, trimmed -// of leading spaces, instead of the constant name. For instance, if the constants above had a -// Pill prefix, one could write -// -// PillAspirin // Aspirin -// -// to suppress it in the output. -// -// The -trimprefix flag specifies a prefix to remove from the constant names -// when generating the string representations. For instance, -trimprefix=Pill -// would be an alternative way to ensure that PillAspirin.String() == "Aspirin". -package main // import "golang.org/x/tools/cmd/stringer" - -import ( - "bytes" - "flag" - "fmt" - "go/ast" - "go/constant" - "go/format" - "go/token" - "go/types" - "log" - "os" - "path/filepath" - "sort" - "strings" - - "golang.org/x/tools/go/packages" -) - -var ( - typeNames = flag.String("type", "", "comma-separated list of type names; must be set") - output = flag.String("output", "", "output file name; default srcdir/_string.go") - trimprefix = flag.String("trimprefix", "", "trim the `prefix` from the generated constant names") - linecomment = flag.Bool("linecomment", false, "use line comment text as printed text when present") - buildTags = flag.String("tags", "", "comma-separated list of build tags to apply") -) - -// Usage is a replacement usage function for the flags package. -func Usage() { - fmt.Fprintf(os.Stderr, "Usage of stringer:\n") - fmt.Fprintf(os.Stderr, "\tstringer [flags] -type T [directory]\n") - fmt.Fprintf(os.Stderr, "\tstringer [flags] -type T files... # Must be a single package\n") - fmt.Fprintf(os.Stderr, "For more information, see:\n") - fmt.Fprintf(os.Stderr, "\thttps://pkg.go.dev/golang.org/x/tools/cmd/stringer\n") - fmt.Fprintf(os.Stderr, "Flags:\n") - flag.PrintDefaults() -} - -func main() { - log.SetFlags(0) - log.SetPrefix("stringer: ") - flag.Usage = Usage - flag.Parse() - if len(*typeNames) == 0 { - flag.Usage() - os.Exit(2) - } - types := strings.Split(*typeNames, ",") - var tags []string - if len(*buildTags) > 0 { - tags = strings.Split(*buildTags, ",") - } - - // We accept either one directory or a list of files. Which do we have? - args := flag.Args() - if len(args) == 0 { - // Default: process whole package in current directory. - args = []string{"."} - } - - // Parse the package once. - var dir string - // TODO(suzmue): accept other patterns for packages (directories, list of files, import paths, etc). - if len(args) == 1 && isDirectory(args[0]) { - dir = args[0] - } else { - if len(tags) != 0 { - log.Fatal("-tags option applies only to directories, not when files are specified") - } - dir = filepath.Dir(args[0]) - } - - // For each type, generate code in the first package where the type is declared. - // The order of packages is as follows: - // package x - // package x compiled for tests - // package x_test - // - // Each package pass could result in a separate generated file. - // These files must have the same package and test/not-test nature as the types - // from which they were generated. - // - // Types will be excluded when generated, to avoid repetitions. - pkgs := loadPackages(args, tags, *trimprefix, *linecomment, nil /* logf */) - sort.Slice(pkgs, func(i, j int) bool { - // Put x_test packages last. - iTest := strings.HasSuffix(pkgs[i].name, "_test") - jTest := strings.HasSuffix(pkgs[j].name, "_test") - if iTest != jTest { - return !iTest - } - - return len(pkgs[i].files) < len(pkgs[j].files) - }) - for _, pkg := range pkgs { - g := Generator{ - pkg: pkg, - } - - // Print the header and package clause. - g.Printf("// Code generated by \"stringer %s\"; DO NOT EDIT.\n", strings.Join(os.Args[1:], " ")) - g.Printf("\n") - g.Printf("package %s", g.pkg.name) - g.Printf("\n") - g.Printf("import \"strconv\"\n") // Used by all methods. - - // Run generate for types that can be found. Keep the rest for the remainingTypes iteration. - var foundTypes, remainingTypes []string - for _, typeName := range types { - values := findValues(typeName, pkg) - if len(values) > 0 { - g.generate(typeName, values) - foundTypes = append(foundTypes, typeName) - } else { - remainingTypes = append(remainingTypes, typeName) - } - } - if len(foundTypes) == 0 { - // This package didn't have any of the relevant types, skip writing a file. - continue - } - if len(remainingTypes) > 0 && output != nil && *output != "" { - log.Fatalf("cannot write to single file (-output=%q) when matching types are found in multiple packages", *output) - } - types = remainingTypes - - // Format the output. - src := g.format() - - // Write to file. - outputName := *output - if outputName == "" { - // Type names will be unique across packages since only the first - // match is picked. - // So there won't be collisions between a package compiled for tests - // and the separate package of tests (package foo_test). - outputName = filepath.Join(dir, baseName(pkg, foundTypes[0])) - } - err := os.WriteFile(outputName, src, 0o644) - if err != nil { - log.Fatalf("writing output: %s", err) - } - } - - if len(types) > 0 { - log.Fatalf("no values defined for types: %s", strings.Join(types, ",")) - } -} - -// baseName that will put the generated code together with pkg. -func baseName(pkg *Package, typename string) string { - suffix := "string.go" - if pkg.hasTestFiles { - suffix = "string_test.go" - } - return fmt.Sprintf("%s_%s", strings.ToLower(typename), suffix) -} - -// isDirectory reports whether the named file is a directory. -func isDirectory(name string) bool { - info, err := os.Stat(name) - if err != nil { - log.Fatal(err) - } - return info.IsDir() -} - -// Generator holds the state of the analysis. Primarily used to buffer -// the output for format.Source. -type Generator struct { - buf bytes.Buffer // Accumulated output. - pkg *Package // Package we are scanning. - - logf func(format string, args ...any) // test logging hook; nil when not testing -} - -func (g *Generator) Printf(format string, args ...any) { - fmt.Fprintf(&g.buf, format, args...) -} - -// File holds a single parsed file and associated data. -type File struct { - pkg *Package // Package to which this file belongs. - file *ast.File // Parsed AST. - // These fields are reset for each type being generated. - typeName string // Name of the constant type. - values []Value // Accumulator for constant values of that type. - - trimPrefix string - lineComment bool -} - -type Package struct { - name string - defs map[*ast.Ident]types.Object - files []*File - hasTestFiles bool -} - -// loadPackages analyzes the single package constructed from the patterns and tags. -// loadPackages exits if there is an error. -// -// Returns all variants (such as tests) of the package. -// -// logf is a test logging hook. It can be nil when not testing. -func loadPackages( - patterns, tags []string, - trimPrefix string, lineComment bool, - logf func(format string, args ...any), -) []*Package { - cfg := &packages.Config{ - Mode: packages.NeedName | packages.NeedTypes | packages.NeedTypesInfo | packages.NeedSyntax | packages.NeedFiles, - // Tests are included, let the caller decide how to fold them in. - Tests: true, - BuildFlags: []string{fmt.Sprintf("-tags=%s", strings.Join(tags, " "))}, - Logf: logf, - } - pkgs, err := packages.Load(cfg, patterns...) - if err != nil { - log.Fatal(err) - } - if len(pkgs) == 0 { - log.Fatalf("error: no packages matching %v", strings.Join(patterns, " ")) - } - - out := make([]*Package, len(pkgs)) - for i, pkg := range pkgs { - p := &Package{ - name: pkg.Name, - defs: pkg.TypesInfo.Defs, - files: make([]*File, len(pkg.Syntax)), - } - - for j, file := range pkg.Syntax { - p.files[j] = &File{ - file: file, - pkg: p, - - trimPrefix: trimPrefix, - lineComment: lineComment, - } - } - - // Keep track of test files, since we might want to generated - // code that ends up in that kind of package. - // Can be replaced once https://go.dev/issue/38445 lands. - for _, f := range pkg.GoFiles { - if strings.HasSuffix(f, "_test.go") { - p.hasTestFiles = true - break - } - } - - out[i] = p - } - return out -} - -func findValues(typeName string, pkg *Package) []Value { - values := make([]Value, 0, 100) - for _, file := range pkg.files { - // Set the state for this run of the walker. - file.typeName = typeName - file.values = nil - if file.file != nil { - ast.Inspect(file.file, file.genDecl) - values = append(values, file.values...) - } - } - return values -} - -// generate produces the String method for the named type. -func (g *Generator) generate(typeName string, values []Value) { - // Generate code that will fail if the constants change value. - g.Printf("func _() {\n") - g.Printf("\t// An \"invalid array index\" compiler error signifies that the constant values have changed.\n") - g.Printf("\t// Re-run the stringer command to generate them again.\n") - g.Printf("\tvar x [1]struct{}\n") - for _, v := range values { - g.Printf("\t_ = x[%s - %s]\n", v.originalName, v.str) - } - g.Printf("}\n") - runs := splitIntoRuns(values) - // The decision of which pattern to use depends on the number of - // runs in the numbers. If there's only one, it's easy. For more than - // one, there's a tradeoff between complexity and size of the data - // and code vs. the simplicity of a map. A map takes more space, - // but so does the code. The decision here (crossover at 10) is - // arbitrary, but considers that for large numbers of runs the cost - // of the linear scan in the switch might become important, and - // rather than use yet another algorithm such as binary search, - // we punt and use a map. In any case, the likelihood of a map - // being necessary for any realistic example other than bitmasks - // is very low. And bitmasks probably deserve their own analysis, - // to be done some other day. - switch { - case len(runs) == 1: - g.buildOneRun(runs, typeName) - case len(runs) <= 10: - g.buildMultipleRuns(runs, typeName) - default: - g.buildMap(runs, typeName) - } -} - -// splitIntoRuns breaks the values into runs of contiguous sequences. -// For example, given 1,2,3,5,6,7 it returns {1,2,3},{5,6,7}. -// The input slice is known to be non-empty. -func splitIntoRuns(values []Value) [][]Value { - // We use stable sort so the lexically first name is chosen for equal elements. - sort.Stable(byValue(values)) - // Remove duplicates. Stable sort has put the one we want to print first, - // so use that one. The String method won't care about which named constant - // was the argument, so the first name for the given value is the only one to keep. - // We need to do this because identical values would cause the switch or map - // to fail to compile. - j := 1 - for i := 1; i < len(values); i++ { - if values[i].value != values[i-1].value { - values[j] = values[i] - j++ - } - } - values = values[:j] - runs := make([][]Value, 0, 10) - for len(values) > 0 { - // One contiguous sequence per outer loop. - i := 1 - for i < len(values) && values[i].value == values[i-1].value+1 { - i++ - } - runs = append(runs, values[:i]) - values = values[i:] - } - return runs -} - -// format returns the gofmt-ed contents of the Generator's buffer. -func (g *Generator) format() []byte { - src, err := format.Source(g.buf.Bytes()) - if err != nil { - // Should never happen, but can arise when developing this code. - // The user can compile the output to see the error. - log.Printf("warning: internal error: invalid Go generated: %s", err) - log.Printf("warning: compile the package to analyze the error") - return g.buf.Bytes() - } - return src -} - -// Value represents a declared constant. -type Value struct { - originalName string // The name of the constant. - name string // The name with trimmed prefix. - // The value is stored as a bit pattern alone. The boolean tells us - // whether to interpret it as an int64 or a uint64; the only place - // this matters is when sorting. - // Much of the time the str field is all we need; it is printed - // by Value.String. - value uint64 // Will be converted to int64 when needed. - signed bool // Whether the constant is a signed type. - str string // The string representation given by the "go/constant" package. -} - -func (v *Value) String() string { - return v.str -} - -// byValue lets us sort the constants into increasing order. -// We take care in the Less method to sort in signed or unsigned order, -// as appropriate. -type byValue []Value - -func (b byValue) Len() int { return len(b) } -func (b byValue) Swap(i, j int) { b[i], b[j] = b[j], b[i] } -func (b byValue) Less(i, j int) bool { - if b[i].signed { - return int64(b[i].value) < int64(b[j].value) - } - return b[i].value < b[j].value -} - -// genDecl processes one declaration clause. -func (f *File) genDecl(node ast.Node) bool { - decl, ok := node.(*ast.GenDecl) - if !ok || decl.Tok != token.CONST { - // We only care about const declarations. - return true - } - // The name of the type of the constants we are declaring. - // Can change if this is a multi-element declaration. - typ := "" - // Loop over the elements of the declaration. Each element is a ValueSpec: - // a list of names possibly followed by a type, possibly followed by values. - // If the type and value are both missing, we carry down the type (and value, - // but the "go/types" package takes care of that). - for _, spec := range decl.Specs { - vspec := spec.(*ast.ValueSpec) // Guaranteed to succeed as this is CONST. - if vspec.Type == nil && len(vspec.Values) > 0 { - // "X = 1". With no type but a value. If the constant is untyped, - // skip this vspec and reset the remembered type. - typ = "" - - // If this is a simple type conversion, remember the type. - // We don't mind if this is actually a call; a qualified call won't - // be matched (that will be SelectorExpr, not Ident), and only unusual - // situations will result in a function call that appears to be - // a type conversion. - ce, ok := vspec.Values[0].(*ast.CallExpr) - if !ok { - continue - } - id, ok := ce.Fun.(*ast.Ident) - if !ok { - continue - } - typ = id.Name - } - if vspec.Type != nil { - // "X T". We have a type. Remember it. - ident, ok := vspec.Type.(*ast.Ident) - if !ok { - continue - } - typ = ident.Name - } - if typ != f.typeName { - // This is not the type we're looking for. - continue - } - // We now have a list of names (from one line of source code) all being - // declared with the desired type. - // Grab their names and actual values and store them in f.values. - for _, name := range vspec.Names { - if name.Name == "_" { - continue - } - // This dance lets the type checker find the values for us. It's a - // bit tricky: look up the object declared by the name, find its - // types.Const, and extract its value. - obj, ok := f.pkg.defs[name] - if !ok { - log.Fatalf("no value for constant %s", name) - } - info := obj.Type().Underlying().(*types.Basic).Info() - if info&types.IsInteger == 0 { - log.Fatalf("can't handle non-integer constant type %s", typ) - } - value := obj.(*types.Const).Val() // Guaranteed to succeed as this is CONST. - if value.Kind() != constant.Int { - log.Fatalf("can't happen: constant is not an integer %s", name) - } - i64, isInt := constant.Int64Val(value) - u64, isUint := constant.Uint64Val(value) - if !isInt && !isUint { - log.Fatalf("internal error: value of %s is not an integer: %s", name, value.String()) - } - if !isInt { - u64 = uint64(i64) - } - v := Value{ - originalName: name.Name, - value: u64, - signed: info&types.IsUnsigned == 0, - str: value.String(), - } - if c := vspec.Comment; f.lineComment && c != nil && len(c.List) == 1 { - v.name = strings.TrimSpace(c.Text()) - } else { - v.name = strings.TrimPrefix(v.originalName, f.trimPrefix) - } - f.values = append(f.values, v) - } - } - return false -} - -// Helpers - -// usize returns the number of bits of the smallest unsigned integer -// type that will hold n. Used to create the smallest possible slice of -// integers to use as indexes into the concatenated strings. -func usize(n int) int { - switch { - case n < 1<<8: - return 8 - case n < 1<<16: - return 16 - default: - // 2^32 is enough constants for anyone. - return 32 - } -} - -// declareIndexAndNameVars declares the index slices and concatenated names -// strings representing the runs of values. -func (g *Generator) declareIndexAndNameVars(runs [][]Value, typeName string) { - var indexes, names []string - for i, run := range runs { - index, name := g.createIndexAndNameDecl(run, typeName, fmt.Sprintf("_%d", i)) - if len(run) != 1 { - indexes = append(indexes, index) - } - names = append(names, name) - } - g.Printf("const (\n") - for _, name := range names { - g.Printf("\t%s\n", name) - } - g.Printf(")\n\n") - - if len(indexes) > 0 { - g.Printf("var (") - for _, index := range indexes { - g.Printf("\t%s\n", index) - } - g.Printf(")\n\n") - } -} - -// declareIndexAndNameVar is the single-run version of declareIndexAndNameVars -func (g *Generator) declareIndexAndNameVar(run []Value, typeName string) { - index, name := g.createIndexAndNameDecl(run, typeName, "") - g.Printf("const %s\n", name) - g.Printf("var %s\n", index) -} - -// createIndexAndNameDecl returns the pair of declarations for the run. The caller will add "const" and "var". -func (g *Generator) createIndexAndNameDecl(run []Value, typeName string, suffix string) (string, string) { - b := new(bytes.Buffer) - indexes := make([]int, len(run)) - for i := range run { - b.WriteString(run[i].name) - indexes[i] = b.Len() - } - nameConst := fmt.Sprintf("_%s_name%s = %q", typeName, suffix, b.String()) - nameLen := b.Len() - b.Reset() - fmt.Fprintf(b, "_%s_index%s = [...]uint%d{0, ", typeName, suffix, usize(nameLen)) - for i, v := range indexes { - if i > 0 { - fmt.Fprintf(b, ", ") - } - fmt.Fprintf(b, "%d", v) - } - fmt.Fprintf(b, "}") - return b.String(), nameConst -} - -// declareNameVars declares the concatenated names string representing all the values in the runs. -func (g *Generator) declareNameVars(runs [][]Value, typeName string, suffix string) { - g.Printf("const _%s_name%s = \"", typeName, suffix) - for _, run := range runs { - for i := range run { - g.Printf("%s", run[i].name) - } - } - g.Printf("\"\n") -} - -// buildOneRun generates the variables and String method for a single run of contiguous values. -func (g *Generator) buildOneRun(runs [][]Value, typeName string) { - values := runs[0] - g.Printf("\n") - g.declareIndexAndNameVar(values, typeName) - g.Printf(stringOneRun, typeName, values[0].String()) -} - -// Arguments to format are: -// -// [1]: type name -// [2]: lowest defined value for type, as a string -const stringOneRun = `func (i %[1]s) String() string { - idx := int(i) - %[2]s - if i < %[2]s || idx >= len(_%[1]s_index)-1 { - return "%[1]s(" + strconv.FormatInt(int64(i), 10) + ")" - } - return _%[1]s_name[_%[1]s_index[idx] : _%[1]s_index[idx+1]] -} -` - -// buildMultipleRuns generates the variables and String method for multiple runs of contiguous values. -// For this pattern, a single Printf format won't do. -func (g *Generator) buildMultipleRuns(runs [][]Value, typeName string) { - g.Printf("\n") - g.declareIndexAndNameVars(runs, typeName) - g.Printf("func (i %s) String() string {\n", typeName) - g.Printf("\tswitch {\n") - for i, values := range runs { - if len(values) == 1 { - g.Printf("\tcase i == %s:\n", &values[0]) - g.Printf("\t\treturn _%s_name_%d\n", typeName, i) - continue - } - if values[0].value == 0 && !values[0].signed { - // For an unsigned lower bound of 0, "0 <= i" would be redundant. - g.Printf("\tcase i <= %s:\n", &values[len(values)-1]) - } else { - g.Printf("\tcase %s <= i && i <= %s:\n", &values[0], &values[len(values)-1]) - } - if values[0].value != 0 { - g.Printf("\t\ti -= %s\n", &values[0]) - } - g.Printf("\t\treturn _%s_name_%d[_%s_index_%d[i]:_%s_index_%d[i+1]]\n", - typeName, i, typeName, i, typeName, i) - } - g.Printf("\tdefault:\n") - g.Printf("\t\treturn \"%s(\" + strconv.FormatInt(int64(i), 10) + \")\"\n", typeName) - g.Printf("\t}\n") - g.Printf("}\n") -} - -// buildMap handles the case where the space is so sparse a map is a reasonable fallback. -// It's a rare situation but has simple code. -func (g *Generator) buildMap(runs [][]Value, typeName string) { - g.Printf("\n") - g.declareNameVars(runs, typeName, "") - g.Printf("\nvar _%s_map = map[%s]string{\n", typeName, typeName) - n := 0 - for _, values := range runs { - for _, value := range values { - g.Printf("\t%s: _%s_name[%d:%d],\n", &value, typeName, n, n+len(value.name)) - n += len(value.name) - } - } - g.Printf("}\n\n") - g.Printf(stringMap, typeName) -} - -// Argument to format is the type name. -const stringMap = `func (i %[1]s) String() string { - if str, ok := _%[1]s_map[i]; ok { - return str - } - return "%[1]s(" + strconv.FormatInt(int64(i), 10) + ")" -} -` diff --git a/vendor/modules.txt b/vendor/modules.txt index 39392eb712..116b081dc3 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -28,8 +28,8 @@ github.com/Azure/go-ansiterm github.com/Azure/go-ansiterm/winterm # github.com/BurntSushi/toml v1.3.2 ## explicit; go 1.16 -# github.com/Microsoft/go-winio v0.6.1 -## explicit; go 1.17 +# github.com/Microsoft/go-winio v0.6.2 +## explicit; go 1.21 github.com/Microsoft/go-winio github.com/Microsoft/go-winio/internal/fs github.com/Microsoft/go-winio/internal/socket @@ -37,7 +37,7 @@ github.com/Microsoft/go-winio/internal/stringbuffer github.com/Microsoft/go-winio/pkg/guid # github.com/Netflix/go-expect v0.0.0-20201125194554-85d881c3777e ## explicit; go 1.13 -# github.com/ProtonMail/go-crypto v1.1.3 +# github.com/ProtonMail/go-crypto v1.1.6 ## explicit; go 1.17 github.com/ProtonMail/go-crypto/bitcurves github.com/ProtonMail/go-crypto/brainpool @@ -287,7 +287,7 @@ github.com/containerd/console # github.com/creack/pty v1.1.11 ## explicit; go 1.13 github.com/creack/pty -# github.com/cyphar/filepath-securejoin v0.3.6 +# github.com/cyphar/filepath-securejoin v0.4.1 ## explicit; go 1.18 github.com/cyphar/filepath-securejoin # github.com/dave/jennifer v0.18.0 @@ -333,7 +333,7 @@ github.com/go-git/gcfg github.com/go-git/gcfg/scanner github.com/go-git/gcfg/token github.com/go-git/gcfg/types -# github.com/go-git/go-billy/v5 v5.6.1 +# github.com/go-git/go-billy/v5 v5.6.2 ## explicit; go 1.21 github.com/go-git/go-billy/v5 github.com/go-git/go-billy/v5/helper/chroot @@ -341,8 +341,8 @@ github.com/go-git/go-billy/v5/helper/polyfill github.com/go-git/go-billy/v5/memfs github.com/go-git/go-billy/v5/osfs github.com/go-git/go-billy/v5/util -# github.com/go-git/go-git/v5 v5.13.1 -## explicit; go 1.21 +# github.com/go-git/go-git/v5 v5.16.5 +## explicit; go 1.24.0 github.com/go-git/go-git/v5 github.com/go-git/go-git/v5/config github.com/go-git/go-git/v5/internal/path_util @@ -438,8 +438,8 @@ github.com/go-stack/stack # github.com/gofrs/flock v0.8.1 ## explicit github.com/gofrs/flock -# github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da -## explicit +# github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 +## explicit; go 1.20 github.com/golang/groupcache/lru # github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99 ## explicit; go 1.14 @@ -643,8 +643,8 @@ github.com/pierrec/lz4/v4/internal/lz4block github.com/pierrec/lz4/v4/internal/lz4errors github.com/pierrec/lz4/v4/internal/lz4stream github.com/pierrec/lz4/v4/internal/xxh32 -# github.com/pjbgf/sha1cd v0.3.0 -## explicit; go 1.19 +# github.com/pjbgf/sha1cd v0.3.2 +## explicit; go 1.21 github.com/pjbgf/sha1cd github.com/pjbgf/sha1cd/internal github.com/pjbgf/sha1cd/ubc @@ -683,8 +683,8 @@ github.com/shirou/gopsutil/v3/process # github.com/shoenig/go-m1cpu v0.1.6 ## explicit; go 1.20 github.com/shoenig/go-m1cpu -# github.com/skeema/knownhosts v1.3.0 -## explicit; go 1.17 +# github.com/skeema/knownhosts v1.3.1 +## explicit; go 1.22 github.com/skeema/knownhosts # github.com/skratchdot/open-golang v0.0.0-20190104022628-a2dfa6d0dab6 ## explicit @@ -848,7 +848,6 @@ golang.org/x/text/width golang.org/x/time/rate # golang.org/x/tools v0.38.0 ## explicit; go 1.24.0 -golang.org/x/tools/cmd/stringer golang.org/x/tools/go/ast/edge golang.org/x/tools/go/ast/inspector golang.org/x/tools/go/gcexportdata